InfoPath Forms Services and the xsi:nil in code behind


October 25, 2013 - 12:27, by Steven Van de Craen - 1 Comments

Yesterday I had the requirement to programmatically add and remove the xsi:nil attribute from an InfoPath 2010 browser form hosted in InfoPath Forms Services in SharePoint 2010.

There are several solutions for adding and removing xsi:nil to be found on the internet, but I’ve found only one that works in both browser and InfoPath client forms, and that’s by replacing the node’s OuterXml.

public const string NIL_PREFIX = "xsi";
public const string NIL_LOCALNAME = "nil";
public const string NIL_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance";
        
public static void RemoveNil(XPathNavigator node)
{
    if (node.MoveToAttribute(NIL_LOCALNAME, NIL_NAMESPACE))
        node.DeleteSelf();
}

public static void ClearAndSetNil(XPathNavigator node)
{
    XmlDocument doc = new XmlDocument();
    doc.LoadXml(node.OuterXml);

    XmlElement nDoc = doc.DocumentElement;

    XmlAttribute attr = doc.CreateAttribute(NIL_PREFIX, NIL_LOCALNAME, NIL_NAMESPACE);
    attr.Value = BoolHelper.True;

    nDoc.Attributes.Append(attr);
    nDoc.InnerText = String.Empty;

    node.ReplaceSelf(nDoc.OuterXml);
}

All other solutions seem to throw the “Schema validation found non-data type errors” error. Note that the xsi:nil attribute is only required for field types that require a value, such as:

  • Whole Number (integer)
  • Decimal (double)
  • Date (date)
  • Time (time)
  • Date and Time (dateTime)

 

Related

» The xsi:nil attribute - http://blogs.msdn.com/b/infopath/archive/2006/11/28/the-xsi-nil-attribute.aspx

» How to: Work with the XPathNavigator and XPathNodeIterator Classes - http://msdn.microsoft.com/en-us/library/office/aa945227.aspx


InfoPath Forms Services 2010: glitch with repeating dynamic hyperlinks


May 22, 2012 - 11:15, by Steven Van de Craen - 0 Comments

Yesterday I noticed a strange issue, very hard to reproduce due to quite some nested sections, filtered repeating sections and other circumstances. So while I can’t reproduce the issue in a clean form (because it would take too much time to reproduce our working form situation) I’ll just write on the experienced behaviour and a workaround.

Environment

A SharePoint 2010 environment patched up to SP1 and December 2011 Cumulative Update, hosts an InfoPath 2010 web form in IPFS that displays data from a secondary data source.

The secondary data source (simplified) contains repeating items with a URL and (on a deeper node) addition information about the item.

<l> <i> <data> <ref>REF-1</ref> </data> <url>http://url1</url> </i> <i> <data> <ref>REF-2</ref> </data> <url>http://url2</url> </i> <i> <data> <ref>REF-3</ref> </data> <url>http://url3</url> </i> </l>

The InfoPath Form renders a filtered view on this data, but further testing ruled this out as the culprit. It is formatted to display a repeating section with a Hyperlink field. The hyperlink field has the address bound to the url element, the text is bound to the data/ref element.

Form Edit Mode

Experienced behaviour

When the form is opened using InfoPath Forms Services, it renders the right number of repeating sections, but all section hyperlinks point to the first element of the Secondary Data Source.

The picture below shows what should have been rendered, but instead it renders all links pointing to “REF-1” (both text and address).

IPFS form

Workaround

Somehow by adding the data element as a section in the repeating section fixes the issue. At first I moved the Hyperlink inside that section, but that wasn’t even required ! So you might as well leave the section empty.

Now since an empty section looks rather silly, I suggest you design the form with the Hyperlink field inside that section. This makes for a minor difference in XPath for the Address and Text bound properties but really that doesn’t matter.

Form Design Mode (2)

You can set the padding, margin and border options for the section so that it isn’t visible in runtime mode.

 

That concludes my blog on this glitch. If you experience this issue as well I hope the workaround solves it as well !


SharePoint and InfoPath Promoted Fields


August 25, 2011 - 17:28, by Steven Van de Craen - 0 Comments

A short blog on how the Promoted Fields seem to behave for InfoPath forms stored in SharePoint.

They are created as fields (Date, Text, …) and have the XPath property configured to the field in InfoPath (example: /my:myFields/my:field1)

When the form is stored in the library, the value of the XPath’s InnerText is stored in the List Item. It is by no means a live evaluation of the XPath.

Through code one can update the XPath value of the SPField. This does not affect existing forms since the value is persisted during form save, only new forms are affected.

SPSite site = new SPSite(url); SPWeb web = site.OpenWeb(); SPList list = web.GetList(url); SPField field = list.Fields["Field1"]; field.XPath = "/my:myFields/my:field1"; field.Update();

When you set the XPath to an element that has child elements, the InnerText will render all the elements contents as you’d expect:

<my:myFields>
  <my:field1>value 1</my:field1>
  <my:field2>value 2</my:field2>
</my:myFields>

When the XPath is set to "/my:myFields”, the Promoted Field value will be “\n\t11\n\t22\n” (it preserves indents).

That’s all for this quick blog post !


InfoPath Forms Server 2010 Parameterized Submit issue


March 9, 2011 - 13:16, by Steven Van de Craen - 1 Comments

I’m currently testing our InfoPath Web Forms for an upcoming migration to InfoPath 2010 and SharePoint 2010 and have come up with a reproducible issue.

Issue

InfoPath Web Forms cannot use values from other Data Sources as parameters in a Submit Data Connection. When the form is submitted a warning “There has been an error while processing the form.” shows. From that point on the only working option is Exit Form.

image

  • It does not affect data connections to XML files, only when the query data connections connects to a Web Service
  • It does not affect the offline version of the form (InfoPath Filler 2010)
  • Tested in both December 2010 Cumulative Update and February 2011 Cumulative Update for SharePoint 2010

Set up

  1. Create a new InfoPath Web Form
  2. Add a Query Data Connection to retrieve data from a Web Service

    InfoPath Query Data Connection
  3. Add a Submit Data Connection to submit data to a Web Service. Configure at least 1 parameter (if more then one) to link to a value from the above Query Data Connection

    InfoPath Submit Data Connection
  4. Configure the form to submit using the above connection

    Submit Options
  5. Publish the form to SharePoint 2010 and open a new form in the browser

Workaround

Store the value of the query data connection in an intermediary field in the form (“Main” Data Connection). Configure the Submit Data Connection to use the intermediary field value as parameter for the Submit. You can store the value as late as possible using Rules in Submit Options or your own submit buttons.


SharePoint URL Changes and InfoPath Forms


March 8, 2011 - 10:28, by Steven Van de Craen - 0 Comments

InfoPath Form Template URL

We have a solution that makes extensive use of online and offline InfoPath forms in a MOSS 2007 environment. An upgrade to SharePoint 2010 is due in a few months, including a redesign of Managed Paths and Site Collection ‘hierarchy’ having a direct effect on the URL of our Site Collection.

I thought this meant a lot of work for converting the thousands of InfoPath XML Forms by script, because they all contained an absolute URL to the InfoPath Form Template.

However as it seems after restoring the Site Collection all forms automagically had a corrected absolute URL to their template !!

<?xml version="1.0"?>
<?mso-infoPathSolution productVersion="12.0.0" PIVersion="1.0.0.0" href="https://public.contoso.com/sites/csapp/FormServerTemplates/LeaveRequest.xsn" name="urn:schemas-microsoft-com:office:infopath:LeaveRequest:-myXSD-2009-05-29T07-59-01" solutionVersion="1.0.0.422" ?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?>
<my:Data  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"
          xmlns:tns="http://public.contoso.com/webservices"
          xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
          xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
          xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
          xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
          xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
          xmlns:xhtml="http://www.w3.org/1999/xhtml"
          xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"
          xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-05-29T07:59:01"
          xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"
          xml:lang="nl-be">
  <!-- Form content -->
</my:Data>
 

Default Alternate Access Mapping

What happens is that when you restore a Site Collection backup, it looks up the Web Application by the URL you specified as a parameter. From that Web Application, it takes the Alternate Mapping configured on the "Default” Zone and uses that URL to construct the absolute URL in the InfoPath XMLs.

Only at restore time

This mechanism only seems to trigger when the restore takes place. Changing the Default AAM afterwards to a different URL has no effect. You could temporarily change the AAM for the restore operation and then set it back if you want. Beats any script iterating and updating all Form XMLs any day.

 

Most of the times you expect the worst from SharePoint, but then it catches you by surprise and brings a huge smile to the face :)


How does SharePoint know the Content Type of an InfoPath form saved to a document library ?


March 10, 2010 - 20:13, by Steven Van de Craen - 0 Comments

When you have multiple Form Content Types with each their respective form templates assigned to the same Form Library by some magic it will automatically save a new form in the correct Content Type. How it does this ?

The new form’s XML contains an InfoPath processing instruction with a “href” attribute set to the XSN template URL. At save time the Content Types configured in the Form Library are iterated and a match is made based on Template URL. If no match is found it will use the default Content Type.

 

InfoPath Form XML

List Content Type Advanced Settings

 

Even works in code if you do a SPFileCollection.Add() so no need to specify the Content Type explicitly during saves !

It doesn’t seem to take Alternate Access Mappings into account so that’s a bit of a downer, but still powerful.


Deserialize + serialize an InfoPath Form loses the processing instructions


January 21, 2010 - 17:16, by Steven Van de Craen - 0 Comments

Using xsd.exe you can generate a Class from your form schema (xsd) and then deserialize a form to an instance of that class. This makes it a lot easier to interact with its data.

CS class based on XSD

The code for serialization and deserialization might look like this:

public static T Deserialize<T>(Stream s)
{
T result = default(T);
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    using (XmlTextReader reader = new XmlTextReader(s))
    {
         result = (T)serializer.Deserialize(reader);
    }
    s.Close();
    return result;
}
public static T Deserialize<T>(string s)
{
    return Deserialize<T>(new MemoryStream(Encoding.UTF8.GetBytes(s)));
}
public static string Serialize<T>(T o)
{
string result = null;
    XmlSerializer serializer = new XmlSerializer(typeof(T));
    XmlWriterSettings settings = new XmlWriterSettings(); 
    settings.Indent = true;
    settings.Encoding = Encoding.UTF8;
    using (MemoryStream stream = new MemoryStream()) 
    {
         using (XmlWriter writer = XmlTextWriter.Create(stream, settings))
         {
             serializer.Serialize(writer, o);
         }
         stream.Flush(); 
         result = Encoding.UTF8.GetString(stream.ToArray());
    }
    return result; 
}

However you lose the original processing instructions at the top of the XML file. If you want to keep those either do custom serialization using an XmlWriter or do some kind of merge code with the original XML and the XML coming from serialization.

InfoPath XML Processing Instructions

Quite obvious if you think about it but I keep forgetting it :)