WCF is, on the whole, pretty neat. It’s a doddle to decorate methods with UriTemplates and specify DataMembers. Building the actual meat of a web service is made very easy by the wealth of functionality available in WCF4, and this is the bit I usually happily chip together whenever I need to write a RESTful web service.
Then I get to the part where I have to add the service’s endpoint to web.config. It’s usually been several months since I last did it. I look it up on google, but the results don’t quite seem to apply to me. I open up an old project where I last did this ridiculous dance, but evidently I’m missing something because the damned thing still won’t work. The problem is most likely a subtly mis-set attribute. Or may web.config is just a monster which will eat us all.
With that in mind, I was recently delighted to find this blog post by Steve Michelotti. It’s a little old, but the knowledge within was new to me, so it may be new to you too.
In a nutshell, it leverages the WebServiceHostFactory class to allow a ServiceRoute to your WCF service to be defined. The advantages of this are two-fold:
- No service-specific entries are needed in web.config
- The WCF service can be defined in a plain C# class rather than a .svc file.
Steve covers this in much more detail in his blog post, so what follows is a quick summary of the steps required to get a service up and running:
- Define your service in a C# class (implementing an interface is recommended but not required).
- Decorate your class with
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
This is required for the service to operate over HTTP.
- A teensy bit of web.config tweaking is required. This is the other half of the configuration above.
<system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> </system.serviceModel>
- Add a reference to System.ServiceModel.Activation. This is not to be confused with System.ServiceModel.Activision.
- To add the ServiceRoute, add a line similar to the one below to Application_Start in Global.asax.cs:
RouteTable.Routes.Add(new ServiceRoute("Services", new WebServiceHostFactory(), typeof(Your_Service_Class)));
Where Your_Service_Class is the name of the class you previously wrote for your service. Leaving the first parameter of ServiceRoute blank results in all requests to the service being relative to the site route. Services in the example above is the route prefix of your service url. You can leave it blank, but I prefer to specify a path to keep my services tidily organised. You should decorate your service methods with a suitable UriTemplate, eg
[WebGet(UriTemplate = "MyService", ResponseFormat = WebMessageFormat.Json)]
In the above case the service can be called via a browser on http://my_hostname/services/myservice
That’s it! I can now get on with the meaty business of writing code instead of wrestling with the beast that is web.config.
In the meantime, here are some goats in a tree.