Friday, July 30, 2010

REST Services in WCF and ASP.NET MVC

So, recently my team has started a project with a large base of legacy code, causing us to switch from the Java world, in which we have a large amount of experience to the .NET world in which we are much more limited. In doing this, one of the first things we needed to determine was how we were going to create Web Services, and if they were going to be in REST or SOAP. After some banter about SOAP and REST, we decided to use REST for now, delivering the responses in JSON. The next obvious question was, how are we going to implement the REST services. Here are the two ways that we have gotten them implemented so far:

To do this, we simply created a new ASP.NET MVC 2 Application. From here, it was a simple matter of adding a Controller to the Controllers folder, and viola, we had a REST Service. The next thing we had to do was to make it return the response in JSON. This was another fairly simple matter, and eventually, we had a method returning an "ActionResult" and ending with this line:

return Json(result, JsonRequestBehavior.AllowGet);

We were disappointed that result had to be an actual object instead of a dynamic object, however (unless we just haven't figured out how to get around that).

We did run into a couple of lessons on this, though:

1. This works great with IIS 7 (and much less great with anything before it). To get around this, we have used wildcard extensions for now. If you are getting 404 errors when trying to hit your Controllers in IIS, but everything works while debugging, Google this, as it will help.

2. Our controller's method really likes being called "Index". I'm sure there's a configuration where we can change this, but we have realized that configurations can be hard to find in .NET.

3. When deploying, there seem to be a large number of files that are always necessary, instead of neatly bundling into a single artifact.

To create a service in WCF is just as simple as creating one in MVC. Just create a new WCF project, and *poof* you have a Web Service. Unfortunately, it's SOAP. To get around this, you have to perform some configuration of your Web.config file. I don't understand all of it, but in the end, this is what I came up with that worked for ours (note that this is just the Services and Behavior tags inside of the system.serviceModel tag - this is not the whole file):

<service name="RestLayerInWCF.Service1">
behaviorConfiguration="webby" binding="webHttpBinding" bindingConfiguration=""
name="Rest" contract="RestLayerInWCF.IService1" />
<behavior name="webby">

Also, we had to mark our services with an extra line:

[WebGet(UriTemplate = "/", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]

We had some observations about this one, too:

1. The Web.config is a pain to figure out the first time.

2. You have to maintain both an Interface and an implementation of each Service.

3. You seem to have to type the .svc to navigate to the service instead of having the freedom to name your service whatever you want.

4. An interesting thing we noticed is that the return of JSON is smarter than I thought. I had a problem here where my method signature returned a string, and so I was converting things to Json to return. This caused them to all return the quotes as \". Instead, I should have just let the method "do it's thing" and return the original object - it converts it to Json for me.

Anyway, now we have the tough decision to make - which one are we going to use? I have no idea....