Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

Submitting to 'this' document library

Submitting to 'this' document library

Rate This

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 find attached 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:

  1. Add 3 text box controls, all with a data type of text, named as follows: strFormURL, strLocation and strFolderName
  2. Add a “Submit” data connection named “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
  3. Set the Security Level of the form to Full Trust and sign the form template with a digital certificate
  4. 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:

 

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.

 

Scott Heim

Support Engineer

Attachment: submitToThisLibrary.zip
Leave a Comment
  • Please add 3 and 6 and type the answer here:
  • Post
  • Hi Scott

    I got a little question about submitting a form to a sps document library.

    I publish my forms as content types at the root of the site collection. After filling out one of these form templates I'd like to submit this form to a specific doc library in the same site collection, the URL of the appropriate library is depending on a string in a textbox.

    So I have to add a submit dataconnection programmatically, however I don't have a clue how to do that?

    Walter

  • Hi Walter,

    So that you know, InfoPath does not have an object model for the designer whatsoever so "adding" a data connection at runtime is not possible; however, changing an existing data connection at runtime is possible and that is what this blog post is for. But if you have tested (or gone through the comments in this blog) you have seen that if you publish the XSN as a Site Content Type *and* are opening the form in the InfoPath client then there is no way to capture the location of where the form has been opened. We have had this request a number of times but it is not possible to capture that information...unless you open the form in the browser.

    Scott

  • Hi Scott,

    First, thanks!  Your example worked as expected in SP2010 (even works with Document Sets.)  Although, I'm hoping that you're able to provide insight for a problem that I'm encountering.  After the form is submitted to the "this" library/location, I get an error when I re-open the form and the following is logged to Windows Event Log:

    Source: InfoPath Forms Services

    Event ID: 5337

    Task Category: Runtime - Business Logic

    Type: KeyNotFoundException

    Exception Message: The given key was not present in the dictionary.

    Any ideas?

    Thanks!

    Thomas

  • Hi KCD75,

    Glad it worked for you. :)

    When you get the error are you opening the form in the InfoPath client or in the browser?

    Also - can you post the actual code you have on the loading event?

    Thanks,

    Scott

  • Hi Scott

    I got the same error message (5337 in the event log) as KDC75, each time I'am reopening a form. Here you got my loading method:

    public void FormEvents_Loading(object sender, LoadingEventArgs e)

           {

                   //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 is not necessary -

                   //this is simply to see the process in action

                   PopulateLibInfo(OpenedInBrowser);

           }

    Walter

  • .. oh I get the error message in the browser.

  • Hi KDC75 and Walter,

    The error you are getting was due to a bug <g> in my original sample code. Take a look at the January 2 comments on page 5 - here I have updated code to correct that error.

    Scott

  • Thats a good tutorial. Can I have a a similar solution for creating a  Receiving data connection from a Sharepoint list?

  • Hi Abdul,

    Are you referring to how to dynamically create a receive data connection to a SharePoint list? If so - I don't know of a way to do this as InfoPath actually uses the GUID to the list as part of the receive data connection so it is not as simple as just knowing what URL the XSN was opened from.

    Scott

  • Hi Scott,

    You say to Walter in April 2010:

    ... if you publish the XSN as a Site Content Type *and* are opening the form in the InfoPath client then there is no way to capture the location of where the form has been opened.

    If you double click an InfoPath Form that was published as a Content Type in a SharePoint Form Library, then in FormEvents_Loading if you use the statement:

    string formUrl = this.Uri;

    formUrl will contain the total URL for where the form was opened from.

    If you do this on a form you opened with NEW it will contain a suggested form name such as Form1.

    If you do it from Preview or Debug mode it will contain (Preview) Form1.

    I use this technique to retrieve the form URL at runtime so that I can tell where it came from to use as necessary in program logic.

    Jeff

  • Hi Jeff,

    Thank you for the information. I believe in most cases, users will add the Content Type to the library and click New, which will not give the same information.

    Scott

  • Is there a way to submit a form to a folder on the computer rather than a URL?

  • Hi,

    I'm having a problem publishing my form to a content type. I made the form full trust created a cert to sign it, but my only option when publishing is to make it administrator-approved. Do you have any idea why that might be?

    Meri

  • Hi Meri,

    Yes - this is expected when you form template is browser-compatible. Once you set the security level to Full Trust and you have a browser-compatible form, the only SharePoint publishing option you will have is as an Administrator-approved form template. However, once you complete the entire process, you *will* wind up with a SharePoint Content Type that you activate to a site collection and then add to a library.

    Take a look at this link:

    technet.microsoft.com/.../cc262921.aspx

    It is written for InfoPath and SharePoint 2010 but if you are using 2007 the steps are basically the same.

    Scott

  • Hi Scott,

    I am trying to get this exact functionality work on Infopath 2010 integrating with Sharepoint 2010. I have a admin approved, browser enabled form which I installed using Central admin. But I want the form to be submitted using a custom button.I added a button, named it submit and onClick event of button I added the code that you have in your form submit event.

    The values in the text box fields appear correct, but when I try to submit,

    I keep getting exceptions something like this.

    Is there something I am missing? I don't have my form digitally signed. Is this an issue.

    Appreciate any response.

    Business logic failed due to an exception. (Type: InvalidOperationException, Exception Message: The given key was not present in the dictionary. The given key was not present in the dictionary.) 7b141a58-0563-4801-9e99-128bac7d3102

    01/31/2011 14:01:32.02 w3wp.exe (0x1A0C)                       0x17B0 InfoPath Forms Services       Runtime - Business Logic       7tge Medium   Exception thrown from business logic event listener: System.InvalidOperationException: The given key was not present in the dictionary. ---> System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.     at System.ThrowHelper.ThrowKeyNotFoundException()     at System.Collections.Generic.Dictionary`2.get_Item(TKey key)     at Microsoft.Office.InfoPath.Server.DocumentLifetime.DataAdapters.EnsureDataAdapter(String name)     at Microsoft.Office.InfoPath.Server.DocumentLifetime.DataConnectionCollectionHost.<>c__DisplayClass4.<get_Item>b__3()     at Microsoft.Office.InfoPath.Server.DocumentLifetime.OMExceptionManager.ExecuteOMCallWithExceptions(OMCall d, ExceptionFilter exceptionFilter)     --- End of inner exception stack trace ---     at Microsoft.Office.... 7b141a58-0563-4801-9e99-128bac7d3102

    01/31/2011 14:01:32.02* w3wp.exe (0x1A0C)                       0x17B0 InfoPath Forms Services       Runtime - Business Logic       7tge Medium  

Page 9 of 12 (166 items) «7891011»