WCF and SharePoint: context != context
Recently I got interested in Windows Communication Foundation (WCF) Services and SharePoint. I’ve heard some great stories about how WCF can improve the architecture of your solutions. On the other hand I’ve heard some complaints about how complex the integration with SharePoint is. To keep it short: reason enough to check it out myself.
To be honest I haven’t worked with WCF services yet. Somehow the new technology passed me and I didn’t even give it a chance. Recently I stumbled upon Daniel Larson’s book Developing Service-Oriented AJAX Applications on the Microsoft Platform. Not surprisingly Daniel heavily uses WCF services to show us what can be achieved using ASP.NET 3.5. Reason enough to try some things out myself.
So how do you start with WCF and SharePoint? Sahil Malik did a great job covering that particular subject. Sahil wrote a series of topics covering almost every aspect of the process of working with WCF in context of SharePoint: from creating the directory hosting the WCF services, through configuring the SharePoint Web Application to accept WCF requests, to deploying WCF end points as solutions.
One of the steps in configuring a SharePoint Web Application to handle WCF requests is to register a Virtual Path Provider. It turns out that SharePoint doesn’t handle requests to .svc files properly. Sahil did a great job and created a CodePlex project called Winsmarts SharePoint WCF Support which contains all the components required to make it work. The downside is that Sahil didn’t create a SharePoint Solution (.wsp) for it, so you’d have to make one yourself. It’s absolutely worth doing as it’s something you’ll be using in all your SharePoint+WCF projects. I chose the simple approach and used WSPBuilder to get the job done. I copied Sahil’s code, wrapped it in a project and used WSPBuilder to create a Solution for me. To spare you that 10 extra minutes of work I published my WSP on CodePlex @ http://imtech.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28399.
Following Sahil’s instructions I was quite fast up and running: I had my custom WCF service running on a SharePoint Web Application:
Then I decided to take it a step further and check if it properly handles SharePoint context.
Why is context so important?
Every request you make in ASP.NET is wrapped in a context object. That object contains a lot of information including current location, authenticated user, etc. SharePoint uses that mechanism too. Every request made towards a SharePoint site is wrapped in an instance of the Microsoft.SharePoint.SPContext class. Comparing to the plain ASP.NET context object, the SPContext contains a lot of valuable SharePoint-specific information including references to the current Site Collection (SPSite), Site (SPWeb), List (SPList), Item (SPListItem), etc. Considering that almost every action you would perform using a WCF service on SharePoint requires one of these objects it is very useful to have them around instead of instantiating them yourself.
SharePoint context magic
How the context works? If you’ve been working with SharePoint you probably know of the _layouts Virtual Directory. In IIS Manager it looks like a regular IIS Virtual Directory. The cool thing is the SharePoint magic that happens behind the scenes: you can append _layouts to every existing path on your SharePoint site and while it still points to files located in 12\TEMPLATE\LAYOUTS on your web server, it instantiates context objects based on the URL, eg. http://moss/_layouts/settings.aspx opens settings for the Root Site but http://moss/PressReleases/_layouts/settings.aspx opens settings for the Press Releases Site. In both cases we’re requesting the same settings.aspx page located in 12\TEMPLATE\LAYOUTS but it does different things depending on the URL used to call it. See the magic?
Following Sahil’s advice to keep the things clean, I have decided to create a directory called _wcf under the root of my Web Application. Additionally I have created a Virtual Directory pointing to it:
Unfortunately the SharePoint magic wasn’t working for me:
It turns out that the SharePoint magic works for Virtual Directories owned by SharePoint not all Virtual Directories under a SharePoint Web Application. That takes us to two conclusions.
context != context
There is context and context that we’re talking about while referring to a WCF service running on a SharePoint Web Application. The first one is all about making a WCF service available through the URL of a Web Application using the SharePoint technologies. The request gets authenticated and you are able to get some information using the SPContext object. Let’s call it SharePoint context.
The second context is the Site Context. Remember how we were able to call one and the same settings.aspx page in context of different sites (Root Site and Press Releases Site) and make it behave differently depending on the URL? Site Context is all about being able to fully benefit of the context information provided by SharePoint and leverage it for your purposes. As far as I know such functionality is available to Virtual Directories owned by SharePoint only. While debugging the custom Virtual Path Provider I’ve found out that a request to http://moss/PressReleases/_wcf/SharePointTestService.svc is being passed to the Virtual Path Provider as ~/PressReleases/_wcf/SharePointTestService.svc A similar request to http://moss/PressReleases/_layouts/settings.aspx is being transformed to ~/_layouts/settings.aspx before it even hits the Virtual Path Provider! See the difference?
Once again it’s all about context
The second conclusion takes us to a question: do you really need Site Context in your WCF service to make it useful? It depends on what it is supposed to do and how you will leverage the functionality. Theoretically you would be able to get to the data in SharePoint even without the context object. As your service is running on a SharePoint Web Application you could instantiate a reference to Site Collection and all other objects you might need.
Whether your WCF service requires context or not determines your deployment process. WCF services that depend on Site Context must be deployed in one of the Virtual Directories owned by SharePoint: preferably _layouts or _vti_bin (where all SharePoint web services are located by the way).
Many people are concerned about deploying to locations owned by SharePoint. First of all there is a chance that a SharePoint update or a Service Pack, or a future version might deploy a file with the same name to the same location. Any existing file would be overwritten. You could mitigate this by creating a subfolder and store your files there. Choosing a non-general name (something else than wcf) might be a wise choice if you want to be sure that nobody will overwrite your files.
Another thing many people worry about is the security: everything you put in one of the SharePoint’s Virtual Directories is available across the whole Farm. You could partly suppress this by deploying the service’s assemblies to a specific Web Application. Everyone who would try to reference the service through a different Web Application would get a nasty error. It’s not a perfect solution but it could help you to solve some security issues.
On the other hand there might be situations when you won’t be needing the Site Context. In such scenario you can create a Virtual Directory under your SharePoint Web Application and everything will work just fine. One more question you should answer before you make your choice is: just because your service doesn’t need the Site Context today, are you sure it won’t be needing it tomorrow?
WCF services are really powerful and can improve the architecture of your solution. Deploying WCF services to a SharePoint Web Application requires you to configure some components which make calling WCF services possible. While WCF service give you great power of providing data stored in SharePoint to external clients, you have to consider a few things before you determine the architecture of your solution.