SharePoint: Creating InfoPath Property Promoted Columns Using Code


When you create an InfoPath 2007 form and publish it to a SharePoint deployment, you have the option to promote 1 or more of your forms XML elements to SharePoint as List columns or Content-Type columns, see this article for more information on property promotion.

Setting a forms promoted properties
Setting a forms promoted properties

This is a great feature, however it does have some drawbacks, principly – the XML elements you choose to promote as columns are created with column names set to a Guid value. You aren’t able to select the SharePoint internal column name from the infoPath client, you can of course set the display name.

To check this out, you can have a look in your forms manifest.xsf file, for a section named xsf:listproperties;

	<xsf:listProperties>
		<xsf:fields>
			<xsf:field name="PerPatientBudget_Total" columnName="{2A11F10A-F3AE-4AB0-B59C-4A05972A4714}" node="/my:costingdata/my:summary/my:perpatientbudget_cm_total" type="xsd:double"></xsf:field>
			<xsf:field name="PerPatientBudget_TotalPbrMFF" columnName="{2E21798F-183B-4BE6-B9C9-1F1310F0C2C3}" node="/my:costingdata/my:summary/my:perpatientbudget_cm_totalpbrmff" type="xsd:double"></xsf:field>
			<xsf:field name="CostingModel_Total" columnName="{0631F935-FB80-4A43-B72D-FFBD56390011}" node="/my:costingdata/my:summary/my:costingmodel_total" type="xsd:double"></xsf:field>
			<xsf:field name="CostingModel_TotalPbrMFF" columnName="{66F34174-7BA4-4DF6-B7CF-100E426B36D1}" node="/my:costingdata/my:summary/my:costingmodel_totalpbrmff" type="xsd:double"></xsf:field>
		</xsf:fields>
	</xsf:listProperties>

This can be an issue for you if say you want to build other assets which use these columns – a custom web part or a data view webpart for instance. Of course it’s not difficult to find the internal names of these columns, and once set the columns names generally don’t change unless you edit the promoted properties list.

There is another way though, and that is to create these columns programmatically, in a feature reciever if you’re provisioning your forms this way. Exactly what you will need to do to create your form columns will depend on your requirements, but will include at least 1 of the following tasks;

  1. Add the column definition as a Site Column
  2. Add the Site Column to a Site Collection content type
  3. Add the Site Column to a List content type

If you are publishing your form as a content type, or it’s an administrator approved form, then there will be a site collection content type representing the form.

For background information on how XML property promotion/demotion works within SharePoint, try this article and this MSDN article. To create promoted columns this way, the InfoPath form must first have been published to a SharePoint site collection.

The MSDN article is a link into the series of articles on MSDN concerned with the SharePoint built-in XML parser and how that works to enable promoted XML properties. These articles are a great source of information concerning the SharePoint built-in XML parser and how XML forms (and not just InfoPath forms) can be associated with SharePoint content types.

Note that the MSDN article “Specifying Content Type by Content Type ID”, is somewhat misleading, specifically if refers to the ContentTypeID column using the wrong Field ID, and refers to the DocumentTemplate field when this field is properly named TemplateUrl, defined in the document library schema.xml – these inconsistencies aside they are great articles.

In another article I’ll demostrate how you can publish your own (non InfoPath) XML forms to a SharePoint forms library, associate these XML forms with content types using the SharePoint built-in XML parser, and of course create XML property columns which support promotion and demotion.

The Field Definition.

We will define the column using a piece of CAML as shown.

<Field ID="658EB4E2-A293-43e4-8310-733A3A8AAA07" Type="Number"
				Name="MyTableTotal"
				DisplayName="My Table Total"
				Required="FALSE"
				SourceID="{F6BE8A09-B219-4f8a-8FDF-D9B6BE9E5CD8}"
				StaticName="MyTableTotal"
				Decimals="2"
				Percentage="FALSE"
				ReadOnly="TRUE"	// property column doesn't support demotion
				Group="MyGroup"
				Node="/my:myFields/my:tableTotal"
				Version="1" />

It’s a pretty standard field definition, notice the Node element, it is here where you set the XPath query which is used to specify which element [value] is promoted to the SharePoint column – the namespace usage is required.

Creating the SharePoint Column.

Adding the Site Column.

// add new column to site columns
web.Fields.AddFieldAsXml(columnXmlSchema);

// get new site column
var newSiteColumn = web.Fields.GetFieldByInternalName(schemaColumnName);

Adding the Site Column to a Site Collection Content Type.

// add site column to site content type
var siteCT = web.ContentTypes[ctName];
siteCT.FieldLinks.Add(new SPFieldLink(newSiteColumn));
siteCT.Update();

Add the Site Column to a List Content Type.

// add site column to list content type
var list = web.Lists[listName];
var listCT = list.ContentTypes[ctName];
listCT.FieldLinks.Add(new SPFieldLink(newSiteColumn));
listCT.Update();

and the complete function;

private static void AddSiteColumnToSite(SPWeb web, string listName, string ctName, string columnXmlSchema)
{
	var schemaColumnName = GetColumnAttributeFromSchemaXml("Name", columnXmlSchema);
	Debug.Assert(!string.IsNullOrEmpty(schemaColumnName));
	if (web.Fields.ContainsField(schemaColumnName))
		return; // don't attempt to add the column again

	try
	{
		// add new column to site columns
		web.Fields.AddFieldAsXml(columnXmlSchema);

		// get new site column
		var newSiteColumn = web.Fields.GetFieldByInternalName(schemaColumnName);

		// add site column to site content type
		var siteCT = web.ContentTypes[ctName];
		siteCT.FieldLinks.Add(new SPFieldLink(newSiteColumn));
		siteCT.Update();

		// add site column to list content type
		var list = web.Lists[listName];
		var listCT = list.ContentTypes[ctName];
		listCT.FieldLinks.Add(new SPFieldLink(newSiteColumn));
		listCT.Update();

		// add site column to list default view
		var dv = list.DefaultView;
		dv.ViewFields.Add(newSiteColumn);
		dv.Update();

		list.Update();
		web.Update();
	}
	catch
	{}
}

Of course, you would reverse these steps to remove the column, during say feature deactivation.

The complete CreateInfoPathPromotedPropertyColumn.cs file can be found on my projects page.

Published by

Phil Harding

SharePoint Consultant, Developer, Father, Husband and Climber.

4 thoughts on “SharePoint: Creating InfoPath Property Promoted Columns Using Code

  1. Hi,
    I have published a form to share point website and I would like to transfer the date field data(Expected project Start date) to a share point column with the same name (Expected project Start date) and every time the user submit the form I would like to see the date transfers automatically to the share point column (Expected project start date).

    Thanks

    Mohammad

  2. Do you know there is a limit to how many property promotions there are from the InfoPath form? I have been working in my form and got to a certain point where when i publish the form, it gives me an error saying it cannot update the list or library.

  3. Patti, I’m not aware of any limit, however this technique can be used in place of InfoPath property promotions (using the InfoPath designer)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s