ContentType route constraint in ASP.NET MVC

Posted by Dan on Friday, January 29th, 2010 in Programming |

Update: The functionality of this constraint is incorrect, and should use AcceptTypes, rather than ContentType. I will write an update to it.

The kudos for this goes to ‘Daniel T‘ who wrote the original JSON implementation.

I was helping out on StackOverflow, and I came across a question which asked why a users custom route constraint didn’t work. Their implementation was for JSON only, but there’s no reason why it couldn’t be extended further to encompass any ContentType.

And that’s what I’ve done…

First let’s the ConstraintContentType enum and add a few example MIME types into the description attributes:

  public enum ConstraintContentType
  {
    [Description("text/xml")]
    XML,
    [Description("application/json")]
    JSON,
    [Description("text/html")]
    HTML
  }

Now, let’s create something so that we can get the description attribute:

  public static class Enum
  {
    public static string Description(T value)
    {
      DescriptionAttribute[] da = (DescriptionAttribute[])(typeof(T).GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false));
      return da.Length > 0 ? da[0].Description : value.ToString();
    }
  }

And now the ContentTypeConstraint:

namespace MyWebsite
{
  public class ContentTypeConstraint : IRouteConstraint
  {
    private ConstraintContentType contentType;

    public ContentTypeConstraint(ConstraintContentType constraintType)
    {
      contentType = constraintType;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
      if (routeDirection == RouteDirection.UrlGeneration)
        return true;

        return httpContext.Request.ContentType == Enum.Description(contentType);
    }
  }
}

So how do you use it?

Well…

  routes.MapRoute(
    "JsonOnlyRoute",
    "json/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index" },
    new { contentType = new ContentTypeConstraint(ConstraintContentType.JSON) }
  );

It’s that simple! Now the only content type that matches this route is JSON. Of course, you could easily expand this to include a whitelist/blacklist approach, and also add in more MIME types, but that’s just another reason why the ASP.NET MVC routing system is so great – it’s so extensible!

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Live
  • DotNetKicks
  • email
  • FriendFeed
  • MySpace
  • Ping.fm
  • Reddit
  • RSS
  • Twitter

Tags: ,

5 Comments

  • [...] to Vote[FriendFeed] ContentType route constraint in ASP.NET MVC (1/28/2010)Thursday, January 28, 2010 from [...]

  • Social comments and analytics for this post…

    This post was mentioned on Twitter by Danbo: New blog post: ContentType route constraint in ASP.NET MVC http://bit.ly/blb4xr...

  • [...] This post was mentioned on Twitter by Elijah Manor, George Chatzimanolis, SynteZZZ, SynteZZZ, OryxDEV.NET and others. OryxDEV.NET said: RT @ScottGu: Useful tip RT "ContentType route constraint in ASP.NET MVC" by @danbo http://j.mp/aKjEk6 (via @elijahmanor) [...]

  • Hightechrider says:

    Why use reflection and Enum’s when a simple class would suffice? Maybe something like …


    public class ContentTypeConstraint : IRouteConstraint
    {
    private string contentType;
    private ContentTypeConstraint() {}

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
    if (routeDirection == RouteDirection.UrlGeneration)
    return true;
    return httpContext.Request.ContentType == this.contentType;
    }

    public static readonly ContentTypeConstraint Xml = new ContentTypeConstraint() { contentType = "text/xml" };
    public static readonly ContentTypeConstraint Json = new ContentTypeConstraint() { contentType = "application/json" };
    public static readonly ContentTypeConstraint Html = new ContentTypeConstraint() { contentType = "text/html" };
    }

  • Dan says:

    Yes, that’s certainly another way of doing it that I hadn’t thought of! I will look to including this as a way of doing it in a new version. If you have a website, please can you send me the url so I can give you credit?

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 307 bad guys.

Copyright © 2009-2010 Dan Atkinson All rights reserved.
Desk Mess Mirrored v1.7.2 theme from BuyNowShop.com.