Monday, 13 February 2012

SharePoint 2010 - When Hosting Custom WCF Services in SharePoint, SPContext is Null due to MultipleBaseAddressBasicHttpBindingServiceHostFactory Bug

The recommended way to expose a WCF Service through SharePoint 2010 is to NOT manipulate the Web.Config manually/through code to set your WCF bindings.

Instead, it is recommended that you use one of the Service factories provided for you as part of the  Microsoft.SharePoint.Client.Services namespace. These generate the neccessary bindings entries for you.
The 3 types of Binding Service Host Factories are as below:
  • SOAP = MultipleBaseAddressBasicHttpBindingServiceHostFactory (WARNING This has Bugs if the site collection is not at the root)
  • REST = MultipleBaseAddressWebServiceHostFactory
  • Data Service = MultipleBaseAddressDataServiceHostFactory 
There appears to be a bug in MultipleBaseAddressBasicHttpBindingServiceHostFactory that means that the endpoints generated by that factory are only correct if the site is hosted in the root. If your site collection is hosted in say /sites/myportal and you deploy your WCF Service there, then the endpoint will be:
http://servername/mycompanyname/_vti_bin/myportal/CommonService.svc when it should really be
http://servername/mycompanyname/sites/myportal/_vti_bin/CommonService.svc

Consequently if you try to query this with the default bindings then the requests will work but they wont have a valid SPContext even though the HTTP Context is valid and has a valid authenticated user (e.g. when calling through SOAPUI, the WCF Test tool or otherwise (e.g. jQuery).

I wondered why the examples that Microsoft provides work (See the "Revert" WCF Sample here http://msdn.microsoft.com/en-us/library/ff521582.aspx) - and it is because the Microsoft samples actually override the bindings in the client side code and use a constructor overload of WCF classes that accepts the bindings and the endpoints as parameters. This is clearly not an option in say jQuery - so it is not an ideal example at all. Take away the endpoints set in code and calls to SPContext will fail.

I confirmed this behaviour by turning off the loopback exclusion in Fiddler and executing the same calls and saw that indeed the WCF service was trying to connect to an invalid location at the root of my server. This is why the SPContext was null when calling my custom SharePoint WCF Services.

Workarounds:
1) Don't use the SOAP binding factory if you need to deploy your WCF services outside the root. You can manually change/script the web.config changes to add the correct bindings there.
2) Use the REST factory as it doesn't suffer from the same issue.

DDK

1 comment:

TruthSeeker said...

Want a link exchange? Offer any nicher PR0-3. if interested write dorkster100@gmail.com