【问题标题】:How should a C# Web API model binder provider work?C# Web API 模型绑定器提供程序应该如何工作?
【发布时间】:2014-08-19 15:20:07
【问题描述】:

我有以下几点:

  • 请求网址:'endpoint/1,2,3?q=foo'
  • 请求绑定的动作: 公共对象 Bar([ModelBinder] List ids, [FromUri] string q)

我想将“1,2,3”片段映射到“ids”参数,所以我根据this link创建了一个ModelBinderProvider,它应该调用正确的模型绑定器。

public class MyModelBinderProvider: ModelBinderProvider
{
    public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
    {
        IModelBinder modelBinder = null;

        if (modelType.IsGenericType && (modelType.GetGenericTypeDefinition() == typeof(List<>)))
        {
            modelBinder = new ListModelBinder();   
        }

        return modelBinder;
    }
}

我像这样在 Global.asax 中注册了提供程序:

GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, new MyModelBinderProvider());

原因:我创建此提供程序是因为我希望,无论 T 是什么('1,2,3' 或 '一、二、三'),绑定都能正常工作。

问题: 假设 T 是 'int';每次发送请求时,'modelType' 参数始终是 'int' 而不是我所期望的 - 'List',因此请求没有得到正确处理。

奇怪的事情:做这样的事情是可行的,但 T 是专门的,因此不是我想要的:

var simpleProvider = new SimpleModelBinderProvider(typeof(List<int>), new ListModelBinder());
GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, simpleProvider);

我看不到我做错了什么,为什么'modelType'参数不是预期值?

【问题讨论】:

  • 请详细说明您为什么要这样做?您认为这很有用的实际情况是什么?因此,这似乎是对可能具有完全不同 URI 的更复杂解决方案的一种破解。

标签: asp.net asp.net-mvc asp.net-web-api asp.net-mvc-5 asp.net-web-api2


【解决方案1】:

这是一个非常古老的问题,但我在这里遇到了与旧代码类似的问题。

逗号是保留的,应该避免使用,尽管它们在某些情况下有效,但如果你真的想使用它们......

一旦“1,2,3”是 url 的路径部分,我认为这比模型绑定器更像是一个路由问题。假设我写了一个小 RouteHandler 来解决这个问题(请原谅非常简单的“字到整数”翻译器)。

CsvRouteHandler 从 URL 获取 id 数组并将其作为整数数组放在 RouteData 上。如果原始数组有诸如一、二或三之类的单词,则它将每个值转换为 int。

MvcRouteHandler

protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
    var idArrayParameter = requestContext.RouteData.Values["idArray"] != null ? requestContext.RouteData.Values["idArray"].ToString() : null;
    if (string.IsNullOrEmpty(idArrayParameter))
    {
        return base.GetHttpHandler(requestContext);
    }

    requestContext.RouteData.Values.Remove("idArray"); // remove the old array from routedata

    // Note: it is horrible and bugged but and you probably have your own translation method :)
    string[] idArray = idArrayParameter.Split(',');
    int[] ids = new int[idArray.Length];

    for(int i = 0; i < idArray.Length; i++)
    {
        if (!int.TryParse(idArray[i], out ids[i]))
        {
            switch (idArray[i])
            {
                case "one":
                    ids[i] = 1;
                    break;
                case "two":
                    ids[i] = 2;
                    break;
                case "three":
                    ids[i] = 3;
                    break;
            }
        }
    }

    requestContext.RouteData.Values.Add("Id", ids);

    return base.GetHttpHandler(requestContext);

}
}

路线配置:

    routes.Add(
        name: "Id Array Route",
        item: new Route(
            url: "endpoint/{idArray}",
            defaults: new RouteValueDictionary(new { controller = "Test", action = "Index" }),
            routeHandler: new CsvRouteHandler())
    );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 2021-06-07
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多