6

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

我还希望能够使用 GET 参数来欺骗此标头以进行调试(我希望这也能持续到 prod)。

这是我目前检测到的方式:

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

这是我的控制器代码中唯一直接接触 Request 对象的地方。我想要一种更干净、更可测试的方式来阅读这篇文章。我理想的解决方案是控制器上的参数。

我尝试了几个关键字来查看默认模型绑定器是否会使用它,但我尝试过的没有任何效果。

那么获取这些信息的最干净的方法是什么?自定义模型绑定器?你能举个例子吗?

4

2 回答 2

2

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

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

于 2012-07-30T23:23:26.963 回答
2

我没有看到任何比自定义模型活页夹更好的替代品。我将在这里发布我的活页夹实现,以防其他人看到。使用模型绑定器允许将 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)

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

于 2012-07-31T16:09:32.813 回答