Format Filter for ASP.NET MVC -- getting a little more RESTful.

I developing http://nsfw4.me, I wanted a closer-to-automated way to add extensionbased format filtering to the different controller methods. For integration'ssake, I wanted the clients which may adopt using nsfw4.me tohave an easy way to interact and understand what the outcomes of those interactionswere.  In building this site on Microsoft's newly released MVC framework,it was easy to create a RESTful interface, but I didn't see a baked in way toformat output based on requested extension.

The approach I took was create two new route entries in Global.asax.cs:
 

1:  
2: routes.MapRoute("DefaultFormat", "{controller}/{action}.{format}", 
3:                           new { controller = "Home", action = "Index", id = "", format = "html"});    
4:  
5: routes.MapRoute("DefaultFormat","{controller}/{action}/{id}.{format}",
6:                            new { controller = "Home", action = "Index",id = "", format = "html"});
7:  
8:  

Now, I would be able to pick up an extension on the requested path and act accordingly. For example, if someone visits a details link for a given object, and theywant .xml, then I can give them a serialized version of that data to suit theirneeds.  If someone visits with the default .html (or nothing at all) we cangive a standard html rendering.  

Enter the FormatFilterAttribute class.  This class hangs on a Controller methodand works its magic in the OnActionExecuted method.  It is in this method thatwe make the determination on how to handle the request.  

Note: Thisfilter requires James Newton-King'sJSON Library.

1:        public override void OnActionExecuted(ActionExecutedContext filterContext)
2:         {
3:             if (filterContext.RouteData.Values.ContainsKey("format"))
4:             {
5:                 var fmt = GetFormat(filterContext);
6:                 var obj = GetResultObject(filterContext);
7:                 switch (fmt)
8:                 {
9:                     case "xml":
10:                         if (null != obj)
11:                         {
12:                             XmlSerializer xs = new XmlSerializer(obj.GetType());
13:                             using (MemoryStream Ms = new MemoryStream())
14:                             {
15:                                 xs.Serialize(Ms, obj);
16:                                 var ret = System.Text.Encoding.UTF8.GetString(Ms.ToArray());
17:                                 filterContext.Result =new PlainTextActionResult(ret);
18:                             }
19:                         }
20:                         break;
21:                     case "json":
22:                         if (null != obj)
23:                         {
24:                             filterContext.Result =new PlainTextActionResult(
25:                                 JsonConvert.SerializeObject(obj, Formatting.Indented));
26:                         }
27:                         break;
28:                     case "html":
29:                         //DO NOTHING
30:                         break;
31:                     default:
32:                         throw new ArgumentException("Invalid format supplied");
33:                         break;
34:                 }
35:             }
36:             base.OnActionExecuted(filterContext);
37:         }
38:  

What's happening Here?

As the MVC framework processes the request to this method, we will intercept afterthe user code has run.  At this time we determine whether there was requestfor something other than a standard render and act accordingly.  If a ViewDataKeyhas been set for the attribute, we look for this object in the ViewData collection,if no key is specified, we try getting the data from the Model property of the currentViewData.  This data is then serialized back to the requesting client.  Currently,2 formats are supported: xml and json.

Try it here:

HTML: http://nsfw4.me/links/details/yahoo
JSON:  http://nsfw4.me/links/details/yahoo.json
XML:  http://nsfw4.me/links/details/yahoo.xml

It also works with creating data.   If you post the proper values (LinkId,LinkUrl) to http://nsfw4.me/links/create.xml, you will receive the result, goodor bad in xml format.  The same also applies for .json requests.

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

ASP.NET 2.0 Menu Control - Safari Fix

Note: This advice is provided without warranty, guarantee and manatee.

 Getting the ASP.NET 2.0 Menu control to work with Safari (on OS X) proved itself to be a a bear -- not so much because of the solution, but because everyone blames MS for not fixing it instead of coming up with a solution.  After some tinkering with it, I found a directive I hadn't seen before:

Page.ClientTarget

As it turns out, you can simply set Page.ClientTarget = "uplevel" and the control renders perfectly in Safari.  Of course, we should ensure that we're on Safari which can be done with a simple check in Request.ServerVariables["http_user_agent"].

 All in all, it looks like this: (without the spacing of course :))

protected void Page_PreInit(object sender, EventArgs e)
{

if (Request.ServerVariables["http_user_agent"].ToLower().Contains("safari"))
{


Page.ClientTarget =

"uplevel";


}

}

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: