Tuesday, 7 October 2014

Hosting and Configuring Web Services in SharePoint



WCF services (Rest, SOAP, ADO.Net Data Services) can be hosted in SharePoint. The advantage is that the configuration of wcf services which can be complex is taken care of by SharePoint (up to a point). Also given added complexities/limitations around the same application being extended to use different authentication zones, each wcf end point requiring a different address etc. and the configuration does not remain in the realm of the faint hearted. However SharePoint abstracts away much of that complexity using dynamic configuration or programmatic configuration.


SharePoint implements dynamic configuration of web service endpoints using custom service factories. Out of the box, SharePoint provides the following service factories; depending on the type of service required (SOAP, RESTFUL or ADO.NET Data Service) one of these is referenced in the web service file (.svc file that needs to be added in ISAPI folder in the 15 hive):

Service Type                 Service Factory

SOAP service                 MultipleBaseAddressBasicHttpBindingServiceHostFactory

REST Service                 MultipleBaseAddressWebServiceHostFactory

ADO.NET Data Service MultipleBaseAddressDataServiceHostFactory


Once one of the above is referenced when creating a service, entries in the web application’s web.config are no longer necessary. The referenced service factory dynamically configures endpoint(s) for the service. In fact, trying to add entries to web.config and without ensuring unique addresses for the additional endpoints will cause an error (WCF requires a unique address for every endpoint). 


Configuring Behaviour 


Implementing the service in a code beside file and adding the .svc file to the ISAPI folder should suffice for most cases. However, what if the default configuration/behaviour of the service does not satisfy your requirements. What if you have to change the configuration of the service or change some aspect of its behaviour? For example, the default maximum payload of the service is configured to be 64K. If the payload of your service exceeds this default limit you will get a 413 response status (Request Entity too large). 


If the default configuration of endpoint needs to be modified/tweaked, like in the scenario above, then this can be achieved using the SPWcfServiceSettings object associated with each service. The SPWcfServiceSettings class has properties representing the different wcf settings that are used to control the behaviour of a wcf service.  For the above scenario, to be able to cater for a payload larger than the default 64 K, it is necessary to set the value of theMaxReceivedMessageSize setting. 


There are at least two ways of modifying wcf settings for a web service – have a web application level feature that will do this or use powershell. My preference would be the Web Application level feature because it is naturally integrated with your solution. Following is the sample code to change the wcf service settings, implemented in the feature receiver of a web application level feature: 


public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    ConfigureServiceSettings();
}

private void ConfigureServiceSettings()
{
     try
     {
        var contentService = SPWebService.ContentService;
        var wcfServiceSettings = new SPWcfServiceSettings
        {
            ReaderQuotasMaxStringContentLength = 1073741824,
            ReaderQuotasMaxArrayLength = 1073741824,
            ReaderQuotasMaxBytesPerRead = 1073741824,
            MaxReceivedMessageSize = 1073741824
         };

         contentService.WcfServiceSettings["CustomService1.svc"] = wcfServiceSettings;
         contentService.WcfServiceSettings["CustomService2.svc"] = wcfServiceSettings;
         
         contentService.Update(true);
      }
      catch (Exception ex)
      {
         //Exception handling code
      }

 }


In the above code, the call to SPWebService.ContentService returns a reference to the parent web service (the content service) that is used to access content in the current web application. The content service has a dictionary of SPWcfServiceSettings objects, keyed by the name of the web service. The integer (1073741824) represents the expected maximum size of the payload for your custom web service. For example, the above code will allow for a payload of up to 1GB (1073741824 bytes).Assigning the WcfServiceSettings object with the customized setting will create an entry in the dictionary if one does not exist or overwrite it if one already exists.