Cuando trabajamos con formularios InfoPath y estos los tenemos que leer programáticamente desde un flujo de trabajo construido con Visual Studio y hospedado sobre SharePoint tenemos múltiples alternativas para manipularlos.
Alternativa 1: Usar una clase Stream y XmlDocument
SPFile file = workflowProperties.Item.File; if (file.Exists) { Stream binFile = file.OpenBinaryStream(); XmlDocument doc = new XmlDocument(); doc.Load(binFile); XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-06-18T06:49:06"); this.info = doc.SelectSingleNode("/my:misCampos/my:solicitudNumber", nsmgr).InnerText; binFile.Dispose(); }
Esta alternativa nos da acceso a la información mediante un XmlDocument. Se tiene que conocer el esquema y mediante rutas XPath accedemos a sus miembros. Ademas hay que realizar la conversión de tipos de forma explicita.
Alternativa 2: Usar un serializador y deserializador
Debido a que nuestros formularios InfoPath hacen uso del estándar XML utilizamos el comando xsd del .NET Framework nos permite leer el esquema y generar el código de una clase que sirve como enlace entre el archivo XML y un objeto .NET instanciado. Para poder implementar esta técnica debemos de obtener el xsd de nuestro InfoPath, para lograrlo debemos de guardarlo y utilizar la opción de extraer los archivos del InfoPath “extract form files” ubicada en el menú “File”. Esto nos guarda en una carpeta los archivos que constituyen nuestro InfoPath, entre ellos myschema.xsd.
Después desde nuestra consola de comandos de Visual Studio invocamos la instrucción:
Y con esto tenemos toda una clase “myschema.cs” que representa el esquema de nuestro InfoPath. Esta clase hay que agregarla al Visual Studio en nuestro proyecto y ahora si mediante serializacion podemos transformar un archivo InfoPath a un objeto instanciado. El siguiente codigo muestra como obtener una instancia de la clase que representa la forma de iniciacion de un flujo de trabajo. este codigo puede ir dentro de nuestra actividad OnWorkflowActivated
XmlSerializer serializer = new XmlSerializer(typeof(myFields)); XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(workflowProperties.InitiationData)); myFields initForm = (myFields)serializer.Deserialize(reader);
Nos apoyamos de los siguientes metodos concretos:
private myFields DeserializeFormData(string xmlString) { using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString))) { XmlSerializer serializer = new XmlSerializer(typeof(myFields)); myFields data = (myFields)serializer.Deserialize(stream); return data; } } private string SerializeFormData(ModificationForm form) { using (MemoryStream stream = new MemoryStream()) { XmlSerializer serializer = new XmlSerializer(typeof(myFields)); serializer.Serialize(stream, form); return Encoding.UTF8.GetString(stream.GetBuffer()); } }
Esta alternativa resulta interesante ya que el xsd genera la clase que realizar las transformaciones de datos complejos, esto quiere decir que en caso de utilizar el Contact Selector dentro de nuestro formulario el xsd lo soporta y nos genera las propiedades correspondientes para manejar una estructura de este tipo haciéndonos la vida mucho más fácil a la hora de leer tipos de datos persona. El unico problema es que en caso de cambiar algun campo dentro de nuestro InfoPath hay que de neuvo generar la clase correspondiente al esquema e importarlo de nuevo a nuestro proyecto.
Alternativa 3: Usar la clase Form
Cuando utilizamos flujos de trabajo hospedados sobre Office SharePoint Server 2007 podemos hacer la referencia a la clase Forms. Esta clase cuenta con métodos auxiliares que nos facilitan la transformación y manejo de datos entre otros. Tenemos por ahí el método XmlToHastable que nos regresa una coleccion de tipo HastTable donde el índice representa cada campo de nuestro formulario InfoPath.
Hashtable formData = Form.XmlToHashtable(workflowProperties.AssociationData);
aprobadores = Contact.ToContacts((string)formData["aprobadores"], workflowProperties.Web); dias = (string)formData["dias"];
Bien pues estas son algunas de las alternativas disponibles para la manipulación programática de formularios InfoPath bajo contexto de ejecución hospedado sobre SharePoint.
Hola Haaron, muy buena contribución.
Tengo la siguiente duda:
Puedo generar dinámicamente formularios con infopath desde un front para el usuario final, e ir guardando esas definiciones, y que ese formulario guarde su respectivo esquema?