woensdag 26 oktober 2011

Creating a WCF service in SharePoint 2010 using JSON

Recently I was trying to create a REST WCF service which uses JSON and although there are a lot of articles that talk about it, I couldn’t find one which contained a totally working example for SharePoint 2010. So to spare you some hours of frustration, I will share this information with you Smile .

1. Download the CKS tools
Because Visual Studio 2010 doesn’t have out of the box templates to quickly develop a WCF service, I downloaded and installed the CKS tools.

2. Create WCF Service
In your project, add a new WCF service from the CKS templates. You will notice that the template will always create an interface and a SVC + code behind file.

Untitled

3. Add your method prototypes to the interface
Open the interface file and add prototypes for each of your service methods.

   1: namespace MyNamespace
   2: {
   3:     // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ISubscriptionService" in both code and config file together.
   4:     [ServiceContract]
   5:     public interface IWCFService1
   6:     {
   7:  
   8:         [OperationContract]
   9:         [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
  10:         MyMethodAnswer MyMethod(string p1, int p2);
  11:  
  12:     }
  13:  
  14: }

What’s the most important here is the WebInvoke tag. It specifies the method uses POST, that the JSON format is used to accept and return data and that the sent data must be wrapped in a wrapping element (more about that later).

4. Edit the SVC file


By default it points to the code behind file. Let’s change it to the full assembly name. I also got rid of the Factory property.

   1: <%@ ServiceHost Language="C#" Debug="true" 
   2: Service="MyNamespace.MyClass, MyAssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d373e6657f243d25" %>

5. Implement your methods.

As you can see, the method is returning a ‘MyMethodAnswer’ object. You can use this if you want to return more than just a primitive type. Just make sure that object can be serialized. These methods are implemented in the ‘MyClass’ class.

   1: public MyMethodAnswer MyMethod(string p1, string p2)
   2: {
   3:     
   4:     // Implement
   5:  
   6: }

6. Prepare the web.config

I always create a separate web.config which holds the WCF service’s configuration. It’s better to deploy the SVC file in it’s separate subfolder in the ISAPI folder (automatically done by Visual Studio). The important thing is to also deploy the web.config there. Therefore I also create an ISAPI/MyAssemblyName folder in the Visual Studio project. In there, I create the web.config.

   1: <?xml version="1.0"?>
   2: <configuration>
   3:  
   4:   <system.serviceModel>
   5:  
   6:     <!-- we need this to enable session -->
   7:     <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
   8:     <behaviors>
   9:       <endpointBehaviors>
  10:  
  11:         <!-- our configuration for rest relies on web http -->
  12:         <behavior name="RestBehavior">
  13:           <webHttp />
  14:         </behavior>
  15:  
  16:       </endpointBehaviors>
  17:  
  18:       <serviceBehaviors>
  19:         <behavior name="NewBehavior" >
  20:           <serviceMetadata httpGetEnabled="true" />
  21:           <serviceDebug
  22:             httpHelpPageEnabled="true"
  23:             includeExceptionDetailInFaults="true"
  24:           />
  25:         </behavior>
  26:       </serviceBehaviors>
  27:  
  28:     </behaviors>
  29:     <bindings>
  30:       <webHttpBinding>
  31:  
  32:         <!-- a selection of security bindings that you can use in the service registration below-->
  33:         <binding name="WindowsAuthenticationBasicHttpBinding">
  34:           <security mode="TransportCredentialOnly">
  35:             <transport clientCredentialType="Windows" />
  36:           </security>
  37:         </binding>
  38:         <binding name="NoSecurityHttpBinding">
  39:           <security mode="None">
  40:             <transport clientCredentialType="None" />
  41:           </security>
  42:         </binding>
  43:  
  44:       </webHttpBinding>
  45:  
  46:     </bindings>
  47:     <services>
  48:  
  49:       <service name="MyNamespace.MyClass" behaviorConfiguration="NewBehavior">
  50:         <endpoint address=""
  51:                 binding="webHttpBinding"
  52:                 behaviorConfiguration="RestBehavior"
  53:                 contract="MyNamespace.IMyClass"
  54:                 bindingConfiguration="WindowsAuthenticationBasicHttpBinding">
  55:         </endpoint>
  56:       </service>
  57:  
  58:     </services>
  59:  
  60:   </system.serviceModel>
  61:  
  62: </configuration>
First of the all the web.config contains information about how the end point and the web service behave. This is defined in the behavior tags. Please note that the behaviors are used in the service definition.

In the bindings we define two authentication methods. The first one is the standard Windows authentication. The second one has no authentication.

Last thing is the service itself. The name itself doesn’t really matter. Just make sure you correctly reference the behavior configuration in the service and endpoint tag.


Make sure the ‘contract’ property is correctly set. This must point to your interface class in the correct namespace.

7. Deploy

What’s left right now is packaging and deploying it. You can then surf to the SVC file using your browser. If everything is right, you will see a page that starts with

   1: You have created a service.
   2:  
   3: To test this service, you will need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:
   4:  

and what follows is some info about how to talk with your service.


8. Test the communication

Building the service is one thing, communicating with it is something else. It’s not always clear what exact data the service expects and what kind of data it will send back. Here are some tips to help you:

- In the same folder as the SVC file, create an html file with some simple JQuery:

   1: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
   2: <html>
   3:     <head>
   4:         <title></title>
   5:         <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
   1:  
   2:     </head>
   3:     <body>
   4:     
   5:         <script>
   6:  
   7:             jQuery.support.cors = true;
   8:  
   9:             var url = 'http://myserver/_vti_bin/mySubFolder/MyService.svc/MyMethod';
  10:  
  11:             $.ajax({
  12:                 url: url,
  13:                 dataType: "json",
  14:                 type: "POST",
  15:                 data: '{ "p1": "Parameter1", "p2": "54321" }',
  16:                 contentType: "application/json; charset=utf-8",
  17:                 dataFilter: function (data) { return data; },
  18:                 success: function (data) {
  19:                     alert('success');
  20:                 },
  21:                 error: function (XMLHttpRequest, textStatus, errorThrown) {
  22:                     alert(errorThrown);
  23:                 }
  24:             });
  25:  
  26:         
</script>
   6:  
   7:     </body>
   8:  
   9: </html>

This small piece of JavaScript is very powerful when you quickly want to test your WCF service. First, reference the jquery.js file (via the Internet or a local URL).

jQuery.support.Cors = true is meant to enable cross domain scripting. But not always necessary.

Next, specify the URL of the method you want to use.

And then finally, perform the Ajax call. It’s important you use and correctly specify all these parameters. Make sure that the dataType and contentType are correctly set. Also make sure the type is POST as we specified this earlier. Next big thing is the data property. As you can see, the parameter names are exactly the same as in C#.

If the call succeeds or fails, separate JavaScript is executed.

You can also use cUrl to make quick calls to the service but I will not go deeper into this here.

- Use the IE9 developer tools

They allow you to monitor the data that is sent and received so you can immediately see if everything is OK there. Do this by visiting your test HTML file, press F12, go to the ‘Network’ tab, click ‘Start capturing’. Then reload the test page, get back to the test HTML file and take a look at the POST entry.

If you click it, you can see the sent and received data in respectively the ‘Request body’ and ‘Response body’ tabs.

1 opmerking: