Tuesday, April 28, 2009

Rendering to Xml with ASP.Net MVC

 

Warning: This is my first post using Windows Live Writer so if things don’t come out right I apologize.

I have been working lately on using the ASP.Net MVC platform as a rest based endpoint. My current consumer is looking for xml documents of our model; however, in the future I’d love to move our web site over as well. I have been playing around with a couple of different ways to render xml content from a view.

I have seen some approaches on the web which use an automatic serialization mechanism to convert your model into xml or json. I feel that this should not be done automatically but you should be able to customize the rendering however way you need. This has led me to try out three different options to date.

Option 1 Serializing a DTO

The first approach I tried was to take my DTO and get into Xml the quickest easiest way possible. The XmlSerializer. This broke down a little bit when I discovered I actually needed two DTO’s. This method I used a helper method in a code behind file. So my view looks like:

<%@ Page Language="C#" Inherits="MyViewToXml" CodeBehind="MyViewToXml.aspx.cs"  %> 
<%this.RenderToXml(); %>




Now if we look at RenderToXml we can see the magic here:




Response.ContentType = "text/xml";
Response.Write("<MyRoot>");

var dcs = new DataContractSerializer(typeof(List<DTO1>));
dcs.WriteObject(Response.OutputStream, this.Model);

var dcs2 = new DataContractSerializer(typeof(IList<DTO2>));
IList<DTO2> bfs = (IList<DTO2r>)this.ViewData["DTO2"];

dcs2.WriteObject(Response.OutputStream, bfs);

Response.Write("</MyRoot>");



I like this approach in that it was quick easy, and gave me full control, but it doesn’t sit well with me. It feels like I am grinding against the purpose of having a view. So let’s look at option 2.



Option 2 Embracing MVC View



My next shot was to serialize a much more complex object. In my actual case I don’t have a DTO defined, and I need to have even more control over the Xml being generated. Serialization by the framework won’t cut it, and I wasn’t go back 10 years to the days of having build xml via strings or even via a DOM. So what does that leave me with?




<Order Id="<%=this.Model.Id%>"  Number="<%=this.Model.Number%>">

<Customer Company="<%=this.Model.CompanyName %>">
<Address Line1="<%=this.Model.Address.Line%>"
City="<%=this.Model.Address.City %>"
State="<%=this.Model.Address.State %>"/>
</Customer>

<ShipTo Name="<%=this.Model.Location.Name %>">
<%if (!this.Model.ShipTo.Equals(this.Model.Contact.Address))
{ %>
<Address City="<%=this.Model.ShipTo.City %>"
State="<%=this.Model.ShipTo.State %>" />
<%} %>
</ShipTo>

<Items GrandTotal="<%=this.Model.CalculateGrandTotal()%>"
IsOverride
="<%=this.Model.IsGrandTotalOverridden %>">
<%foreach(var item in this.Model.Items) {%>
<Item Name="<%=item.Name%>" Total="<%=item.Total%>" />
<%} %>
</Items>
<Order>



Here we are embracing the view and generating our xml just as if we were rendering an Xhtml view of the domain. This is neat; however, it is a little verbose so I started to question what else is out there.



Option 3 Finding Alternate View Engines



Asp.Net MVC is very extensible. If you don’t like the view engine go find a new one or write your own. I ran across a port of HAML called NHAML. This can simplify the syntax to look at; however, NHAML’s tooling is not there. If you want intellisense or color highlighting, its just not there.



Further more it treats white space as significant characters. For example to nest elements you would need to do:




%Order
  %Customer
    %Address


Child elements are indented by two spaces. While this frees you from worrying about closing all your tags, its a little counterintuitive. There are other view engines out there, which I am looking forward to running through their paces.

No comments: