Web ServicesBuild a Custom SharePoint Web Service for Your InfoPath 2003 Documents

Build a Custom SharePoint Web Service for Your InfoPath 2003 Documents

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Like many organizations, much of the collaborative work we perform at Crowe Chizek is done using electronic documents. In years past, we stored many of the documents we utilized in file shares, which had a number of limitations for collaboration. Our biggest challenge was organizing the file shares in an intuitive fashion.

Our company wanted to build a workflow process around the task of approving new clients. A workflow is a series of tasks performed to complete a particular goal. We perform financial services, so client approval is important for risk assessment and regulatory compliance. We began turning to online collaboration tools to organize our processes. Often, online collaboration is performed as a part of a workflow process.

Requirements for our client approval process essentially amounted to review and approval by various individuals within our organization. The approval routing was dynamic and based on the group making the client approval request. We decided to use SharePoint, the Microsoft standard for online collaboration, for the document receptacle, but we realized we needed to augment it in some way to incorporate workflow in the process. We wanted to utilize the power of our InfoPath 2003 installation to quickly design forms. InfoPath stores its data as XML documents.

We evaluated two potential technologies for augmenting SharePoint: events and custom Web services. A custom Web service appeared to be the best choice for a number of reasons:

  • Implementing a Web service put a layer between the client’s application and SharePoint.
  • A Web service would enable us to perform other actions before writing the document to SharePoint.
  • Events are executed after a document has been written to SharePoint.

A Web service was simply a more robust solution to the problem. Using an Event, any failure to perform actions beyond saving the XML document will not be visible to the end-user and therefore will, at best, be detected later than a failed step in a Web service.

A Custom Web Service for SharePoint

Developing a custom Web service for a SharePoint server is different from creating a traditional ASP.NET Web service. To utilize the full capabilities of the SharePoint API, your Web service must be configured to run from a virtual directory inside of the SharePoint Server Web site. Much of what you need to configure your development environment to write a custom Web service for SharePoint is covered in an article on the MSDN Web site, titled “Writing Custom Web Services for SharePoint Products and Technologies.” The article explains how to set up your development environment and create the appropriate files so a Web service can be integrated with the SharePoint Server. The remainder of this article will build on the techniques outlined in the “Writing custom Web services for SharePoint products and Technologies” MSDN article to illustrate how you would integrate with InfoPath 2003 SP1 (Service Pack 1).

As you could probably guess, you begin building a SharePoint custom Web service by creating a Web service Project in Visual Studio.NET. If SharePoint is installed to utilize port 80, SharePoint essentially commandeers anything initiating communication with port 80. So, you have two options for configuring your Web service for use by Visual Studio. The first option is to configure the Web service to utilize; for instance, an alternative HTTP port such as 8080. When prompted for a location, include the port number in the URL like in this the example:

http//ServerName:8080/ProjectName

Alternatively, you can create the Web service in a virtual directory excluded from the SharePoint path using the stsadm SharePoint command-line utility:

stsadm -o addpath -url http:// servername /SPSWebApp -type exclusion

After building the Web service in Visual Studio, you must add a Web method that accepts the contents of an InfoPath document. An InfoPath document is in XML format, so the Web method parameter must accept XML data. Your two best parameter choices are a string or an XmlDocument. We decided to use an XmlDocument mainly because a string must be parsed and validated. Therefore, further code would’ve been required to parse and validate a string. This is the save method declaration:

[WebMethod]
public string Save(XmlDocument xmldoc)
{
   SharePointSiteMediator sp;
   XmlFilePackager xmlFile;
   MemoryStream strm;
   MemoryStream strmWorkflow;
   string fileName = "";
   string docID = "";
   FileSystemMediator fs;
   Guid workflowFileName = Guid.NewGuid();

   sp = new SharePointSiteMediator();
   xmlFile = new XmlFilePackager ();
   fs = new FileSystemMediator();

   sp.Open();

   sp.NavigateToFolder ("Client Engagement Setup Form");

   strm = xmlFile.BuildSubmitFile( xmldoc, ref fileName,ref docID );

   sp.WriteFile (fileName,strm );

   strmWorkflow = xmlFile.BuildWorkFlowFile(xmldoc,sp.CurrentURL +
                                            fileName,docID,5);

   fs.WriteFile(strmWorkflow,@"C:InetpubwwwrootEIS_Services" +
                workflowFileName.ToString() + ".xml" );

   return "";
}

As you construct and debug your Web services, you will repeatedly build your Web service. So that SharePoint can locate the assembly utilized by your Web service, you must change the target directory of the Web service assembly to write to the SharePoint bin virtual directory. The physical location of the SharePoint bin directory on the file server is here:

<INSTALLED DIR>:Program FilesCommon FilesMicrosoft Shared
                 web server extensions60ISAPIBIN

Enable InfoPath to Discover Your Web Service

Now, you must create the WSDL and DISCO files so that InfoPath can discover your Web service. The MSDN Web site whitepaper titled “Writing Custom Web Services for SharePoint Products and Technologies” completely covers how to create the WSDL and DISCO file, so I won’t repeat the steps in the article; I’ll just make the appropriate changes for differences in the name of the Web service. In the included sample code, the Web service is named CEA, not Service1. If you create your own SharePoint Web service, you must make similar changes. The URL for the Web service will be located in a virtual directory called _vti_bin:

http://tomcat/_vti_bin/CEA.asmx

Like all development projects, utilizing the Visual Studio debugger is important for productivity. When you invoke the Web service, you can perform debugging by selecting Processes from the Visual Studio.NET debug menu. Select the process called w3wp.exe, which is highlighted in Figure 1.

Figure 1: Select the Process Called w3wp.exe

If you see multiple w3wp.exe processes, select the process with the .NET type running the vti_bin virtual directory. Some experimentation may be necessary to find the correct process.

Once you’ve built the Web service and made the Web service available from within SharePoint, you can integrate with InfoPath 2003 Service Pack 1. After you’ve created an new InfoPath form, select Submitting Forms on the InfoPath Tools menu. The dialog in Figure 2 will appear.

Figure 2: Result of Select Submitting Forms on the InfoPath Tools Menu

Select the Web service option from the Submit to menu and then press the Add button to configure the Web service options. Follow the Data Connection wizard entering the URL for the Web service and selecting the method you wish to invoke. When prompted for Web service parameters, select the options to send the entire XML document as shown in Figure 3.

Figure 3: Select the Options to Send the Entire XML Document

Process Incoming Data

At this point, you’ve built everything you’ll need to discover the Web service and transmit the XML document from InfoPath 2003. The remaining tasks are performing some processing on the incoming XML and writing the data to SharePoint.

First, you must remove the root node from the incoming document. Processing information (PI) in the InfoPath document exists outside of the root of the InfoPath document. The underlying Web service technology creates a root outside of the InfoPath document PI. Before saving the incoming XML document, you must remove the root node outside of the PI. The following code illustrates how to remove the root information and write the XML data to a MemoryStream object:

strm = new MemoryStream();

root = xmldoc.FirstChild;

foreach( XmlNode child in root.ChildNodes )
{
   xmldata = encode.GetBytes(child.OuterXml);

   strm.Write(xmldata,0,xmldata.Length);
}

Once you have the data in a Stream object, you can extract the bytes and write the file to the SharePoint site. SharePoint offers two APIs for manipulating data: a Web service and a .NET assembly. The .NET assembly is the more complete API. We elected to use the Microsoft.SharePoint.dll assembly API in case we decided to extend our solution. Microsoft.SharePoint.dll includes functions for reading, writing, and versioning files in SharePoint. In the example code, all of the code to read and write to SharePoint is embedded in the SharePointSiteMediator class.

Three critical classes navigate and manipulate files in SharePoint. SPSite provides the navigation in SharePoint. SPWeb provides methods for accessing objects in a given site. SPFolder allows you to manipulate documents in a document library or list. In the example, SPSite, SPWeb, and SPFolder are declared as follows:

private SPSite _siteHome = null;
private SPWeb _subsite = null;
private SPFolder _folder;

The WriteFile function below utilizes the Stream you created to add or update the XML document in SharePoint:

public void WriteFile (string fileName,MemoryStream strm )
{
   byte[] fileContent = null;
   SPFile file;

   fileContent = strm.GetBuffer();

   if ( FileExists(fileName ) )
   {
      file = _folder.Files[fileName];

      file.SaveBinary(fileContent);
   }
   else
   {
      file = _folder.Files.Add(fileName, fileContent,true);
   }

}

To determine whether the document already exists, you must use the SPQuery object and a pseudo SQL query. FileExists illustrates querying SharePoint for the existence of a document. The following is an excerpt from FileExists:

query = new SPQuery();

docLib = (SPDocumentLibrary)_subsite.Lists[_folder.
         ContainingDocumentLibrary];

fileExistsQry = _fileExists.Replace("{filename}", fileName);

query.Query = fileExistsQry;

items = docLib.GetItems(query);

With the Web service writing to SharePoint complete, you can extend the code to perform other duties, including:

  • Perform validation on the formatting of the XmlDocument
  • Perform an additional security check
  • Initiate a workflow process in a workflow tool such as BizTalk 2004 Human Workflow or K2
  • Place the XML Document in multiple libraries

Now You Can Perform Other Actions

Building a SharePoint Web service for your InfoPath 2003 documents adds a layer of software to your application, allowing you to reliably perform other actions whenever a user saves an InfoPath document. Among the other actions are initiating workflow processes and performing some additional security validation.

Download the Code

To download the accompanying source code for this article, click here.

About the Author

Jeffrey Juday is a software developer with Crowe Chizek in South Bend, Indiana. He has been developing software with Microsoft tools for more than 12 years in a variety of industries. Jeff currently builds solutions using BizTalk 2004, ASP.NET, Sharepoint, and SQL Server 2000. You can reach Jeff at jjuday@crowechizek.com.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories