How should the C # Web API middleware provider work?

I have the following:

  • request url: 'endpoint / 1,2,3? q = foo '
  • action to which the request is bound: public object Bar ([ModelBinder] List <T> identifiers, string [FromUri] q)

I want to map the fragment "1,2,3" to the parameter "ids", so I created ModelBinderProvider according to this link , which should call the proper connecting device.

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; } } 

I registered the provider in Global.asax as follows:

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

Reason . I created this provider because I want, no matter what T ("1,2,3" or "one, two, three"), binding to work.

Problem : Let T be 'int'; every time a request is sent, the parameter "modelType" is always "int", and not what I expect - "List <int> ', so the request is not processed properly.

The strange thing : Doing something like this works, but T is specialized, and therefore not what I want:

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

I do not see what I am doing wrong, why is the parameter modelType not expected?

+7
asp.net-mvc asp.net-web-api asp.net-mvc-5 asp.net-web-api2
source share
1 answer

This is a very old question, but I had a similar problem with legacy code.

Commas are reserved and should be avoided, although they work in some cases, but if you really want to use them ...

I think this is more of a route problem than a model binder when "1,2,3" is part of the URL. Assuming this, I wrote a small RouteHandler that does the trick (please forgive the very simple word "word to integer").

CsvRouteHandler gets the id array from the URL and puts it in RouteData as an array of integers. If the original array has words such as one, two, or three, it translates each value into int.

Mvcoutouthandler

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

Route Configuration:

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

All Articles