【问题标题】:How can I extend the content negotiation behavior in MVC4?如何扩展 MVC4 中的内容协商行为?
【发布时间】:2012-03-30 22:52:49
【问题描述】:

我正在研究一个 RESTful API 设计,我在 Programmers StackExchange 网站here 上发布了关于内容协商的问题之一。

基于此,我对如何在 MVC4 中支持以下行为感兴趣:

  1. 如果在 URL 上指定了扩展名(例如,GET /api/search.json/api/search.xml),请覆盖 MVC4 中的默认内容协商行为
  2. 如果未指定扩展名,则使用默认行为检查 application/xmlapplication.json 的接受标头值。

捕获此扩展并修改内容协商行为的最简洁/最直接的方法是什么?

【问题讨论】:

    标签: asp.net rest asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    您可以使用格式化程序中的 UriPathExtensionMapping 来完成此操作。这些映射使您可以将扩展“分配”到格式化程序,以便在内容协商期间优先考虑它们。您还需要添加一个路由,以便也接受带有“扩展名”的请求。下面的代码显示了启用此方案所需的默认模板中的更改。

        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();
        }
    

    【讨论】:

    • 太棒了!这些格式扩展还允许您通过查询字符串参数来驱动它,我认为我更喜欢它。
    • @BrandonLinton - 查询字符串参数如何为您工作?你需要做任何额外的事情来拦截和转换吗?
    • @drzaus 代替AddUriPathExtensionMapping,使用AddQueryStringMapping 扩展操作,像这样:formatter.AddQueryStringMapping("returnType", "json", "application/json");
    • 是否可以将扩展名放在末尾,所以可以使用/api/products.xml/6 代替/api/products/6.xml?这将允许像 IE 这样的浏览器显示数据而不是提示下载。我已经尝试过routeTemplate: "api/{controller}/{id}.{ext}",但这会导致将 id 解析为整数时出错。
    • 我搞定了,这是添加路由的顺序问题,带有 {ext} 的路由应该出现在没有的路由之前。
    猜你喜欢
    • 2014-11-15
    • 2015-01-31
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多