Saturday, May 1, 2010

ASP.NET MVC and different output formats

Hi there,

I wanted to mimic the nice behavior of Ruby on Rails that allows you to render different content based on the extension passed on in the URL. Here are a couple of examples:

http://localhost/people/list.json <- list of people in JSON
http://localhost/people/show/1.json <- person with id=1 in JSON
http://localhost/people/list.xml <- list of people in XML
http://localhost/people/show/1.xml <- person with id=1 in XML

The part I was not able to figure out right away was the routing configuration. Here's how I finally did it:
routes.MapRoute(
"ActionWithFormat",
"{controller}/{action}.{format}"
);

routes.MapRoute(
"ActionWithFormatAndId",
"{controller}/{action}/{id}.{format}"
);

routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
format = "html"
}
);

As you can see here I've added 2 additional routes (ActionWithFormat and ActionWithFormatAndId) that contain the additional parameter distinguished by "." (dot) instead of "/" (forward slash). I've also took the liberty to modify the Default route so that when no format is passed the default "html" format is what you'd get passed to the action.

Now suppose you'd like to make use of it in the PersonController's Show action:
public ActionResult Show(String id, String format)
{
var person = new { FirstName = "John", LastName = "Doe" };
switch (format)
{
case "json":
return Json(person, JsonRequestBehavior.AllowGet);
default:
return View(person);
}
}

Sure that the RoR's version is shorted, nicer, purer and all that but this little fellow here does the trick as good as the RoR's :)

The key here is that the format is just a string so if you'd like to come up with (let's say) a PdfActionResult then using it in an action is just dead simple!

I hope you'll find it useful!

4 comments:

The Reverand said...

I love this! The only thing that stands out to me is couldn't you implement this to a certain extent with a custom ViewResult class?
ooooh I feel some code coming on.

The Reverand said...

Wow I am so stupid I missed that the last part was a result. Disregard my comment.

The Reverand said...

OK so I was wrong and it isn't what I thought. What I was talking about was implementing a result class so you could simply say call a method on the controller and produce the desired format with no switch in the action.
And your final code is not that.

Matthias Hryniszak said...

Yeah, my solution was totaly based on how RoR is doin' things. It emulates the way of addressing stuff on the net where HTML pages have an extenstion as well as gifs and jpegs.

This might not be the nicest thing but it's definitely very easy to figure out :)