Make Sitecore host WCF
For a long time I’ve been a huge fan of .net remoting. Once you got your head around the architecture, it is a really nice technology to use when you need to make calls across applications. In the past I have done this straight out of Sitecore with no problems.
The general scenario involves 2 Sitecore servers setup in a master / slave configuration where the master server is the content authoring platform and publishes content out to the slave server which only serves content out to the web. On any Sitecore server, we already know if we need to create items which are to be retained, we don’t create them in the web database as they will be lost on the next publish operation. We need to create the items in the master database. But given the master / slave dual server configuration, we can’t even do that; we need to create the item on a different server.
.net remoting has served me well to achieve this outcome. But recently I thought I should pull myself and my cross AppDomain communication techniques into 2008 and do the same with WCF. I also had an additional desire to make use of the new “OneWay” attribute which would allow me to “fire and forget” from the slave server so I didn’t have to wait for confirmation of item creation (again, it was a requirement to not wait for the response. You probably wouldn’t normally do that in your app).
So, with Visual Studio 2008 in hand, and a glimmer in my eye, I set off to create my WCF service to be hosted out of my Sitecore application. Through trial and error I stumbled upon the realization that I had to manually tell my ASP.NET application to host the WCF service. IIS 7 can host WCF services without invoking ASP.NET, so you have to manually do that. So the first thing I did after creating my plain-old-WCF service was to add the AspNetCompatibilityRequirements attribute to my service class and set the RequirementsMode to AspNetCompatibilityRequirementsMode.Required. That would tell my service that it required ASP.NET to run so I could get access to the Sitecore context. I also had to add the <serviceHostingEnvironment aspNetCompatibilityEnabled=”true”/> element to the <system.serviceModel> element in my web.config to tell the ASP.NET application (Sitecore) to host the service. I also added the <services> element to register my service as an endpoint.
OK, all going good. Let’s just hit the service manually to make sure the plumbing is right. So I fire up my browser, navigate to the svc file and get…
Download the svc file? Hang on ASP.NET, shouldn’t you process that file and tell me I need a client to invoke it? Why are you trying to pass me the file? I don’t want it, process it for me!
OK, so I tried many things and spent several hours / days on trying to get Sitecore to process the file instead of serve it. I tried creating a blank WCF project and hosting the service in ASP.NET: all good. I tried hosting the service in Sitecore but using the web.config from the previous blank WCF project: all good. Hmm. So Sitecore was doing something that was upsetting the processing of the svc file.
It got down to comparing the config files line by line. Tearing out the Sitecore stuff in the web.config to peel it back to the basics and try to pin point the element that was causing the problem.
It was late on a Thursday night, in Sydney domestic airport after my flight had been delayed that I finally stumbled upon the culprit element…the nexus httpModule. With that module commented out my service would be processed, not served. But with that module not active Sitecore would not work. What are you doing nexus? I dug around in the web.config for a while hoping to find another element which would allow me to control some of the processing nexus was doing. And I just so happened to find it. The FilterUrlExtensions processor of the preprocessRequest pipeline has a “Allowed extensions” parameter which controls which file extensions will be processed. I altered this element to include the svc extension as such:
<param desc="Allowed extensions (comma separated)">aspx, ashx, axd, asmx, svc</param>
And SUCCESS! Now when I hit the svc file in my browser the file is processed and I get that message telling me I need a WCF client to use the service.