Introduction to Sandboxed Solutions - Sort data in repeating tables using managed code
Hi. My name is Phil Newman and I'm a program manager on the InfoPath team. In this post, I'd like to introduce you to one of my favourite new features in InfoPath 2010 - Sandboxed Solutions. In InfoPath 2010, forms with code can now be published directly to SharePoint without requiring the farm administrator to approve and upload them! These forms run in a sandboxed environment which protects other resources on the SharePoint server from malicious code.
In this short video demo, I show how you can add the ability to sort repeating tables in your forms using code. I use picture buttons in the heading of the repeating table to trigger the code which sorts the table based on the values in the columns.
About the Code
In a nutshell, the code puts the XML from the repeating table into an array, sorts the array using built-in .Net functionality, and then writes back into the XML to update the table.
//Sorts a repeating table. Takes the parent group node and the index of the column to sort by. private void SortTable(string xpathToSort, int columnToSortBy) { //get the values in an array string[][] ValuesToSort = GetRepeatingTableValues(xpathToSort); //sort the array Array.Sort(ValuesToSort, new StringArrayComparer(columnToSortBy)); //write the values back to the xml SetRepeatingTableValues(xpathToSort, ValuesToSort); } //Takes an array of arrays and inserts it into a repeating table //Assumes that the array and table are the same size private void SetRepeatingTableValues(string xpathToSet, string[][] tableValues) { //Create a navigator on main node supplied in the parameters XPathNavigator mainGroup = this.CreateNavigator().SelectSingleNode(xpathToSet, this.NamespaceManager); //Clone the first child node of the main navigator and populate it with data XPathNodeIterator tableRows = mainGroup.SelectChildren(XPathNodeType.Element);
//iterate through the existing XML and update the values from the sorted array for (int i = 0; i < tableValues.Length; i++) { tableRows.MoveNext(); XPathNodeIterator thisRow = tableRows.Current.SelectChildren(XPathNodeType.Element); for (int j = 0; j < tableValues[0].Length; j++) { thisRow.MoveNext(); thisRow.Current.InnerXml = tableValues[i][j]; } } } //Returns an array of arrays of strings representing the values in a repeating table private string[][] GetRepeatingTableValues(string xpathToGet) { XPathNavigator myNav = this.CreateNavigator(); int rows, cols; XPathNodeIterator tableNodes; //figure out the dimensions of the table tableNodes = myNav.SelectSingleNode(xpathToGet, this.NamespaceManager).SelectChildren(XPathNodeType.Element); rows = tableNodes.Count;
//move to the first row to count the columns tableNodes.MoveNext(); cols = tableNodes.Current.SelectChildren(XPathNodeType.Element).Count; //create an array to store the values string[][] tableValues = new string[rows][]; //get all the rows in the table tableNodes = myNav.SelectSingleNode(xpathToGet, this.NamespaceManager).SelectChildren(XPathNodeType.Element); //iterate through the rows and write the inner xml of each element in each row to the array for (int i = 0; i < rows; i++) { tableNodes.MoveNext(); XPathNodeIterator childNodes = tableNodes.Current.SelectChildren(XPathNodeType.Element); string[] rowValues = new string[cols]; for (int j = 0; j < cols; j++) { childNodes.MoveNext(); rowValues[j] = childNodes.Current.InnerXml; } tableValues[i] = rowValues; } return tableValues; } //Comparison implementation for array or arrays class StringArrayComparer : IComparer { private int iColumn; public StringArrayComparer(int iColumn) { this.iColumn = iColumn; } int IComparer.Compare(Object x, Object y) { string[] xAsString = (string[])x; string[] yAsString = (string[])y; return xAsString[iColumn].CompareTo(yAsString[iColumn]); } } |
Requirements for publishing your forms with code as Sandboxed solutions:
- The Sandboxed code service need to be enabled on the farm
- You must be a site collection administrator on the site collection you’re publishing to
- Your form must be domain trust
- Your form template must be an InfoPath 2010 template
- InfoPath 2007 form code needs to be upgraded to InfoPath 2010 form code
Complete sandboxed solution documentation is available here. Note that InfoPath takes care of packaging and activating the solution, all you need to do is publish your form to a document library or as a site content type.
I look forward to hearing your comments about this new feature. Let me know what you think!
Phil
Comments
Anonymous
February 22, 2010
Nice post. I am working InfoPath 2010/SharePoint 2010 project, however, after adding developer tab, every menu items under developer tab is inactivate, gray-ed out. Any idea ? Thanks.Anonymous
February 22, 2010
Is it possible that you have not selected a programming language? If the "Language" button is enabled on the developer tab, try clicking it and selecting either C# or VB. Once you have selected a language, the buttons should be enabled. Let me know if that doesn't do the trick.Anonymous
February 22, 2010
If you haven't selected a language, you might also not be using an InfoPath 2010 form template. For your form to be published as a Sandboxed solution, make sure the form template compatibility is set to "Web browser form" and not "Web Browser form (InfoPath 2007)" in the form options dialog. You'll also need to be sure you are using either C# or VB as the programming language and not the InfoPath 2007 versions. You can change this by clicking the language button in the ribbon or by going into the form options dialog. PhilAnonymous
February 22, 2010
Thanks Phil for your reply. The problem as I just discovered that if your form template is SharePoint List, the developer tab does not work, however it works for SharePoint Form Library. so for SharePoint List template, there is no way to have managed code behind ? I am working for BI consultant firm. I see InfoPath is a great way for data collection. without managed code behind, I see a hug limitation. Thanks MaxAnonymous
February 22, 2010
Unfortunately we were not able to support code behind list forms in InfoPath 2010. You could work around this by writing a Web service and calling it from the form or using sandboxed event handlers on the list if your code only needs to be run when an item is created or updated in the list.Anonymous
September 02, 2010
Hi Phil, I tried your code but it crashes on the first compare when I try to preview the form. Should this work in preview or do I need to run it from the server? Also, does the data need to be submitted first? ThanksAnonymous
April 26, 2011
Hello Phil, First thank you for your effort in this article, second i have a problem to run this video.. Any idea to run it? sure i have silverlight installed on my machine and i have added silverlight.net in the trusted sites for the IE :(.. In fact I am a beginner in the sharepoint and infopath world, but I have good knowledge to work on it. I was started with infopath and sharepoint 2007, and now I have upgrade to 2010 in both. I think cause I am a developer I like to develop my life with Code really I am very happy cause this feature is added to infopath ad sharepoint 2010. But I need a short and an effective way to get and collect knowledge in this feature if you can help me to get the best resource that can I use. I look forward to hearing your comments about this And thank you again….Anonymous
December 15, 2011
Hello, Nice post. I am trying to deploy an InfoPath browser enabled form using features as a sandbox solution and I am having some problems. Please see social.msdn.microsoft.com/.../76b28eec-0460-4d43-b6fe-9210d28b0dbc for more details. If you could help, I would be greatly appreciated. Thanks, MiguelAnonymous
January 23, 2013
Written by an it'er click, blabla, click, clickAnonymous
November 11, 2013
Hi Phil, Is it possible that we can package the InfoPath codebehind using visual studio, uploading the WSP package and activating it manually? And is it possible to give a link between the solution and an infopath form which contains no code?