在.NET MVC中建模绑定Accept头的最简洁方法

时间:2012-07-30 23:14:31

标签: c# json asp.net-mvc-3 model-binding

我正在.NET MVC 3中实现REST层。我正在寻找一种干净的方法来获取Accept标头以确定我是否应该返回Json或Xml。

我还希望能够使用GET参数来欺骗此标头以进行调试(我希望这样做仍然可以生成)。

以下是我目前正在检测到的内容:

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

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

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

那么获取此信息的最简洁方法是什么?自定义模型绑定器?你能提供一个例子吗?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

我没有看到任何更好的替代自定义模型绑定器。我会发布我的粘合剂实现,以防其他人看到这个。使用模型绑定器允许Accept标头强烈绑定到操作的直接输入,允许直接测试返回类型,并且不会强制您人为地拥有比您需要的更多操作,也不会导致动态类型视图数据/袋。

这是带有支持枚举类型的Model Binder:

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)

如果没有人在几天内用更好的方法回应,我会接受这个作为答案。