问题
My controller method looks like this:
public ActionResult SomeMethod(Dictionary<int, string> model)
{
}
Is it possible to call this method and populate "model" using only query string? I mean, typing something like this:
ControllerName/SomeMethod?model.0=someText&model.1=someOtherText
in our browser address bar. Is it possible?
EDIT:
It would appear my question was misunderstood - I want to bind the query string, so that the Dictionary method parameter is populated automatically. In other words - I don't want to manually create the dictionary inside my method, but have some automathic .NET binder do it form me, so I can access it right away like this:
public ActionResult SomeMethod(Dictionary<int, string> model)
{
var a = model[SomeKey];
}
Is there an automatic binder, smart enough to do this?
回答1:
In ASP.NET Core, you can use the following syntax (without needing a custom binder):
?dictionaryVariableName[KEY]=VALUE
Assuming you had this as your method:
public ActionResult SomeMethod([FromQuery] Dictionary<int, string> model)
And then called the following URL:
?model[0]=firstString&model[1]=secondString
Your dictionary would then be automatically populated. With values:
(0, "firstString")
(1, "secondString")
回答2:
For .NET Core 2.1, you can do this very easily.
public class SomeController : ControllerBase
{
public IActionResult Method([FromQuery]IDictionary<int, string> query)
{
// Do something
}
}
And the url
/Some/Method?1=value1&2=value2&3=value3
It will bind that to the dictionary. You don't even have to use the parameter name query.
回答3:
try custom model binder
public class QueryStringToDictionaryBinder: IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var collection = controllerContext.HttpContext.Request.QueryString;
var modelKeys =
collection.AllKeys.Where(
m => m.StartsWith(bindingContext.ModelName));
var dictionary = new Dictionary<int, string>();
foreach (string key in modelKeys)
{
var splits = key.Split(new[]{'.'}, StringSplitOptions.RemoveEmptyEntries);
int nummericKey = -1;
if(splits.Count() > 1)
{
var tempKey = splits[1];
if(int.TryParse(tempKey, out nummericKey))
{
dictionary.Add(nummericKey, collection[key]);
}
}
}
return dictionary;
}
}
in controller action use it on model
public ActionResult SomeMethod(
[ModelBinder(typeof(QueryStringToDictionaryBinder))]
Dictionary<int, string> model)
{
//return Content("Test");
}
回答4:
More specific to mvc model binding is to construct the query string as
/somemethod?model[0].Key=1&model[0].Value=One&model[1].Key=2&model[1].Value=Two
Custom Binder would simply follow DefaultModelBinder
public class QueryStringToDictionary<TKey, TValue> : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var modelBindingContext = new ModelBindingContext
{
ModelName = bindingContext.ModelName,
ModelMetadata = new ModelMetadata(new EmptyModelMetadataProvider(), null,
null, typeof(Dictionary<TKey, TValue>), bindingContext.ModelName),
ValueProvider = new QueryStringValueProvider(controllerContext)
};
var temp = new DefaultModelBinder().BindModel(controllerContext, modelBindingContext);
return temp;
}
}
Apply custom model binder in model as
public ActionResult SomeMethod(
[ModelBinder(typeof(QueryStringToDictionary<int, string>))] Dictionary<int, string> model)
{
// var a = model[SomeKey];
return Content("Test");
}
来源:https://stackoverflow.com/questions/22707788/is-it-possible-to-get-dictionary-from-query-string