How to serve the same data in Json, Xml or Html with Asp.Net MVC

About four weeks ago I went to a small event for developers where one of the speakers (christian dalager) compared Ruby on Rails to Asp.Net Mvc. One of the things that really caught my attention in Ruby on Rails was the ability to have an Action serve content in various formats like Json, Xml or Html just by changing the file extension of the requested resource.

I thought it would be cool if you could do something similar in Asp.net MVC and found it to be quite easy, however if you want to serve your content in Xml, you need to download MvcContrib.

To do this, we need to create a new controller that we can inherit from.

The Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/// <summary>
/// A base controller that will enable you to serve your data in either Json, Xml, Html
/// </summary>
public abstract class FormatController : Controller
{
	/// <summary>
	/// The Key to extract the format from Route Data
	/// </summary>
	private const string FORMAT_KEY = "Format";
 
	/// <summary>
	/// The type of files we can server the requested content in
	/// </summary>
	public enum FileFormat { Html, Json, Xml }
 
	protected FormatController()
	{
		// Our Default format
		RequestedFormat = FileFormat.Html;
	}
 
	/// <summary>
	/// The format that has been requested
	/// </summary>
	protected FileFormat RequestedFormat { get; private set; }
 
	/// <summary>
	/// Occurs before an action is executed
	/// </summary>
	/// <param name="filterContext"></param>
	protected override void OnActionExecuting(ActionExecutingContext filterContext)
	{
		base.OnActionExecuting(filterContext);
 
		var routeValues = filterContext.RouteData.Values;
		if (routeValues.ContainsKey(FORMAT_KEY))
		{
			var requestedFormat = routeValues[FORMAT_KEY].ToString();
			if (IsValidFormat(requestedFormat))
			{
				RequestedFormat = (FileFormat)Enum.Parse(typeof(FileFormat), requestedFormat, true);
			}
		}
	}
 
	/// <summary>
	/// Verifies that the requested format is one that can be servered
	/// </summary>
	/// <param name="requestedFormat"></param>
	/// <returns></returns>
	private bool IsValidFormat(string requestedFormat)
	{
		return Enum.GetNames(typeof(FileFormat)).Any(format => format.ToLower() == requestedFormat.ToLower());
	}
 
	/// <summary>
	/// Returns the content in the requested format
	/// </summary>
	/// <param name="viewModel">Viewmodel</param>
	/// <returns>ActionResult</returns>
	protected ActionResult FormatView(object viewModel)
	{
		switch (RequestedFormat)
		{
			case FileFormat.Html:
				return View(viewModel);
			case FileFormat.Json:
				return Json(viewModel);
			case FileFormat.Xml:
				return new XmlResult(viewModel);
			default:
				throw new FormatException(string.Concat("Cannot server the content in the request format: ", RequestedFormat));
		}
	}
}

Setting it up

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Pizza
{
	public int Number { get; set; }
	public string Name { get; set; }
	public string Price { get; set; }
}
 
public class HomeController : FormatController
{
	public ActionResult Index()
	{
		var pizzas = new[]
			{
				new Pizza {Number = 1, Name = "Pizza 1", Price = "$10"},
				new Pizza {Number = 2, Name = "Pizza 2", Price = "$13"},
				new Pizza {Number = 3, Name = "Pizza 3", Price = "$20"}
			};
 
		return FormatView(pizzas);
	}
}
1
2
3
4
5
6
// Add this to Global.asax
routes.MapRoute(
	"Format",
	"{controller}/{action}.{format}/{id}",
	new {id = ""}
);

Fire up your application and then type something like “home/index.xml” or “home/index.json” in the browser.

Finale word

Imaging that on your website you have different categories that contain products, by applying this technique you will be able to create a REST like webservice for your users in no time, everyone will be able to integrate your website into their own.

Sharing data has never been easier, this is so awesome.

I have submittet this piece of code (and some other stuff) to MvcContrib, I hope that it makes into the project.

Further reading
Controllers and Action Methods in MVC Applications

JSON (JavaScript Object Notation)

Hello Twitter World

A guy named Adam just wrote me and asked if I could make my blog available through Twitter and my first thought was “what a great idea”. So, my next thought was, “how do I do this” and it was actually pretty easy. I added my feed to Twitterfeed.com and of course created an account on Twitter and now I am ready to conquer the world, woohoo (hope it works :p).

Find me here @fatagnus

So thank you Adam for the idea :)

If anyone else has an idea or have a question, please contact me.

Nate Koechley talks about Professional Frontend Engineering

Over the years I have been involved in doing both backend and frontend development, but for some reason there seems to be a lack of understanding and maybe even respect for what Frontend Engineers do.

Maybe it is because that some people think that doing Html, Css, Javascript and so forth is easy, but in reality it can be really difficult, at least if you want to have it done right.

Browsers are the most hostile software development environment imaginable.
Douglas Crockford

Douglas said this when he was talking about browsers on desktop computers, but he later on changed his mind when he saw how much worse it was on mobile.

There are so many things to keep track of when doing frontend development and you don’t have the same benefit as the Backend people do, like compiling your stuff, so you cant really trust what is going on.

In Nate Koechleys’s speech he sums up how many things that a frontend engineer needs to balance out.

A conservative number may be 672 different things we’re trying to balance as we built out these websites. – Nate Koechley

The number doesn’t include things like usability, performance and security.

In my mind, frontend engineers should get lots more credit for the work they do.

Watch Nate Koechley speak

Next Page »