PANVEGA’s Blog

DotNet Development, SharePoint Customizing, Silverlight, MS Infrastructure and other tips and tricks

How to develope a custom SharePoint WebService

Posted by PANVEGA on April 20, 2008

Szenario

For some procedures like, for example, adding the web service as a reference in a visual studio project or using the SP Designer to consume a Webservice, the discovery (.disco) and wsdl files are required. So we have to develope a WS who need to be registert in SharePoint.  We develope a custom SharePoint Webservice with a .disco and .wsdl file.

Because Windows SharePoint Services virtualizes its URLs (for example, http://MyServer/MySite/MySubsite becomes http://MyServer), you cannot use the autogenerated .disco and .wsdl files generated by ASP.NET. Instead, you must create a .disco page and a .wsdl ASPX page that provide the necessary redirection and maintain virtualization.

I recommend you to make a Content Deplyoment of the service. You do not need a solution.xml file, because you do not have a feature deployment in this special case.

At the end you be able to consume the service like any other SharePoint Webservice.

Information

This web service will work with new versions of SharePoint, Office SharePoint Server 2007 and Windows SharePoint Service 3.0. We gonna use the Webservice I developed in my previous post (access SP all Subites recursive). I have used Microsoft articles as a base for this article.

Create an ASP.NET web service in Microsoft Visual Studio 2005. There are two ways to do this. You can develop a web service on the server machine that hosts SharePoint or you can develop it on a remote machine that does not host SharePoint and later deploy the service on the machine that hosts SharePoint. We will discuss the second method in this article.

Add .ASMX file to your project if it’s not already there. This file will contain the programming logic for the web service. Note, you can add programming logic to the markup page as well as the code behind. The choice is yours. Generate a static discovery file (disco) and a Web Services Description Language (WSDL) file. Modify the disco and wsdl files for SharePoint. Deploy the web service files to the SharePoint server. Create a client application or use SP Designer to consume the web service.

My Class is called AllSitesService which returns a XMLNode. This can be a XMLDocument as well. THe method this.getSubSites(domain) iterates through all Subites.

[WebMethod(Description = “Description: Returns a XML Node with all  first level Subsites from the current SP User. <br/> Enter paramter e.g. http://moss.litwareinc.com&#8221;)]
public XmlNode getAllFirstLevelSubSites(string domain)
{
try
{
if (!domain.Contains(“http://&#8221;))
{
domain = “http://&#8221; + domain;
}
XmlDocument sites = this.getSubSites(domain);
return sites;
}
}
catch (Exception ex)
{
throw (ex);
}
}

Creating a Custom Web Service

1. The first step is to create an ASP.NET web service project in Visual Studio 2005. If you don’t find a web service project template in visual studio, that means that you are still running an old version of Visual Studio 2005, the one without the service pack.

2. In the Templates box, select ASP.NET Web Service Application and give the project a name you wish. You see the HelloWorld() Method. You can use this for the example as well ,-)

3. Add a reference to the assembly for Microsoft Office SharePoint Server 2007 (Microsoft.SharePoint.dll). This assembly is located in the following directory: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI.

Please note that if you are developing on a machine that does not have SharePoint installed then you can copy the required files from the SharePoint machine to your development machine.

4. Open e.g. the AllSitesService.asmx markup page. In Solution Explorer, right-click AllSitesService.asmx and select View Markup. You will notice that the markup page has following line:

<%@ WebService Language=”C#” CodeBehind=”AllSitesService.asmx.cs” Class=”ViewAllSites.Service1″ %>

Change it to the following line. Where ViewAllSites is my Namespace and AllSitesService is my WS class.

<%@ WebService Language=”C#”  Class=”ViewAllSites.AllSitesService” %>

5. Create a strong name for the class library. In Solution Explorer, right-click the web service project, and in the Properties dialog box, click Signing, select Sign the assembly, and select in the box for choosing a strong name key file. You can also strong name your assembly using the command line utility called as sn.exe. Use following steps if you want to strong name your assembly manually.

Strong naming utility (sn.exe) can be found in the following folder: C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin

6. Compile the web service project.

Generating and Modifying Static Discovery and WSDL Files

7. Run disco.exe at the command prompt from the ISAPI directory to generate .disco and .wsdl files. Path C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin.

8. Open command prompt and type the following line and press Enter: Disco YourPath/AllSitesService.asmx. Make sure you have entered the correct path in the command above otherwise you will get an error.

e.g. disco http://moss.litwareinc.com/_vti_bin/AllSitesService.asmx

The command creates 2 files AllSitesServic.wsdl and AllSitesService.disco.

9. To register namespaces of the Windows SharePoint Services object model, open both the .disco and .wsdl files and replace the opening XML processing instruction.

Note:

You will find these 2 new generated files when going to your browser enter the url to the webserice and append ?wsdl or ?disco behind the .asmx file. Cobe the code from the page.

10. Change the name of the disco file to AllSitesServicdisco.aspx. This is importan, because in the SP ISAPI folder you have to register the Webservice with the .asmx, disco and wsdl file.

To register namespaces of the Windows SharePoint Services object model, open both the .disco and .wsdl files and replace the opening XML processing instruction — <?xml version="1.0" encoding="utf-8"?> — with instructions such as the following:

<%@ Page Language=”C#” Inherits=”System.Web.UI.Page”   %>
<%@ Assembly Name=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Import Namespace=”Microsoft.SharePoint.Utilities” %> <%@ Import Namespace=”Microsoft.SharePoint” %>
<% Response.ContentType = “text/xml”; %>

The variables helps you when you want to deply the service to every SP Application you want. Which replaces literal paths with code generated paths through use of the Microsoft.SharePoint.Utilities.SPHttpUtility class, and which replaces the method name that is specified in the binding attribute:

<%@ Page Language=”C#” Inherits=”System.Web.UI.Page”   %> <%@ Assembly Name=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> <%@ Import Namespace=”Microsoft.SharePoint.Utilities” %> <%@ Import Namespace=”Microsoft.SharePoint” %>
<% Response.ContentType = “text/xml”; %>

<discovery xmlns:xsd=”http://www.w3.org/2001/XMLSchema&#8221; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xmlns=”http://schemas.xmlsoap.org/disco/”&gt;
<contractRef ref=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request) + “?wsdl”, ‘”‘); %> docRef=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), ‘”‘); %> xmlns=”http://schemas.xmlsoap.org/disco/scl/&#8221; />
<soap address=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), ‘”‘); %> xmlns:q1=”http://microsoft.com/webservices/SharePointPortalServer/BusinessDataCatalog&#8221; binding=”q1:BusinessDataCatalogSoap” xmlns=”http://schemas.xmlsoap.org/disco/soap/&#8221; />
</discovery>

11. Change the name of the disco fle to AllSitesServicwsdl.aspx

In the .wsdl file, make the following, similar substitution for the SOAP address that is specified: You find these two tag at the end of the page.

<soap:address location=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), ‘”‘); %> />

Make the following substitution for the SOAP12 address:

<soap12:address location=<% SPEncode.WriteHtmlEncodeWithQuote(Response, SPWeb.OriginalBaseUrl(Request), ‘”‘); %> />

Deploying web service on the SharePoint server

You find a good instruction where and how to deploy in my previous post:

https://panvega.wordpress.com/2008/11/19/deploy-a-custom-webservice-into-the-sp-isapi-_vti_bin-filder

or you can deploy it by hand :-(

12. Copy the web service files to the _vti_bin  (ISAPI) directory of the SharePoint server. Web service files that are to be copied are as following:

AllSitesService.asmx
AllSitesServicedisco.aspx
AllSitesServicewsdl.aspx

Note:

The _vti_bin virtual directory maps physically to the Local_Drive:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI directory, which contains the default Web service files used in Windows SharePoint Services.

13. In Notepad, open the spsdisco.aspx file. spsdisco.aspx is located in the following directory (on the SharePoint server).

Local_Drive:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI

The changes make your Web service discoverable in Visual Studio as a Web service alongside the default Windows SharePoint Services Web services

14. Add the following 2 lines to the end of the file within the discovery element and save the file:

<discoveryRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + “/_vti_bin/AllSitesService.asmx?disco”),Response.Output); %> xmlns=”http://schemas.xmlsoap.org/disco/&#8221; />

<contractRef  ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + “/_vti_bin/AllSitesService.asmx?wsdl”),Response.Output); %> docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + “/_vti_bin/AllSitesService.asmx”),Response.Output); %> xmlns=”http://schemas.xmlsoap.org/disco/scl/&#8221; />

15. Copying the assembly to the correct Bin folder or GAC.

To add your assembly to the Global Assembly Cache (GAC), you can either drag and drop the assembly into the %windows%\assembly directory using 2 instances of Windows Explorer, or use the command line utility gacutil.exe that is installed with the .NET Framework SDK 2.0. This utility is located in the following folder:

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin

To use gacutil.exe to copy the class library DLL into the GAC

To open the Visual Studio command prompt, click Start, point to All Programs, point to Microsoft Visual Studio 2005, point to Visual Studio Tools, and click Visual Studio 2005 Command Prompt.
At the command prompt type a command in the following form, and press ENTER:

gacutil.exe -i “”.

16. What we will do is to copy the 3 files in the mapped _vti_bin (ISAPI) sharepoint folder of our site.

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI

17. Reset Internet Information Services (IIS) for changes in the DLL to take effect (only in GAC deployment necessary)

Now you can call your webservice and consume it like any other SharePoint Webservice. In Solution Explorer, right-click the project, and then click Add Web Reference.

e.g. http://moss.litwareinc.com/_vti_bin/AllSitesService.asmx

Good luck!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: