REST in ASP.NET MVC – Generating XML

Nowadays I have a hobby project – a beer catalog for mobile devices. It sounds pretty simple, but I managed to make it complex – and robust as well.
The solution has three parts: an ASP.NET MVC web site backed up by SQL Server, an iPhone and an Android client. I struggled a lot with WCF, I thought it would be the right way to implement a REST-based service, but couldn’t figure it out myself. Anyway, I had an MVC site up and running, so I thought I can sort this out pretty easy, since I had an object model with five entities – that means five services to the mobile apps.
I’ll write about the mobile clients in a future post. It’s enough to know that they pull the data from the services and store it in their own SQLite 3 databases. Sometimes (maybe once a week) they perform an update, request the data again and overwrite their existing databases – that’s all that there’s relevant now.
So how would you create a REST API in ASP.NET MVC. I felt that I want something terribly simple. I want to say that return this data as XML, without any duplication. The obvious way was to subclass ActionResult. After some inspiration from William Duffy’s RSSResult implementation, I came up with the following code:

    1. public class XMLResult<T> : ActionResult
    2.   {
    3.     private IEnumerable<T> _items;
    4.     private string _rootName;
    5.     private string _typeName;
    6.     public XMLResult(IEnumerable<T> items, string rootName, string typeName)
    7.     {
    8.       _items = items;
    9.       _rootName = rootName;
    10.       _typeName = typeName;
    11.     }
    12.     public override void ExecuteResult(ControllerContext context)
    13.     {
    14.       if (_items == null)
    15.       {
    16.         throw new NullReferenceException();
    17.       }
    18.       XmlWriterSettings settings = new XmlWriterSettings() { Indent = true, NewLineHandling = NewLineHandling.Entitize };
    19.       context.HttpContext.Response.ContentType = “text/xml”;
    20.       using (XmlWriter writer = XmlWriter.Create(context.HttpContext.Response.OutputStream, settings))
    21.       {
    22.         writer.WriteStartElement(_rootName);
    23.         foreach (T item in _items)
    24.         {
    25.           if (string.IsNullOrEmpty(_typeName))
    26.           {
    27.             writer.WriteStartElement(item.GetType().Name);
    28.           }
    29.           else
    30.           {
    31.             writer.WriteStartElement(_typeName);
    32.           }
    33.           foreach (PropertyInfo pi in item.GetType().GetProperties())
    34.           {
    35.             if (pi.PropertyType.IsValueType || pi.PropertyType == typeof(string))
    36.             {
    37.               if (pi.GetValue(item, null) != null)
    38.               {
    39.                 writer.WriteElementString(pi.Name, pi.GetValue(item, null).ToString());
    40.               }
    41.             }
    42.           }
    43.           writer.WriteEndElement();
    44.         }
    45.         writer.WriteEndElement();
    46.       }
    47.     }
    48.   }

* This source code was highlighted with Source Code Highlighter.

I think it speaks for itself. The only thing needs a little explanation is the narrowing of the types in the PropertyInfo loop. I needed only value types and string, nothing else. Since my entities contained BLOB data and navigation properties, I got rid of the rest.
This little class is used as follows:

    1. public XMLResult<Beer> Beers()
    2.     {
    3.       return new XMLResult<Beer>(context.Beers.Where(x=>x.IsApproved.Value).OrderBy(x=>x.Name), “Beers”, “Beer”);
    4.     }

* This source code was highlighted with Source Code Highlighter.

And it works with basically anything, thanks to the generic type parameter. From this startpoint, you can easily implement your own POX (Plain Old XML) services with ASP.NET MVC. In the next post we consider how to extract the entities from the generated XML on the iPhone.


Browser navigation with AJAX pages

Recently I came to this issue, and after a lot of googling around I found a simple and powerful solution so I thought it would be beneficial for everyone to know about it. It’s called jQuery Address, and you can find it on the page of Asual. Let’s download it now.

My main problem was that I’m hijaxing almost all of my links in my ASP.NET MVC application, and doing this prevented me from using the browser’s back and forth buttons. I could easily live with this, but my designer couldn’t so I had to come up with a solution. I must warn everyone that it was just pushed together in a hassle, and you could almost see the duct tape holding it together, but it works (for now). Continue reading