ModelBinder is not invoked
Per my previous question, I implemented a model binder that maps /api/v1/widgets/1,2,3
to
// WidgetsController.cs:
public ActionResult Show(IEnumerable<int> idArgs)
{
}
This was working for a while, but now it is not any longer. My ModelBinder is not even being invoked 开发者_如何转开发at all. When my action is invoked, idArgs
has a value of the empty list, even if I set its default value to null
in the route, which suggests to me that the default model binder thinks it's getting a value from somewhere. The only change I've made since last week when it was working is that previously, I had called my action ShowMany.
Since then, I renamed it to Show
. Can anyone help me figure out why my ModelBinder is not being invoked?
In global.asax.cs, I have
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
ModelBinders.Binders.Add(typeof(IEnumerable<int>), new IEnumerableOfIntCSVModelBinder());
}
And the route looks like this (I have verified that this route is being used):
context.MapRoute(
"show",
"api/{controller}/{idArgs}",
new { action = "show" },
new { httpMethod = new HttpMethodConstraint("GET"), idArgs = @"^(\d+,)+\d+,?$" }
);
Edit: I've tried messing messing with the routes some more, as well as commenting out the JsonValueProvider
, and I'm still getting an empty array. In my controller, I can do
var ids = RouteData.Values["idArgs"];
and get the string "1,2,3". If only the framework would pass this to my ModelBinder, my ModelBinder would turn it into the IEnumerable
.
I am using AutoFac. Is it possible that AutoFac is injecting an empty array into my controller method? I haven't had problems like this in other places (and we use AutoFac everywhere in this project.)
Edit2: I also tried decorating both the idArgs
action parameter, and the controller with [ModelBinder(typeof(IEnumerableOfIntCSVModelBinder))]
, but this had no effect.
I see that you have a JsonValueProviderFactory
added in your Application_Start
. Maybe there is something in the implementation of this factory that prevents the model binder from being hit?
Also the url you have shown /api/v1/widgets/1,2,3
has no relation to the route definition that you have "restapi/{controller}/{idArgs}"
.
Could you try moving your route to be the first one registered? I just tried coding this up and had an issue where my route wasn't firing until I moved it's registration above the default route registration. Routes appear to be run in the order they are registered, so if you have a more specific registration after and more general registration, it may not fire.
In this example, the second route never gets called:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
"Ids",
"{controller}/{action}/{ids}",
new { controller = "Home", action = "Index", ids = UrlParameter.Optional },
new { ids = @"^(\d+,)+\d+,?$" });
But if you reverse their order, then "Ids" gets called.
精彩评论