Service contract, the service and a whole bunch of configuration. All code needed for a simple REST (sort of) service with WCF.
I recently needed to create a simple service that exposed some data in JSON format with WCF. Since it turned out to be a bit trickier than I think it should be, much due to WCF’s extreme need for lots and lots of horrible XML configuration, and because I have a feeling that I’ll need to do something similar in the future I’m posting what I ended up doing for future reference. For more details about how to create a JSON service with WCF I strongly recommend reading Anders Tornblad’s post Creating a JSON-REST service using WCF. My code is largely based on his great series of posts with some differences when it comes to error handling and some configuration quirks (did I say that WCF is configuration heavy?) that I found necessary.
1. Classes to expose
The first thing we need is one or several classes that the service will expose in serialized form. As an example we could have a simple product class. The DataContract and DataMember attributes are optional but enables us to specify different names which is nice if we want to abide by Javascript conventions.
[DataContract(Name = "product")] public class Product { [DataMember(Name = "id")] public int Id { get; set; } //More properties... }
2. A service contract
When we do File->New File in Visual Studio and add a WCF Service three files are added to our project: an interface with a ServiceContract attribute and two files (one for “markup” and one for code) for the actual implementation of the service.
[ServiceContract] public interface IProducts { [OperationContract] [WebGet(UriTemplate = "All", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] Product[] GetAllProducts(); [OperationContract] [WebGet(UriTemplate = "ById/{id}", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] Product GetProductById(string id); }
3. The service
The actual service implements the ServiceContract. In the below example both methods fetch data from a private property. In reality there would probably be some calls to a repository to retrieve domain objects and some mapping to the classes that are exposed through the service (I used AutoMapper to easily to that), either in the service or in an external class.
public class Products : IProducts { public Pharmacy[] GetAllProducts() { return AllProducts.ToArray(); } private IEnumerable<Product> AllProducts { get { //Retrieve and return all products } } public Pharmacy GetProductById(string id) { int idValue; if (!int.TryParse(id, out idValue)) { throw new WebFaultException<string>( "Invalid id parameter. It must be an integer.", HttpStatusCode.BadRequest); } var product = AllProducts.FirstOrDefault(p => p.Id == idValue); if (product != null) return product; throw new WebFaultException<string>( string.Format("Unable to find a product with id {0}", idValue), HttpStatusCode.NotFound); } }
4. Configuration
Finally there’s the configuration.
<services> <service name="Namespace.Products" behaviorConfiguration="jsonRestDefault"> <host> <baseAddresses> <add baseAddress=http://domain.com/productsservice/ /> </baseAddresses> </host> <endpoint name="jsonRestEndpoint" behaviorConfiguration="RESTFriendly" binding="webHttpBinding" contract="Namespace.IPharmacies"> </endpoint> <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="jsonRestDefault"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="RESTFriendly"> <webHttp /> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel>
That’s a lot of XML! Anyhow, our service should now be reachable at http://domain.com/productsservice/Products.svc and the two methods can be reached at http://domain.com/productsservice/Products.svc/all and http://domain.com/productsservice/Products.svc/byid/123 where 123 is a product id.
PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.
Similar articles
- Creating a custom Configuration Section in .NET
- Automatically notify Google and MSN when your site is updated
- XML sitemap with ASP.NET MVC
- Performing and Testing Redirects with ASP.NET Web Forms MVP
- Extending ASP.NET MVC Music Store with elasticsearch
- Handling multiple ASP.NET configuration files with build events
- Twitter style paging with ASP.NET MVC and jQuery
- Syntax highlighting JSON with C#
Comments
comments powered by Disqus