Have you ever needed to develop an InfoPath form template that submits back to a SharePoint document library but you did not initially know the server or library name when developing the form? Or have a scenario where your InfoPath form template could be published (or added as a content type) to multiple SharePoint document libraries and you need the submit location to be dynamic? Well read on to find out how you can do this!
When you create an InfoPath form template that needs to be able to submit to a SharePoint document library, you need to specify that connection in the initial design of the form template. However, at run time you can use managed code to determine the server and library name where the form was launched and then modify the “FolderUrl” property of the submit data connection so the form is submitted to the appropriate library.
So let’s get started setting up this sample. The C# walkthrough below uses the new InfoPath 2007 managed object model; below, you will findattached the same logic implemented in InfoPath 2003 managed object model and in InfoPath 2003 JScript.
Step 1: Create a sample InfoPath Form Template
Create a browser-compatible form template as following:
- Add 3 text box controls, all with a data type of text, named as follows: strFormURL, strLocation and strFolderName
- Add a “Submit” data connection named “<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><?xml:namespace prefix = st1 />Main submit”:
- Set the document library name to a dummy SharePoint document library (i.e. http://server/dummyLib)
- Use the concat function to concatenate the strFolderName field and_Test for the File Name property: concat(my:strFolderName, "_Test")
- Enable the Allow overwrite if file exists property
- Set the Security Level of the form to Full Trust and sign the form template with a digital certificate
- Enable the Submit functionality (Tools | Submit Options) and choose the “Perform custom action using code” option
Now that we have the form, controls and submit functionality, let’s add the code to make this process work:
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Step 2: Add the code
- Click the Edit Code button on the Submit Options dialog
- Create the following FormState Dictionary object – this will be used to store the form’s location when the form is initially opened:
private object _strUri { get { return FormState["_strUri"]; set { FormState["_strUri"] = value; } }
- Add the following code to the Forms Loading event:
// Get the Uri (or SaveLocation in a browser form) of where // the form was opened. // See if the form was opened in the browser Boolean OpenedInBrowser = Application.Environment.IsBrowser; // If so, we will get the "SaveLocation" from the InputParameters if (OpenedInBrowser) _strUri = e.InputParameters["SaveLocation"].ToString(); else //If it was opened in the client, we will get the Uri _strUri = this.Template.Uri.ToString(); // Populate the fields on the form - keep in mind, this // not necessary - this is simply to see the results PopulateLibInfo(OpenedInBrowser);
- Add the following procedure to the Forms class:
private void PopulateLibInfo(Boolean OpenedInBrowser) { // Create a Navigator object for the main DOM XPathNavigator xnDoc = this.MainDataSource.CreateNavigator(); // Create Navigator objects for each field XPathNavigator xnFormURL = xnDoc.SelectSingleNode("my:myFields/my:strFormURL", this.NamespaceManager); XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager); XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager); // Get the Uri stored in the FormState Dictionary variable string strUri = _strUri.ToString(); // Create a variable to store the path (URL) to the document library string strPath = ""; if (OpenedInBrowser == true) { //If we are open in the browser, the strUri value is just //the server name and library - so we just need to get //the URL without the last "/" strPath = strUri.Substring(0, strUri.LastIndexOf("/")); } else { // Parse just the path to the document library - // this would return something like this: // http://server/library strPath = strUri.Substring(0, strUri.IndexOf("Forms") - 1); } // Now, parse the URL to where the document library resides; // this would return something like: // http://server or http://server/site string strLoc = strPath.Substring(0, strPath.LastIndexOf("/")); // Lastly, parse the URL to return just the document library name - // in this case,we are looking for the last "/" character // knowing that what comes after this is the document library name string strFolder = strPath.Substring(strPath.LastIndexOf("/") + 1); // Populate the fields on the form – we will use these // values in the Submit process xnFormURL.SetValue(strUri); xnLocation.SetValue(strLoc); xnFolderName.SetValue(strFolder); }
- Add the following code to the form’s Submit event:
// Create a Navigator object for the main DOM XPathNavigator xnDoc = this.MainDataSource.CreateNavigator(); // Create Navigator objects for the fields we will // use to modify the FolderUrl XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager); XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager); // Get a reference to the submit data connection FileSubmitConnection fc = (FileSubmitConnection)this.DataConnections["Main submit"]; // Modify the URL we want to submit to by concatenating the // xnLocation and xnFolderName values fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value; // Execute the submit connection try { fc.Execute(); e.CancelableArgs.Cancel = false; } catch (Exception ex) { e.CancelableArgs.Cancel = true; }
- Build and save the project
- Publish and test
And that is it! You now have an InfoPath form template that will submit to whatever document library the form was opened from so you do not need to know this information when designing the template.
http://blogs.msdn.com/b/infopath/archive/2006/11/08/submitting-to-this-document-library.aspx