Submit infopath form to MOSS 2007 form library using web service

Object:
1. Submit infopath form to sharepoint form library using code, so that custom validations can be implemented.
2. The submitted file name should be based on one of its internal field which would be unique.
3. File should be editable
Here are the basic steps to do this.

Step1: Create a Form Library in MOSS 2007 and go to settings > Form library settings > Advance settings> Select “Allow management of content types” yes and “display as a web page option” and Click ok.

Step 2: Create a web service and add following methods

[WebMethod]
public string Save(string strdoc)
{

try
{
string fieldName = "f1";
// Use elevated privileges so anonymous users can upload through
// this service.
SPSecurity.RunWithElevatedPrivileges(delegate { SubmitToSPLibrary(strdoc, fieldName); });
return "";
}
catch (Exception ex)
{
Log(ex.ToString());
return "error";
}

}
public void Log(string str)
{
StreamWriter Tex = File.AppendText("c:\\Backuplog.txt");
Tex.WriteLine(DateTime.Now.ToString() + " " + str);
Tex.Close();
}
private void SubmitToSPLibrary(string formData, string field)
{
string namespaceURI = "";
try
{
// With the form data submitted to this web service, we now
// need to find the location for submitting list data.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(formData);
//Get the namespace
Match mn = Regex.Match(formData, "my=\"(.+?)\"");
if (mn.Success && mn.Groups.Count > 1)
{
namespaceURI = mn.Groups[1].Value;
}

// Get the XSN location
XmlProcessingInstruction pi =
(XmlProcessingInstruction)xmlDoc.SelectSingleNode("/processing-instruction(\"mso-infoPathSolution\")");

if (null != pi && !String.IsNullOrEmpty(pi.Value))
{
Match m = Regex.Match(pi.Value, "href=\"(.+?)\"");
if (m.Success && m.Groups.Count > 1)
{
string xsnLoc = m.Groups[1].Value;
if (!xsnLoc.StartsWith("http", StringComparison.OrdinalIgnoreCase) || !xsnLoc.ToLower().Contains("/forms/"))

throw new Exception("XSN location is not a published InfoPath document library.");

// Open the site and web, try to get the list.
Log("Site Address: " + xsnLoc);
using (SPSite site = new SPSite(xsnLoc))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
string libLoc = xsnLoc.Substring(0, xsnLoc.LastIndexOf("/Forms/"));
Log("Library Address: " + libLoc);

// Upload form data to the library.
SPFolder folder = web.GetFolder(libLoc);
if (null == folder)
throw new Exception("Cannot find the InfoPath document library root folder.");

UTF32Encoding encoder = new UTF32Encoding();
byte[] data = encoder.GetBytes(formData);

//Get File Name
XmlNodeList list = xmlDoc.GetElementsByTagName(field, namespaceURI);

string fileName = "";
foreach (XmlNode node in list)
{
fileName = node.InnerText;
}
if (fileName.Trim().Length > 0)
{
//Add New File OR Update Existing one.
folder.Files.Add(String.Format("{0}/{1}.xml", libLoc, fileName), data ,true);
Log("Added Successfully.");
}
else
{
folder.Files.Add(String.Format("{0}/{1}.xml", libLoc, Guid.NewGuid()), data);
}
web.AllowUnsafeUpdates = false;
}

}

}

}

}

catch (Exception ex)
{
throw new Exception("Failed to upload form data", ex);
}

}



Step 3: You need to set following parameter in the code
1. fieldName (in Save Method): Submitted File name is based on this field value. If it is null then new GUID will be used.

Step 4: Open infopath app click File > Design a Form Template
Select Form Template, Blank options and Check “Enable Browser-Compatible Features only” option and click OK.

Step 5: Draw layout, Add Controls and validation as per requirement.

Step 6: Tools > Data Connection > Add
Select “Create a new connection to” and “submit data” and Click Next.
Select “To a web service” option and Click Next
Give webservice url and Click Next
Select Save method and Click Next
Select Parameter, “Entire Form” option and “Submit Data as string” option

Click Next
Give Connection name and click Finish.
Note: This web service is deployed with MOSS services or this form is deployed in full trust mode then no problem else you need to convert data connection to UDCX files. For this, Tools> Data Connections >Select Connection > Click Convert button and give data connection url and Click OK.

Step 7: Tools > Submit options
Set “Allow users to submit this form” true, Select web service option from dropdown and Select Data connection which we made as per following image.


Click Advance button > Select “Close the form” in After submit option Click OK.

Step 8: File > Publish
Select “To a sharepoint server with or without form services” and click next
Give url of form library excluding “forms/allitems.aspx” and click next
Select “Enable this form to be filled out by using a browser” (Assume Domain level security in tools > form options>Security and trusts) Select Document Library and click Next.
Select Update the form template … option and select form library and click next
Add column names and click next
Click Publish button and close
Open Form Library and enjoy it.

2 comments:

  1. while invoking it is asking strdoc value, what i have to do with this?

    ReplyDelete
  2. Great article - thanks ! I found that when re-submitting, it was always creating a NEW file. I saw your check for 'f1' field to get the name - but it's BLANK. *shrug* (this is for SP2010)

    Is the filename from an existing item supposed to be in the XML ? sent via InfoPath on submit ?

    ReplyDelete