Writing Custom Web Services for SharePoint
As a SharePoint developer, you may want to use some of the capabilities of Windows SharePoint Services to create custom Web services of your own.
In this sample I will show you how to use the SharePoint to create a custom Web service inside SharePoint.
Writing a Custom Web Service
Create new ASP.NET Web Service Application (MySPServices) as shown in the following figure:
Next, add new Service Library (MySPServicesLibrary) project to the ASP.NET Application:
Add to MySPServicesLibrary project a reference to System.Web.Services.
Rename Class1.cs in MySPServicesLibrary project to MySPService.cs, and insert your web service code. In this sample the following code describes MySPService.cs:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.ComponentModel;
6 using System.Web.Services;
7
8 namespace MySPServicesLibrary
9 {
10 /// <summary>
11 /// Summary description for Service1
12 /// </summary>
13 [WebService(Namespace = "http://tempuri.org/")]
14 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
15 [ToolboxItem(false)]
16 public class MySPService : System.Web.Services.WebService
17 {
18
19 [WebMethod]
20 public void AddEntity(Entity customer)
21 {
22
23 }
24 }
25
26 public class Entity
27 {
28 public string Name { get; set; }
29 }
30 }
In MySPServicesLibrary, righclick on the project name and select properties, then select Signing tab, for signing the assembly:
Build MySPServicesLibrary project.
Open Visual Studion Command Prompt, and type the following command:
sn -Vr MySPServicesLibrary.dll
This will result a Public Key Token. View the markup of the MySPService.asmx (Right Click –> View Markup) and replace the following line:
<%@ WebService Language="C#" CodeBehind="Service1.asmx.cs" Class="MySPServices.Service1" %>
With this line, and update the PublicKeyToken you get from using the sn tool.
<%@ WebService Language="C#" Class="MySPServicesLibrary.MySPService, MySPServicesLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=55D195EC7508F2D2" %>
In MySPServices application, removes Service1.asmx.cs, and rename Service1.asmx to MySPService.asmx.
Add reference from MySPServices application to MySPServicesLibrary.dll and test that your web service is working.
Generating and Modifying Static Discovery and WSDL Files
Copy MySPServicesLibrary.dll into the GAC (C:\WINDOWS\assembly).
Open the Visual Studio .NET command prompt, and go to the LAYOUT directory:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS
Copy MySPService.asmx into this directory.
Run the following command:
disco.exe /MySPService.asmx">/MySPService.asmx">http://<your service url>/MySPService.asmx
The output is two files:
- MySPService.disco
- MySPService.wsdl
Open CustomerService.disco and CustomerService.wsdl, and replace the first line in both files:
<?xml version="1.0" encoding="utf-8"?>
with the following content:
<%@ 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"; %>
Rename the files MySPService.disco to MySPServicedisco.aspx and MySPService.wsdl to MySPServicewsdl.aspx .
Updating MySPServicedisco.aspx
In the .disco file, replace the contactRef and soap tags with the following content:
<discovery xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="
http://www.w3.org/2001/XMLSchema"
xmlns="
http://schemas.xmlsoap.org/disco/"
>
<contractRef ref=""
<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + "?wsdl"),Response.Output); %> docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> xmlns="http://schemas.xmlsoap.org/disco/scl/" />
<soap address=""
<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
xmlns:q1="http://schemas.microsoft.com/sharepoint/soap/" binding="q1:MySPServiceSoap" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
<soap address=""
<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> xmlns:q2="http://schemas.microsoft.com/sharepoint/soap/" binding="q2:MySPServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
</discovery>
Updateing MySPServicewsdl.aspx
In the .wsdl file, replace soap:address and soap12:address tags with the following content:
<wsdl:service name="MySPService">
<wsdl:port name="MySPServiceSoap" binding="tns:MySPServiceSoap">
<soap:address location=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> />
</wsdl:port>
<wsdl:port name="MySPServiceSoap12" binding="tns:MySPServiceSoap12">
<soap12:address location=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> />
</wsdl:port>
Copy the files MySPServicedisco.aspx MySPServicewsdl.aspx and MySPService.aspx into directory: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI
Goto the following URL to verify the web service successfully created:
http://MyServer/_vti_bin/MySPService.asmx
http://MyServer/_vti_bin/MySPService.asmx?wsdl
http://MyServer/_vti_bin/MySPService.asmx?disco
Consuming the SharePoint Web Service
Create new console application project and add a web reference to the new custom web service. The following code show how I can use the web service I created:
1 static void Main(string[] args)
2 {
3 try
4 {
5 MySPServiceSoapClient svc = new MySPServiceSoapClient();
6
7 Entity entity = new Entity()
8 {
9 Name = "SampleEntity"
10 };
11
12 svc.AddEntity(entity);
13
14 svc.Close();
15 }
16 catch (Exception ex)
17 {
18 }
19 }
If you get the following security exception:
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'.
Go to the client app.config and change the security settings of the WCF binding as follows:
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Windows"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
Working with Master Pages
For many sites, there is a need for reusable way for maintaining a standardized appearance across the entire site. Those sites include common headers, footers and menus.
Master Pages in ASP.NET 2.0 consists of two conceptual elements:
- Master Pages
- Content Pages
At runtime, the ASP.NET engine combines these elements into a single page for the end user.
Master Pages is a feature coming in ASP.NET 2.0, which enables to create sites with a common appearance driven by a single template. You can create a single template page that can be used as a foundation for any number of ASP.NET content pages in your application.
Master Pages
Master page file serves as the template for other pages, and contains the top-level HTML elements like header, navigation, footer, Ad space and common items.
The main differences between standard ASP.NET page to master page:
- <%@ master %> directive
- .master extension
You can add master pages in the same way you add .aspx pages – choose Master Page option when you add new item to your application, as shown in the following figure:
The default master page that created for you contains the following content:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site1.master.cs" Inherits="MasterPages.Site1" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Content Pages
Content Pages are ordinary aspx pages, that contains a reference to a master page. Their purpose is to provides the content for the inherited master page template.
The following code is the content of Default.aspx, which cause the result in the below image. In each asp:content tag you specify for which ContentPlaceHolderID in the master page to insert the content.
<%@ Page="" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="MasterPages._Default" MasterPageFile="~/Site1.Master" %>
<asp:content ID="Content1" ContentPlaceHolderID="head" runat="server">
Default page
</asp:content>
<asp:content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
This is the content for the default page.
</asp:content>
One of the implications of this implementation is that master page is just another control in your page, which means it accessible in code:
void Page_Load(object sender, EventArgs e)
{
HtmlForm form = Master.FindControl("form1") as HtmlForm;
if (form != null)
{
}
}
Using Visual Studio 2008 Designer
The great thing in master pages in Visual Studio 2008 is that you can use the designer and switch to code as any .aspx page. For example for the following master page:
<%@ Master="" Language="C#" AutoEventWireup="true" CodeBehind="Site2.master.cs" Inherits="MasterPages.Site2" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<table cellpadding="3" border="1">
<tr bgcolor="yellow">
<td colspan="2">
<h1>My Home Page</h1>
</td>
</tr>
<tr>
<td>
<asp:ContentPlaceHolder ID="ContentPlaceHolder3" runat="server">
</asp:ContentPlaceHolder>
</td>
<td>
<asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server">
</asp:ContentPlaceHolder>
</td>
</tr>
<tr>
<td colspan="2">
Copyright 2009
</td>
</tr>
</table>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Lets change the Default.aspx page as follow:
<%@ Page="" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="MasterPages._Default" MasterPageFile="~/Site2.Master" %>
<asp:content ID="Content1" ContentPlaceHolderID="head" runat="server">
Default page
</asp:content>
<asp:content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
This is the content for the default page.
</asp:content>
<asp:content ID="Content4" ContentPlaceHolderID="ContentPlaceHolder3" runat="server">
ContentPlaceHolder3
</asp:content>
<asp:content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder4" runat="server">
ContentPlaceHolder4
</asp:content>
You can edit the master page using the Visual Studio 2008 Designer as shown in the following figure:

Conclusion
Master pages is a great enhancement to your web pages, and by using a single template page it can be used as a foundation for any number of ASP.NET pages in your site. This template make it easier to develop and manage sites, and supported by the Visual Studio 2008 Designer.