Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I extend the content negotiation behavior in MVC4?

I'm working through a RESTful API design, and one of the questions I have about content negotiation I've posted to the Programmers StackExchange site here.

Based on that, I'm interested in how I would support the following behavior in MVC4:

  1. If an extension is specified on the URL (e.g., GET /api/search.json or /api/search.xml), override the default content negotiation behavior in MVC4
  2. If no extension is specified, use the default behavior of examining the accept header value for application/xml or application.json.

What would be the cleanest / most straightforward way of capturing this extension and modifying the content negotiation behavior?

like image 636
Brandon Linton Avatar asked Jan 17 '23 05:01

Brandon Linton


1 Answers

You can use the UriPathExtensionMapping in the formatters to accomplish that. Those mappings let you "assign" an extension to a formatter, so that they're given precedence during content negotiation. You also need to add a route so that requests with "extension" are also accepted. The code below shows the changes required in the default template to enable this scenario.

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapHttpRoute(
            name: "Api with extension",
            routeTemplate: "api/{controller}.{ext}/{id}",
            defaults: new { id = RouteParameter.Optional, ext = RouteParameter.Optional }
        );

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        GlobalConfiguration.Configuration.Formatters.XmlFormatter.AddUriPathExtensionMapping("xml", "text/xml");
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.AddUriPathExtensionMapping("json", "application/json");
        BundleTable.Bundles.RegisterTemplateBundles();
    }
like image 185
carlosfigueira Avatar answered Jan 31 '23 01:01

carlosfigueira