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 4 and 7 and type the answer here:
  • Post
  • Hi Scott,

    I did not create the dummy Library and that was why I was getting this error. Now the form is submitted perfectly. But when I try to open, while opening it throws the same exception as above. Not sure why is that. On my form load event, I have the method you have to populate the strlocation etc.And then I have few of my other logic.

    Any ideas?

  • Hi Anita,

    If you followed the code in the original post, I believe I had a "bug." :) Take a look at the updated code I provided in my 2 Jan 2008 2:17 PM comments and see if this resolves the issue.

    My apologies for the inconvenience...

    Scott

  • Perfect Scott..That worked great.

    A very useful blog I have to say!!

  • Do I really need to digitally sign the infopath forms with the code? I am deploying the Infopath 2010 forms to the SharePoint using administrator approved method? I have set the forms to full trust but wondering if I really need to set the digital certificate?

  • Nik - if the InfoPath form will *only* ever be used in the browser then no - you don't have to digitally sign the XSN. However, if the security level is explicitly set to Full Trust and there is a possibility it will be opened in the InfoPath client, then you will need to sign it.

    Scott

  • Hi Scott,

    Thanks for the code. We are using infopath 2003, used 'SubmitToThisLib_2003_js.txt' script and working as expected. As per my understanding this code helps to submit the "InfoPath form template" to multiple SharePoint document library's dynamically. But we need to publish the infopath template to multiple SharePoint document library's right?. Can we avoid this multilple Publish in infopath 2003?

  • Hi Surya,

    To clarify - the code allows you to submit the completed InfoPath form to the library from which it was opened without knowing that library at development time. It does *not* submit the InfoPath Form Template - this is something that is published and you *must* publish the XSN to each library...there is no way around this. In fact, this behavior is the same in all three versions of InfoPath: 2003, 2007 and 2010.

    Scott

  • Hi Soctt,

    Thanks for your quick responce. This code is working when we Enable the Submit functionality (Tools | Submit Options) and choose the “Perform custom action using code” option.

    In our case we have a Button for submit and it has some rules before submiting the form. How can we enable this functionality for submit button with out "Enable the Submit functionality"

  • Hi Surya,

    You will need to move the logic you have in the "rules" to the code. If all the rule logic is met, then proceed to submit the form.

    Scott

  • Hi, would the updated code you used on 2 Jan 2008, allow it to work with the forms library having subfolders and check in / check out functionality turned on?

    As it is now, whenever a form is submitted from within a subfolder an exact replica is created in the root of the forms library.

    We are using 2003 C#

  • Hi Sune,

    I just tested this and am not seeing the behavior. Now, I did just a simple test and used C# for 2007 so you will need to change this for 2003:

    - Added a new node to my XSN called: strSubFolder (for this simple teste, I did NOT write any code to populate this node when the form opens)

    - Added strSubfolder to my View so I could enter a value in that control

    - Made the following changes to the "submit" code:

        - Added this line of code where I created the other XPathNavigator objects:

    XPathNavigator xnSubFolder = xnDoc.SelectSingleNode("/my:myFields/my:strSubFolder", this.NamespaceManager);

        - Modified this code from this:

        // Modify the URL we want to submit to by concatenating the

        // xnLocation and xnFolderName values

        fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value;

        To this:

        if(xnSubFolder.Value != string.Empty)

    fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value + "/" + xnSubFolder.Value;

        else

    fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value;

    - Publish the changes

    - Open a new instance of the form in the browser and submit - result: just one copy in the folder - no where else

    - Re-open that form in the browser and submit again - result: again, just the one copy in the folder - no where else

    So it seems I am not able to reproduce your issue. You may want to either debug that code or add tracing statements to your code to see if there is something in the code that causes this to occur.

    Scott

  • This is kinda working for me (submitting an Infopath 2010 Browser enabled form to a Sharepoint 2010 Document Set) when first submitted, but on subsequent submissions it's failing. I've used the revised code from the 2nd January post but it's still not working:

    strFormURL:

    First Run: http://server/doc library/docset/

    Second Run: /doc library/docset/form name

    strLocation:

    First Run: http://server/doc library

    Second Run: http://server

    strFolderName:

    First Run: docset

    Second Run: doc library

    I'm not a programmer and am quite possibly an idiot (I bet it's a schoolboy error), so go easy on me!

    Thanks in advance for any help - much appreciated!

  • Hi Scott,

    Thanks for the blog! I used your same code. There was no error. However, when I publish and test it, I get the following msg:

    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.Internal.DataConnectionsHost.get_Item(String name)

      at Stakeholder_checklist_final.aspx.FormCode.FormEvents_Submit(Object sender, SubmitEventArgs e)

      at Microsoft.Office.InfoPath.Internal.FormEventsHost.OnSubmit(DocReturnEvent pEvent)

      at Microsoft.Office.Interop.InfoPath.SemiTrust._XDocumentEventSink2_SinkHelper.OnSubmitRequest(DocReturnEvent pEvent)

    I m not sure what seems to be the problem. Please help

    Thank you,

    Shyam

  • Hi Shyam,

    I really have no idea since I don't know where the failure occurs. It could be that one of the fields is  not populated? Does it work in the InfoPath client? If it does and only fails in the browser then you will need to debug the code when it runs in the browser - take a look at this for how to debug browser code:

    blogs.msdn.com/.../debugging-browser-forms.aspx

    Scott

  • Does the DummyLib need to be created on the site to get this code to work.

Page 10 of 12 (166 items) «89101112