C#Web API模型绑定提供程序应该如何工作?

时间:2014-06-28 19:08:32

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

我有以下内容:

  • 请求网址:'端点/ 1,2,3?q = foo'
  • 请求绑定的操作: 公共对象栏([ModelBinder]列表< T> ID,[FromUri]字符串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是什么(&#39; 1,2,3&#39;或者&#39;一,二,三&# 39;),绑定工作。

问题: 让&#39;说T是&#39; int&#39 ;;每次发送请求时,&#39; modelType&#39;参数总是&#39; int&#39;而不是我的期望 - &#39; List&lt; int&gt;&#39;,因此请求未得到妥善处理。

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

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

我看不出我做错了什么,为什么&#39; modelType&#39;参数不是预期值?

1 个答案:

答案 0 :(得分:0)

这是一个非常古老的问题,但我在此处遇到类似的遗留代码问题。

逗号是保留的,虽然它们在某些情况下可以使用但是如果你真的想要使用它们,它应该被避免......

我认为,与#34; 1,2,3&#34;是网址的路径部分。假设我写了一个小的RouteHandler来做这个伎俩(请原谅非常简单的&#34;字到整数&#34;翻译)。

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())
    );