InfoPath Submit programmatically with Forms Server – spsite.MakeFullUrl

For a recent project, I needed code to submit an InfoPath form to a forms library. Since this library could have embedded folders, I had to revert to use code for this. Unfortunately, if you use "Submit" it will save only to the root folder or a pre defined Url. Hope this one is solved with SharePoint 2010….!

If you create an InfoPath form via forms server, you will see a querystring attribute called "SaveLocation". This will be a string in the format"/div/hrcontent/formstest/testfolder/myinfopathform.xml". If you edit an InfoPath form you will see a querystring called "XmlLocation" in a similar format.

You can use these strings to build up the location where to submit your form; you just have to convert them to absolute Url’s in your code. Since we use forms server, we are able to get the SPContext; so our code is aware of the SharePoint site where it works within. This is handy, as we can use the relative paths of the described query strings to convert them into absolute Url’s. With this, we do not need to encode any hard coded paths anymore!

The following code is quite straightforward:

InfoPath form Design: create a submit connection like you are used to in you InfoPath designer screen. For convenience, call it "main submit". Later, we will alter this submit connection via code.

Loading event: get the query strings and construct the Url to save to. Since we use forms server, you need to use FormState variables; you can see these as kind of session variables. So, as long as the form is open, you will be able to get to the location.

Submit event: when you submit the form, all you do is replace the pre defined submit location in your form with the location you saved in your FormState variable.

And finally, the code! Note here that this is quickly assembled and not really "clean and lean" enough. If someone has cleaned up the code and wants to share, please let me know.

 

using Microsoft.Office.InfoPath;
using System;
using System.Xml;
using System.Xml.XPath;
using Microsoft.SharePoint;

namespace MyInfoPathForm

{
    public partial class FormCode
    {
        private object _strUri
        {
            get { return FormState["_strUri"]; }
            set { FormState["_strUri"] = value; }
        }
        private object _strLocation
        {
            get { return FormState["_strLocation"]; }
            set { FormState["_strLocation"] = value; }
        }
        private object _strFoldername
        {
            get { return FormState["_strFoldername"]; }
            set { FormState["_strFoldername"] = value; }
        }

        // NOTE: The following procedure is required by Microsoft Office InfoPath.
        // It can be modified using Microsoft Office InfoPath.
        public void InternalStartup()
        {
            EventManager.FormEvents.Loading += new LoadingEventHandler(FormEvents_Loading);
            EventManager.FormEvents.Submit += new SubmitEventHandler(FormEvents_Submit);
        }

        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)
            {
                if(e.InputParameters.ContainsKey("XmlLocation"))
                {
                    _strUri = SPContext.Current.Site.MakeFullUrl(e.InputParameters["XmlLocation"].ToString());

                }
                else if(e.InputParameters.ContainsKey("SaveLocation"))
                {
                    //new form
                    _strUri = e.InputParameters["SaveLocation"].ToString();

                }
            }
            else
            {
                //If it was opened in the client, we will get the Uri
                _strUri = this.Template.Uri.ToString();
            }
            //store the location and foldername
            string strUri = _strUri.ToString();
            string strPath = "";
            if (OpenedInBrowser)
            {
                strPath = strUri.Substring(0, strUri.LastIndexOf("/"));

            }
            else
            {
                strPath = strUri;
            }
            string strLoc = strPath.Substring(0, strPath.LastIndexOf("/"));
            string strFolder = strPath.Substring(strPath.LastIndexOf("/") +1);
            _strLocation = strLoc;
            _strFoldername = strFolder;

        }

        public void FormEvents_Submit(object sender, SubmitEventArgs e)
        {
             // Create a Navigator object for the main DOM
            XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();
            // Get a reference to the submit data connection
            FileSubmitConnection fc = (FileSubmitConnection)this.DataConnections["Main submit"];
            // Modify the URL we want to submit
            fc.FolderUrl = _strLocation.ToString() + "/" + _strFoldername.ToString();

            // Execute the submit connection
            try
            {
                fc.Execute();
                e.CancelableArgs.Cancel = false;
            }
            catch
            {
                e.CancelableArgs.Cancel = true;
            }
        }
    }
}

Leave a comment