C# 在.NETMVC中对绑定接受头建模的最干净方法
我正在.NETMVC3中实现一个REST层。我正在寻找一种干净的方法来获取Accept头,以确定是否应该返回Json或Xml 我还希望能够使用GET参数欺骗此标头以进行调试(我希望它也能持久化到prod) 以下是我目前检测到的情况:C# 在.NETMVC中对绑定接受头建模的最干净方法,c#,json,asp.net-mvc-3,model-binding,C#,Json,Asp.net Mvc 3,Model Binding,我正在.NETMVC3中实现一个REST层。我正在寻找一种干净的方法来获取Accept头,以确定是否应该返回Json或Xml 我还希望能够使用GET参数欺骗此标头以进行调试(我希望它也能持久化到prod) 以下是我目前检测到的情况: if (Request.AcceptTypes.Contains("application/json") || Request.Url.Query.Contains("application/json")) 这是我的控制器代码中唯一直接接触请求对象的地方。我想要一
if (Request.AcceptTypes.Contains("application/json") || Request.Url.Query.Contains("application/json"))
这是我的控制器代码中唯一直接接触请求对象的地方。我想要一个更干净,更可测试的方式来阅读这个。我的理想解决方案是控制器上的一个参数
我尝试了几个关键字,看看默认的模型绑定器是否能找到它,但我尝试的都没有效果
那么获取这些信息最干净的方法是什么?定制模型活页夹?你能提供一个例子吗?一个动作过滤器属性将是一个好的、干净的解决方案
这里有一个很好的教程:我没有看到比自定义模型活页夹更好的替代品。我将在这里发布我的活页夹实现,以防其他人看到。使用模型绑定器可以将Accept标头强绑定到操作的直接输入,从而允许直接测试返回类型,并且不会强制您人为地执行超出需要的操作,也不会导致动态类型的viewdata/bag 以下是支持枚举类型的模型绑定器:
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;
}
}
public ActionResult Index(RequestAcceptType acceptType)
以下是应用程序启动方法中Global.asax中的相关位:
ModelBinders.Binders[typeof(RequestAcceptType)] = new RequestAcceptTypeModelBinder();
然后,要在操作中使用它,只需使用枚举类型创建一个参数(任何名称):
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;
}
}
public ActionResult Index(RequestAcceptType acceptType)
如果几天内没有人用更好的方法回应,我会接受这个答案。如果你不反对mvc4 webapi,你可以自己处理。更不用说在将来的某个时候,当你将你的应用迁移到mvc4+时,你将成为MVC已经为你做的事情的客户。搜索mvc4内容类型协商以获取更多信息。我注意到了这一点,对此感到非常兴奋,但不幸的是,我无法在RC下交付此项目,而且从我所知,4没有发布日期。@Mark,这与我现在用一个基本控制器和一对访问请求对象的两个助手类似,你特别要求模型绑定,但是你可以考虑创建一个自定义路由对象。重写GetRouteData,您可以在其中检查accept头并设置应执行的操作方法名称。请参阅“谢谢”以获得答案,但如果我理解正确,我将需要复制每个操作——一个用于Xml,一个用于Json。就封装性和可测试性而言,这似乎有点过分。或者我遗漏了什么?您可以将其注册为全局操作筛选器,并在一个筛选器中处理Xml和Json。。这不是你想要的吗?您仍然需要将其存储在ViewData/包中,我想这不是“干净的”。。