views:

921

answers:

3

I'm looking at using ASP.Net MVC as a platform for a REST based Service. I know WCF has built in support for REST services; however, I'm looking at returning multiple types of data depending on the request.

I would like the client to request the content type. So if they send text/html for example I would render my model into Html, if they request text/xml it would return xml. We could also do JSON.

Does anyone see any issues with this?

Not using WCF could increase the complexity of the client when calling the service since they won't be able to auto-generate a proxy; however, in my case, the clients will be either browser requesting html, or java client libraries processing the xml.

Since were not using WCF we need to secure the service; however, I'm thinking we can do this using forms authentication.

The benefit of this is that no matter what type of data the client is requesting it is all going through the same controllers / models etc...

+2  A: 

You might want to take a look at this blog post and the following discussion from Phil Haack:

http://haacked.com/archive/2009/01/06/handling-formats-based-on-url-extension.aspx

His code uses the requested file extension (.html,.json,.xml) to determine the output, but you could just as easily use Accept-Encoding (or both).

Note: I left a comment on Phil's post and still feel strongly that actions should be required to "opt-in" to which rendering methods they support. With HTML rendering you control how much of the viewdata is displayed to the end-user. XML/JSON rendering would likely render everything you pass into the viewdata, regardless of whether you intended it to be publicly visible or not.

Troy
+2  A: 

After reading Haack's post, about using extensions to indicate the content type, I think your better off keying off the Accept Header. Seems more Rest'ish to me, although granted its a little more difficult to fire up a browser and test your url.

I through together a little blog article about doing this and using a ModelBinder to abstract out the HttpContext from your controller: http://jberke.blogspot.com/2009/03/aspnet-mvc-model-binder.html.

Additionally in response to Troy's opt-in comment, I was using the view to render Xml of my model. This allowed me to have different xml formats for the same model. Which makes sense. What if you need to support versioning or different formats for different clients. I don't like the idea of the framework automatically rendering anything.

JoshBerke
+3  A: 

Haack's solution is certainly not the best way to go about it, though it is a good starting point.

For starters, if you are working with the Entity Framework (or decide to switch from Linq to SQL at some later date) JsonResult will break because it cannot serialize object graphs with circular references (typically most data models). Secondly, it exposes multiple end-points for the same resource.

The correct way to do this is to look at X-Requested-With HTTP header to determine if this is an XHR request. Or Content-Type: text/xml request header for XML.

I would recommend you install the Firefox plugin for REST testing which simulates XHR requests. The Tamper Data plugin and a few others allow greater control for testing/debugging. WFetch is a straight up raw HTTP request tool which is also essential for testing and debugging.

I have written an JSON/POX action filter for doing just this. You just need to decorate your classes or methods with the [JsonPox] attribute and they will automatically be exposed as JSON or XML depending on the client.

aleemb
I have been using the Content-Type to indicate if the user wishesh Xml or Html (Which today I actually only support Xml). I plan on having my controller pick either an Html or Xml view which is then responsible for transforming the model into the result. I think this works nicely. Thanks for the feedback and additional information.
JoshBerke