Access Sitecore data with WCF
So, my laptop died. Again. Second time within 12 months. Time to get a new one…but as a result I’ve had to borrow another for this blog post. This laptop is quite under spec’d compared to my previous laptop. In fact, this laptop is actually a netbook with only 1 gig RAM and a 1.66 Ghz atom processor running Windows XP home. Yet I’ve been able to get Sitecore 6.4.1 running on it.
I’m also missing Visual Studio professional and am instead using the Visual Web Developer Express that’s on the machine. Being that I’m running Windows XP home I don’t have IIS installed so I’ll have to use the embedded ASP.NET web server that comes with Visual Web Developer.
A few years ago I was going to write a blog post entitled “Express, Express and Xpress” to show how anyone can start playing and developing on Sitecore for free by using Visual Studio Express, SQL Express and the free-for-personal-use Sitecore Xpress. But when I came to write it there really wasn’t anything to write about, the whole process was straight forward. So with this blog post, I’m just confirming that (e)xpress stack does in fact work.
Recently I had a query from a reader about how to use WCF with Sitecore to export data. So in this post I’ll show how easy it is to host a WCF service inside your Sitecore solution and access it using a Windows console application.
Sitecore is currently tied to the HttpContext
and the API simply won’t work without one. I’ve heard of people trying to fake the HttpContext
but only once have I heard of someone being successful in doing so. Yes, I seem to recall I also tried this, but gave up when I realised it was getting to hard for me to have confidence in the solution. Not to mention the giant web.config
required to configure Sitecore to allow it to run which would need to be merged into the application.
An easier way to interact with the Sitecore API is to realise that Sitecore is an ASP.NET application, and deal with it. Don’t try and force the application to run without an HttpContext
. Instead simply expose the APIs you need through a web service or WCF service. These services are hosted by the Sitecore application inside ASP.NET so there’s an HttpContext
and the API will run. External applications including console and Windows applications can then call those services to do what they need to.
The first thing we’re going to do is create our project. Whether you create your project inside the Sitecore webroot or outside and use post build scripts to copy project files to your Sitecore folder is up to you. I favour the build-outside-webroot model, which I’ve covered before, but on this machine lacking IIS it’s much easier to use the build-inside-webroot model.
The build-inside-webroot project model requires an existing Sitecore instance so go ahead and set one of those up. I’ve create a Sitecore 6.4 instance under c:\inetpub\Sitecore64
. Now I’ll create a new ASP.NET web application project called SitecoreWCF in Visual Web Developer under the site webroot (c:\inetpub\sitecore64\website
) so I can have VWD spin up Cassini for me. By default VWD will put your project inside a folder of the same name, so your project would actually site under c:\inetpub\sitecore64\website\SitecoreWCF
and Sitecore wouldn’t run when you start Cassini. So unload your project, move the project to the Sitecore webroot (don’t copy the web.config
or any aspx
files), delete the old folder and load your project in VWD again. You’ll know you’ve got it right if inside your project in VWD you open the web.config
file and it’s your Sitecore web.config
file.
Also add a reference to the Sitecore.Kernel
dll in the /website/bin
folder and set it’s CopyLocal
property to false.
Next I’ll add a folder to put my service below, just to keep things organised. In Windows explorer create a folder called MyAPI
inside the sitecore modules
folder. Back inside VWD select the “Show All Files” button in the solution explorer then find the MyAPI
folder you just created, right click and select “Include in Project”.
Now we can create the WCF service by right clicking the MyAPI
folder and selecting add, new item, WCF service. Call the new WCF service MyAPI.svc
. Visual Studio will now create the SVC file, code-behind and interface for the service. It will also update your web.config
file to expose the service.
Sitecore has a great configuration patching system built in to allow adding or updating configuration through succinct include files. The benefit of this is that you don’t need to modify the Sitecore web.config
file which is quite large (except changing the data folder). This makes it much easier to update Sitecore when the update includes web.config
updates. if you’d made changes to the web.config
file then you’d have to either update the new web.config
with your changes, or update your customised web.config
file with those that Sitecore have included in the release.
Unfortunately the config patching system only works for Sitecore configuration, which is understandable. But ASP.NET already includes a hierarchical configuration system. A web application can include web.config
files in folders of the application to have those changes apply only to that folder. So rather than leaving my WCF configuration in the web.config
file and needing to apply that configuration when I update, I’ll instead move the WCF configuration into a separate web.config
file in the same location as the SVC
file. This will also make it much easier to distribute the service as there wouldn’t be any web.config
updates required to the application running the service.
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I’ll add a new method to the service interface file and stub it out in the code-behind as well. Open the IMyAPI.cs
file and add the following method declaration.
[OperationContract]
string GetItemXML(string id);
Now create the method stub in MyAPI.svc.cs
file.
public string GetItemXML(string id)
{
}
This method should accept an item ID or path as a string, find the item in the database then return the item’s XML. A note about context here though.
If you were to start coding the body of this method you’d be inclined to use the Sitecore context database only to find it’s null. This is because the Sitecore context site and item are both null. This just means we have to get the database ourselves. Which database to get? That will depend on what your doing with your data. If you’re only interested in published and approved content then use the web database. If your after item data to backup then use the master database. I’m going to use the master database for this example. The code below grabs the master database then finds the item and returns it’s XML. This is the body of the GetItemXML
method.
var database = Sitecore.Configuration.Factory.GetDatabase("master");
var item = database.GetItem(id);
if (item != null)
return item.GetOuterXml(false);
else
return "item not found";
Now we have our WCF service we need to implement a WCF client to call the service. I’m going to create a Windows Console application, but Visual Web Developer doesn’t do Windows applications, so we’ll have to rip out one of the other weapons in the Visual Studio Express arsenal. And all I have on this machine is Visual Basic Express. Well, I suppose in the spirit of this “let’s try new approaches” post…
In Visual Basic Express create a new Windows console application then right click in your solution and select “Add Service Reference”. Make sure you have your Sitecore solution running in Visual Web Developer by selecting the debug menu then either “start debugging” or “start without debugging”. In the “Add Service Reference” dialog enter the URL of your WCF service.
http:/sitecore modules/MyAPI/MyAPI.svc
Alter the port above to what Cassini is using.
Click the “Go” button to find the service and after the service has been discovered define the namespace as MyAPI
then click OK. If all goes well Visual Basic Express will create you a client proxy to use.
We can now call the WCF service through the client proxy inside the console application. The following code creates the client, calls the service method then outputs the item XML returned to the console. Keep in mind the below is in VB, not C#.
Dim client = New MyAPI.MyAPIClient
Console.WriteLine("Please enter an item ID or path")
Dim input = Console.ReadLine
Dim xml = client.GetItemXML(input)
Console.WriteLine(xml)
Now run the client with a valid item ID and the item’s XML will be written to the console.
And there you go. A WCF service running in Sitecore, using the Sitecore API and being called by a console application written in VB.
Now you can go and try and wash the VB off your hands :)
Alistair: Very nice article could you share the source code with us.