On Adding Custom Restful Web Services to SharePoint 2010   7 comments

 

At my shop we have data which resides in SQL Servers and FileNet.  We want this data to be callable from the browser during Sharepoint sessions and we desire this data to be called in a RESTful manner with the results returned in JSON format.  Using Microsoft’s (open sourced) WebAPI in the wild would be simple, easy and fun.  But this is SharePoint and the Framework version supported by SharePoint is (necessarily) Framework 3.5.  So we must use the WCF API and package the delivery of the endpoints using Farm solution.  Ouch.  Without getting into the precise definition what Rest is as a practical matter. for this project,  this means that the browser client calls into the SharePoint web server with an HTTP Get call of the form:

http://YOURSHAREPOINTSERVER:80/_vti_bin/Endpoints.svc/sp/INQ_AGENCY_AGCY_DETAIL?agcy_cd=123

and the results returned are in pure JSON format.

When we work on Sharepoint we normally use a version of CKS – Development Tools Edition extension for Visual Studio.  This is available here as a vsix file.   Although there are several blogs and (older) PDS presentations on custom web services our touch stone blog is Sohels’ Blog.  We learned most of what we know from this blog.  We must step lightly as we develop these Web Services since small errors lead to Http 500 and 404 errors which can drive you CRAZY.  So lets get our ducks in order and move through the processes systematically.  Microsoft support several different types of Web Service factories as documented here and summarized as:

  • SOAP service:  MultipleBaseAddressBasicHttpBindingServiceHostFactory
    • Basic HTTP binding must be used, which creates endpoints for a service based on the basic HTTP binding.
  • REST Service:  MultipleBaseAddressWebServiceHostFactory
    • The service factory creates endpoints with Web bindings.
  • ADO.NET Data Service: MultipleBaseAddressDataServiceHostFactory
    • A data service host factory can be used.

For our purposes we are only interested in the REST Service Factory.

Begin the process by creating a new solution and adding a farm solution as a Sharepoint 2010 project:

image

image

You can change the Site URL later is you need to. It is the Project Property called: Site URL (select the project and press F4).  Be sure that the Assembly name and default namespace are set as you want them before adding any project items. (Project Properties / Open):

image

Now add a Web Service item to this project.  We will use the CKSDev Web Template (on Visual Studio 2010 you may need to search for this template):

image

Open the EndPoints.svc file and change the default Service Factory from MultipleBaseAddressBasicHttpBindingServiceHostFactory to MultipleBaseAddressWebServiceHostFactory .

Now open the interface file (IEndpoints.cs) and replace the entire contents with:

using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using System.Web;

namespace Z
{
[ServiceContract]
public partial interface IEndPoint
[OperationContract]
[WebInvoke( UriTemplate = “SP/Ping”, Method = “GET”, BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json )]
string Ping();

}

}

//mind the word wrap on the WebInvoke line

The file will define what the endpoint will look like.  W are starting with the minimal Endpoint we can define and will add a real world example later in this post.  The attributes ServiceContract and OperationContract should be familiar to you.  The WebInvoke attribute is unique for a HTTP GET Restful call defining the path fragment (SP) the public method name (Ping) and the Format (JSON).  The internal method name is (here) the same as the public method name (but they need not be the same).  Likewise,  the URI path fragment can be omitted.

Open the EndPoints.svc.cs file and replace the contents with:

using Microsoft.SharePoint.Client.Services;
using System.ServiceModel.Activation;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace Z
{
[AspNetCompatibilityRequirements( RequirementsMode = AspNetCompatibilityRequirementsMode.Required )]
public partial class EndPoint : IEndPoint
{
public EndPoint( )
{//this code is always called for EACH method call

        }
public string Ping(  )
{
return “Pong: “;
}

}

}

We want ASP Net Compatibility so application and session cache are available to us.

Now lets set up the deployment package in this project.   Double click on the project folder: Package.  If all has gone well the package design surface should look like this:

image

Do a final build on the project, right click on the project and select Deploy.  Watch your output window you should see a successful Deployment.

Now lets build a simple test program to test this:

use either a console or a Windows Form project including the following code fragments

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;

//your prolog code goes here

string urlString=@”http://{myserver}/_vti_bin/Endpoints/SP/Ping”;

worker( urlString );

private void worker(string urlString )
{
const int _MaxRedirect=4;
const int _MaxHeadersLen=4;
string responseString=string.Empty;
HttpWebResponse response=null;
try
{
HttpWebRequest myRequest =( HttpWebRequest ) WebRequest.Create( urlString );
myRequest.MaximumAutomaticRedirections = _MaxRedirect;
myRequest.MaximumResponseHeadersLength = _MaxHeadersLen;
myRequest.Method = “GET”;
myRequest.UseDefaultCredentials = false;
myRequest.PreAuthenticate = true;

myRequest.Credentials = new NetworkCredential( {yournetworkname},{yournetworkpassword},{yourdomain} );
response = ( HttpWebResponse ) myRequest.GetResponse( );
Stream receiveStream=response.GetResponseStream( );
StreamReader readStream = new StreamReader( receiveStream, Encoding.UTF8 );
string thing=readStream.ReadToEnd( );
responseString = thing;
}
catch ( Exception xx )
{
string httpStatusCode=”Unknown”;
string httpStatusText=”Unknown”;
if ( response != null )
{
try
{
httpStatusCode = response.StatusCode.ToString( );
httpStatusText = response.StatusDescription;
responseString = httpStatusCode + ” – ” + httpStatusText;
}
catch ( Exception xxx )
{
responseString += xxx.Message;
}
}
else
{
responseString += xx.Message;
}
}
finally
{
}

}
}
//mind the word wrap

Everything here should be familiar to you.  The only funny part is the actual URL.

string urlString=@http://{myserver}/_vti_bin/Endpoints.svc/SP/Ping;

The _vti_bin is a virtual folder within the SharePoint application which maps to a real folder:

_vti_bin = {yourdefaultdriveletter}:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\isapi

We can move the actual endpoints to a folder within _vti_bin as will be demonstrated later.  OK run your test program and lets see if you get back the desire “Pong” response.  I’ll wait.

OK everything running smoothly?  lets move the endpoints to a new folder and add a endpoint which does something which does something. In Visual Studio click on the project and select RETRACT.  Watch your output window for success.  To change the folder location to a folder under _vti_bin: click on the .svc file and select properties.  Expand the Deployment Location and add a folder under ISAPI in the Path Property:

image

Our full endpoint path now would be (after deployment): http://{myserver}/_vti_bin/BlogTest.SharePoint.Services/Endpoints.svc/SP/Ping.  Build and deploy the project.  Change your path in the test program and test.  Good Luck.

Now lets add a more useful endpoint.  Retract the solution. Open the interface file (EndPoints.cs) and add code with the IEndpoint interface like:

[OperationContract]
[WebInvoke(Method = “GET”, UriTemplate = “SP/mymethod?ID={ID}”, BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
myreturnclass mymethod(string ID);

Note that myreturnclass must include appropriate attributes to be serializable as JSON.  We do this with code like this:

[DataContract]
public class myreturnclass
{
[DataMember]
public string myID { get; set; }

     public myreturnclass(){string ID){

            myID=ID;

}

}

Now open the implementation file (Endpoints.svc.cs) and add code like the following to the EndPoints class:

public myreturnclass mymethod (string ID)   {

return new myreturnclass(ID);

}
Build the project and Deploy.

Add a second urlString for this new method to your test file and retest.  Good Luck.

Have fun.  I know I did.

 

7 responses to “On Adding Custom Restful Web Services to SharePoint 2010

Subscribe to comments with RSS.

  1. Pingback: On Adding Custom Restful Web Services to SharePoint 2010 « Cloud2013 Or Bust « Sutoprise Avenue, A SutoCom Source

  2. Pingback: Sharepoint 2013: Get Me Out Of Here (Part 2): Cross Domain AJAX Calls in Sharepoint Apps « Cloud2013 Or Bust

  3. I rarely write comments, but i did a few searching and wound up here On Adding Custom Restful Web Services to SharePoint 2010
    | Cloud2013 Or Bust. And I actually do have a couple of questions for you if it’s allright. Is it just me or does it seem like a few of these remarks look like they are coming from brain dead individuals? 😛 And, if you are posting on other online social sites, I would like to keep up with anything new you have to post. Could you list of every one of all your public pages like your linkedin profile, Facebook page or twitter feed?

  4. Fantastic! Thanks!

  5. Pingback: Unbearbeitete Links | Yavuz Bogazci

  6. You will be use this idea for custom restful web services

    Microsoft SharePoint 2007 provided the capability to add custom ASMX web services. Web Services could be deployed to the LAYOUTS folder, or could be deployed to the ISAPI folder and supported accessing site settings and list data under the SharePoint user context. Since SharePoint 2007 was built on the ASP.NET 2.0 model, it did not natively support web service enhancements that were introduced with Windows Communication Foundation (WCF) in .NET Framework 3.0 and 3.5 or the additional WCF-based service frameworks like ADO.NET Data Services (now WCF Data Services).

    For those familiar with writing custom ASMX services for 2007, there were some pitfalls. Since SharePoint requires dynamic service endpoints (the ability to call the web service using any site-relative virtual path under the /_vti_bin/ folder), you had to hand-tool your WSDL files to dynamic service locations. This had to be done every time your changed your web-service signature. Not terribly complicated, but certainly tedious.

    The good news is that SharePoint 2010 is based upon ASP.NET 3.5 and now supports WCF custom services including SOAP, REST, and WCF Data Services. The even better news is that is makes it easy to deploy custom WCF services with dynamic endpoints by supporting a number of custom Service Host Factory implementations that can auto-generate. This means it is not necessary to modify the SharePoint web.config to deploy your service endpoint configurations. In this article, I will walkthrough and highlight the important aspects of the Microsoft SharePoint 2010 support for custom WCF services.

  7. Extremely useful and well written article, thanks!

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: