jueves, 19 de noviembre de 2009

InfoPath cannot start Microsoft Visual Studio Tools for Applications

Cuando trate de programar un boton de un formulario infopath obtuve este error


Ocurre porque al momento de instalar el Infopath 2007 dejamos la configuracion por defecto, esta no incluye VSTA (Visual Studio Tools for Applications)
Para solucionarlo solo debemos instalar este complemento: Colocar el CD del office seleccionar agregar o quitar complementos y seleccionar la opcion de VSTA, tal como se muestra en la imagen.

Esto soluciona el problema.

viernes, 13 de noviembre de 2009

Javascript DOM insertAfter

Las funciones de JavaScript DOM no incluyen una función de InsertAfter.

function insertAfter( referenceNode, newNode )
{

referenceNode.parentNode.insertBefore( newNode, referenceNode.nextSibling );

}


Ver pagina del Autor

domingo, 1 de noviembre de 2009

WebPart: People Selector

Sharepoint provee por defecto muchos WebPart tipo filtro, pero tengo la impresion de que olvidaron uno importante, un filtro que permita seleccionar personas o grupos finalmente que esto sea configurable, pero vamos por parte, inicialmente que permita seleccionar una persona o grupo, pero ademas de poder seleccionarlo que permita conectar con otros Webpart.
El primer obstaculo es conseguir una interface muy similar a la que el usuario esta acostumbrado: tenemos 2 opciones:

Contact Selector


People Selector


De ambas opciones yo prefiero el people selector, porque ya nativo del Sharepoint.
Haremos un webpart, usando el template que nos proporciona WSPBuilder, herramienta que podemos descargar de codeplex.
Crearemos un proyecto Provider que sera nuestro People Selector y un Consumer que solo sera demostrativo.


using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI.WebControls;
using System.Collections.ObjectModel;
using Microsoft.SharePoint.WebControls;

namespace FilterProvider
{
[Guid("5a74bba3-4f58-46b2-a988-401ecc3ecf58")]
public class FilterProvider : Microsoft.SharePoint.WebPartPages.WebPart, ITransformableFilterValues
{
private bool _error = false;
private PeopleEditor _PeopleEditor;
private Button _Button;

public FilterProvider()
{
this.ExportMode = WebPartExportMode.All;
}

///
/// Create all your controls here for rendering.
/// Try to avoid using the RenderWebPart() method.
///

protected override void CreateChildControls()
{
if (!_error)
{
try
{

base.CreateChildControls();
_PeopleEditor = new PeopleEditor();
_PeopleEditor.MultiSelect = true;
_PeopleEditor.AutoPostBack = false;
_Button = new Button();
_Button.Text = "Consultar Datos";
_Button.Click += new EventHandler(_Button_Click);
this.Controls.Add(_PeopleEditor);
this.Controls.Add(_Button);

// Your code here...
this.Controls.Add(new LiteralControl(this.MyProperty));
}
catch (Exception ex)
{
HandleException(ex);
}
}
}

///
/// Ensures that the CreateChildControls() is called before events.
/// Use CreateChildControls() to create your controls.
///

///


protected void _Button_Click(object sender, EventArgs e)
{
List people = new List();
for (int i = 0; i <>
/// Clear all child controls and add an error message for display.
///

///
private void HandleException(Exception ex)
{
this._error = true;
this.Controls.Clear();
this.Controls.Add(new LiteralControl(ex.Message));
}

[ConnectionProvider("People", "UniqueIDForPeopleConnection", AllowsMultipleConnections = true)]
public ITransformableFilterValues SetConnection() { return this; }

#region Miembros de ITransformableFilterValues

bool ITransformableFilterValues.AllowAllValue
{
get { return true; }
}

bool ITransformableFilterValues.AllowEmptyValue
{
get { return false; }
}

bool ITransformableFilterValues.AllowMultipleValues
{
get { return true; }
}

string ITransformableFilterValues.ParameterName
{
get { return "People"; }
}

System.Collections.ObjectModel.ReadOnlyCollection ITransformableFilterValues.ParameterValues
{
get {

EnsureChildControls();
List people = new List();
for (int i = 0; i <> result = new ReadOnlyCollection(people);
return result;

}
}
#endregion
}
}

De todo esto lo mas interensate es:
017 private PeopleEditor _PeopleEditor;
Que nos permite reutilizar visual y funcionalmente el control People Editor que nos proporciona Sharepoint para sus columnas tipo Person/Group

077 [ConnectionProvider("People", "UniqueIDForPeopleConnection", AllowsMultipleConnections = true)]
078 public ITransformableFilterValues SetConnection() { return this; }

102 System.Collections.ObjectModel.ReadOnlyCollection ITransformableFilterValues.ParameterValues
Estas funciones permite dar la funcionalidad de Filtro a nuestro WebPart.
En este caso hemos hecho un filtro multi valores, segun las necesidades puede ser modificado.
Ahora el Consumer.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebPartPages;

namespace FilterConsumer
{
[Guid("b9e3fb99-7c6b-4386-b7c1-5fcc37f01740")]
public class FilterConsumer : Microsoft.SharePoint.WebPartPages.WebPart
{
private bool _error = false;
private List _filterProviders;
private List FilterProviders {
get
{
return _filterProviders;
}
}

public FilterConsumer()
{
_filterProviders = new List();
}

///
/// Create all your controls here for rendering.
/// Try to avoid using the RenderWebPart() method.
///

protected override void CreateChildControls()
{
if (!_error)
{
try
{

base.CreateChildControls();

// Your code here...
this.Controls.Add(new LiteralControl(this.MyProperty));
}
catch (Exception ex)
{
HandleException(ex);
}
}
}

///
/// Ensures that the CreateChildControls() is called before events.
/// Use CreateChildControls() to create your controls.
///

///
protected override void OnLoad(EventArgs e)
{
if (!_error)
{
try
{
base.OnLoad(e);
this.EnsureChildControls();

// Your code here...
}
catch (Exception ex)
{
HandleException(ex);
}
}
}

///
/// Clear all child controls and add an error message for display.
///

///
private void HandleException(Exception ex)
{
this._error = true;
this.Controls.Clear();
this.Controls.Add(new LiteralControl(ex.Message));
}

protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
foreach (IFilterValues filter in FilterProviders)
{ writer.WriteLine(string.Format("Parameter: {0}
", filter.ParameterName));
if (filter.ParameterValues != null)
{
foreach (string value in filter.ParameterValues)
if (!string.IsNullOrEmpty(value))
writer.WriteLine(string.Format(" value: {0}
", value));
}
}
base.Render(writer);
}

[ConnectionConsumer("filter", "UniqueIDForConsumer", AllowsMultipleConnections = true)]
public void SetFilter(IFilterValues filterValues) {
if (filterValues != null) {
EnsureChildControls();
List parameters = new List();
parameters.Add(new ConsumerParameter("People", ConsumerParameterCapabilities.SupportsMultipleValues | ConsumerParameterCapabilities.SupportsAllValue));
//parameters.Add(new ConsumerParameter("Status", ConsumerParameterCapabilities.SupportsMultipleValues | ConsumerParameterCapabilities.SupportsAllValue));
filterValues.SetConsumerParameters(new System.Collections.ObjectModel.ReadOnlyCollection(parameters));
this.FilterProviders.Add(filterValues);
}
}
}
}

De igual manera tenemos que recuperar los datos que el provider nos envia.
100 [ConnectionConsumer("filter", "UniqueIDForConsumer", AllowsMultipleConnections = true)]
101 public void SetFilter(IFilterValues filterValues)

Finalmente deberiamos obtener algo como esto:

miércoles, 28 de octubre de 2009

Error: No se puede establecer una relación de confianza para el canal seguro SSL/TLS

Hace unos dias, empezamos los trabajos de construccion para un proyecto en que estoy, basicamente, aplicaciones que se ejecutaran sobre un entorno HTTPS y tuvimos un problema al tratar de acceder a una lista del Sharepoint que se encuentra en ese Site que trabaja con certificados.
El Error que obteniamos era el siguiente

System.Net.WebException: Se ha terminado la conexión: No se puede establecer una relación de confianza para el canal seguro SSL/TLS. --->
System.Security.Authentication.AuthenticationException: El certificado remoto no es válido según el procedimiento de validación.

Este es el codigo que yo uso para acceder a una lista y sacar sus valores:

XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
viewFields.InnerXml = "";
portal.Lists listService = null;
listService = new portal.Lists();
listService.Credentials = new System.Net.NetworkCredential("user", "password", "dominio");
listService.PreAuthenticate = true;
string listGuid = (string)"{AE348D4B-D88C-46B3-A809-B4663C4C7CB0}";
XmlNode itemCollection = listService.GetListItems(listGuid, string.Empty, null, viewFields, "0", null, string.Empty);
return itemCollection;


Para esto portal es un referencia Web al webservice del Sharepoint.
Algo como esto: https://MyServer/_vti_bin/lists.asmx


Bueno sin mas vueltas que dar, agreguemos esta linea

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
CredentialCache cache = new CredentialCache();



Este codigo se coloca antes de hacer una llamada a webservices.
Ademas debemos agregar es funcion, al agregar debemos agrregar algunos imports.

public static bool ValidateServerCertificate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}



Espero que esto soluciona sus problemas.
Saludos

lunes, 19 de octubre de 2009

Event ID: 5343 (One of its dependencies. The system cannot find the file specified)

Escenario:
Se implemento un workFlow con 2 Formularios infopath, en el servidor de desarrollo este error no se mostraba, pero al pasar a produccion empezo a lanzar este error.

Detalle:
Event Type: Error
Event Source: Office SharePoint Server
Event Category: Forms Services Runtime - Business Logic
Event ID: 5343
Date: 7/21/2009
Time: 2:12:39 PM
User: N/A
Computer: PC-Marco
Description:
An exception occurred during loading of business logic. (User: Dominio\Mdiaz, Form Name: SCWFPuestoAprobacionTaskForm0, IP: , Request: http://Server2003/_layouts/WrkTaskIP.aspx?List=xxxxxx-xxxx-xxxx-xxxx-xxxxxxx&ID=225&Source=http://Server2003/Site/_layouts/WrkStat.aspx?List=%xxxxxxx%xxxxxx%xxxxx%xxxxxx%xxxxxxxx%xxxx&WorkflowInstanceID=%xxxxxx%xxxxx%xxxxx%xxxx%xxxxxx%xxxx, Form ID: urn:schemas-microsoft-com:office:infopath:SCWFPuestoAprobacionTaskForm0:-myXSD-2009-06-25T14-20-49, Type: FileNotFoundException, Exception Message: Could not load file or assembly 'file:///C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\Template\Features\SCWFPuestoAprobacion\Forms\SCWFPuestoTaskForm0.dll' or one of its dependencies. The system cannot find the file specified.)

Solucion: En este caso lo mejor es buscar los arhivos xsn ubicados en C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\Template\Features\NombreWorkFlow, y sacar la DLL que esta dentro de ellos, para conseguir esto cambiar la extension de XSN a RAR, extrar la DLL que lleva el mismo nombre del Archivo actual, cambiar la extension de RAR a XSN y listo, el problema se soluciona.

Espero sea de utilidad.

Microsoft.SharePoint.SPUser is not marked as serializable

Escenaro: Este es un error muy interesante.
Se presento en un WorkFlow muy simple, donde en el evento load del WorkFlow se guardaba los datos del usuario al que se le estaba asignado la tarea, para poder usarlo al final del proceso, los datos del usuario eran guardados en un SPUser.

Detalle :

Type 'Microsoft.SharePoint.SPUser' in Assembly 'Microsoft.SharePoint,
Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' is not
marked as serializable. Type 'Microsoft.SharePoint.SPUser' in Assembly
'Microsoft.SharePoint, Version=12.0.0.0

Solucion: Esto pasa cuando se hace public un variable del tipo SPUser o SPListItem. En el proceso de Hidratacion/Desidratacion estos tipos se vuelven no serializables. Es Preferible crear una clase alterna a estos objetos y usarlos, tomando las consideraciones necesarias para poder serializarlas, como contructor vacio por ejemplo.
Espero les sea de ayuda.

Event ID: 5343 ('Microsoft.SharePoint.dll' or one of its dependencies. The system cannot find the file specified)

Escenario: Este error se presento cuando se implemento un formalario infopath con codigo personalizado donde se agrego como regerencia Sharepoint.dll que nos permite acceder a los datos de Lista, Librerias y otros recursos de Sharepoint.

Detalle:

Event Type: Error
Event Source: Office SharePoint Server
Event Category: Forms Services Runtime - Business Logic
Event ID: 5343
Date: 7/17/2009
Time: 11:14:07 AM
User: N/A
Computer: PC-Marco
Description:
An exception occurred during loading of business logic. (User: Dominio\Mdiaz, Form Name: SCWFPuestoAprobacionAssociationForm, IP: , Request: http://Server2003/_layouts/CstWrkflIP.aspx?List={xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx}, Form ID: urn:schemas-microsoft-com:office:infopath:SCWFPuestoAprobacionAssociationForm:-myXSD-2009-07-17T15-36-56, Type: FileNotFoundException, Exception Message: Could not load file or assembly 'file:///C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\Template\Features\SCWFPuestoAprobacion\Forms\Microsoft.SharePoint.dll' or one of its dependencies. The system cannot find the file specified.)

Solucion:
Cuando agregemos la DLL debemos asegurarnos de poner Copy Local = False.
Tal como se muestran las imagenes.




Event ID: 5337

Este error se presento en un formulario infopath que es usado como Form de Instanciacion de un WorkFlow.

Event Type: Warning
Event Source: Office SharePoint Server
Event Category: Forms Services Runtime - Business Logic
Event ID: 5337
Date: 7/16/2009
Time: 4:22:11 PM
User: N/A
Computer: PC-Marco
Description:
Business logic failed due to an exception. (User: Dominio\mdiaz, Form Name: SCWFPuestoAprobacionInstantiationForm, IP: , Request: http://Server2003/_layouts/IniWrkflIP.aspx?List=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx&ID=xx&TemplateID={xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx}&Source=http://Server2003/Site/Lists/Lista/AllItems.aspx, Form ID: urn:schemas-microsoft-com:office:infopath:SCWFPuestoAprobacionInstantiationForm:-myXSD-2009-06-25T14-14-04, Type: SecurityException, Exception Message: Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' failed.)

Solucion:
Deben de configurarse el formulario como FULL TRUST, tal como se muestra en la imagen