2012-07-30 20 views
6

我在.NET MVC 3中实现了一个REST层。我正在寻找一种干净的方式来获取Accept头以确定是否应该返回Json或Xml。在.NET MVC中建模绑定的最简单方法接受头文件MVC

我也希望能够用GET参数来欺骗这个头文件来进行调试(我希望这个文件也可以坚持下去)。

这里是我当前如何检测这样的:

if (Request.AcceptTypes.Contains("application/json") || Request.Url.Query.Contains("application/json")) 

这是在我的控制器代码的唯一地方,直接接触Request对象。我想要一个更清晰,更可测试的方式来阅读这个。我理想的解决方案将是控制器上的参数。

我尝试了几个关键字来查看默认的模型绑定器是否会启动它,但没有尝试过。

那么,获取这些信息的最简洁方法是什么?自定义模型联编程序?你能提供一个例子吗?

+0

如果你不反对mvc4 webapi,你可以为你处理这个问题。更不用说当你将应用程序迁移到mvc4 +的时候,你将会处理一些MVC已经为你做的事情。搜索mvc4内容类型协商以获取更多信息。 – 2012-07-31 00:14:22

+0

我注意到了这一点,对此我感到非常兴奋,但不幸的是,我无法在RC下发布这个项目,并且我可以告诉我没有4的发布日期。 – Travis 2012-07-31 03:01:10

+0

http://prideparrot.com/blog/archive/2012/3/returning_data_view_from_controller_action – VJAI 2012-07-31 06:03:33

回答

2

动作过滤器属性将是一个很好的干净的解决方案。

有一个很好的教程在这里:http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

+0

感谢您的回答,但如果我正确理解这一点,我需要复制每个操作 - 一个用于Xml,一个用于Json。这对于封装和可测试性来说似乎有点过分。或者我错过了什么? – Travis 2012-07-31 03:02:47

+1

你可以将它注册为一个全局动作过滤器,并在一个过滤器中处理Xml和Json。这不是你所追求的吗?您仍然需要将其存储在ViewData/Bag中,这不像我想的那样“干净”。 – 2012-07-31 03:55:16

2

,我没有看到一个自定义的模型绑定任何更好的选择。我会在这里发布我的binder的实现,以防其他人看到这个。使用模型联编程序允许Accept头强制绑定到动作的直接输入,从而允许直接测试返回类型,并且不会强制您人为执行比您需要的更多操作,也不会导致动态类型化视图数据/袋。

这里的模型绑定有支撑枚举类型:

public enum RequestAcceptType 
{ 
    NotSpecified, 
    Json, 
    Xml 
} 

public class RequestAcceptTypeModelBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (bindingContext == null) 
     { 
      throw new ArgumentNullException("bindingContext"); 
     } 

     RequestAcceptType acceptType = RequestAcceptType.NotSpecified; 

     // Try for Json 
     if (controllerContext.HttpContext.Request.AcceptTypes.Contains("application/json") || controllerContext.HttpContext.Request.Url.Query.Contains("application/json")) 
     { 
      acceptType = RequestAcceptType.Json; 
     } 

     // Default to Xml 
     if (acceptType == RequestAcceptType.NotSpecified) 
     { 
      acceptType = RequestAcceptType.Xml; 
     } 

     return acceptType; 
    } 
} 

这里是在Application_Start方法在Global.asax中的相关位:

ModelBinders.Binders[typeof(RequestAcceptType)] = new RequestAcceptTypeModelBinder(); 

然后用它在你的行动,只是使用枚举类型进行参数(任意名称):

public ActionResult Index(RequestAcceptType acceptType) 

如果没有人用ab响应在几天之内,我会接受这个答案。