问题
Okay, lets say I have a URL like so, which is mapped via HTTP verb GET
to the controller action I have below:
GET /foo/bar?sort=asc&r=true
How can I bind this to my model Bar
on my controller action I have below:
class Bar {
string SortOrder { get; set; }
bool Random { get; set; }
}
public ActionResult FooBar(Bar bar) {
// Do something with bar
return null;
}
Note that the property names won't and can't necessarily match the names of the URL parameters. Also, these are OPTIONAL url parameters.
回答1:
The model binder matches the parameters it gets from the view to the model you have in the action by the Names, so if they won't match the binding will not work.
options you got:
- Match the inputs names to the model properties names... but You said you can't do this, (for some unknown reason).
- Write custom Model Binder. *
- Use The Bind attribute with prefix - though it'll still force you to have input names close to the model properties names.
so basically, You can't do exactly what you want.
Update:
You wrote in a comment that the properties CAN match the parameters names, so instead of write custom attributes that maybe will succeeded to do the binding, just write a ViewModel (The VM fromMVC...) to adjust the url parameters names.
Writing custom model binder is not recommended by the MVC team:
In general, we recommend folks don’t write custom model binders because they’re difficult to get right and they’re rarely needed
from here
回答2:
It's not supported out of the box, but you could do this:
class BarQuery : Bar {
public string sort { get { return SortOrder; } set { SortOrder = value; } }
public bool r { get { return Random; } set { Random = value; } }
}
public ActionResult FooBar(BarQuery bar) {
// Do something with bar
}
You could implement a custom IModelBinder
, but it's much easier to do manual mapping.
If you can change the Bar class you can use this attribute:
class FromQueryAttribute : CustomModelBinderAttribute, IModelBinder {
public string Name { get; set; }
public FromQueryAttribute() { }
public FromQueryAttribute(string name) {
this.Name = name;
}
public override IModelBinder GetModelBinder() {
return this;
}
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
return controllerContext.HttpContext.QueryString[this.Name ?? bindingContext.ModelName];
}
}
class Bar {
[FromQuery("sort")]
string SortOrder { get; set; }
[FromQuery("r")]
bool Random { get; set; }
}
public ActionResult FooBar(Bar bar) {
// Do something with bar
return null;
}
回答3:
I had the same problem a long time ago and used this stack solution by Andras Zoltan: Asp.Net MVC 2 - Bind a model's property to a different named value
I set the ModelBinder attribute on my class and the BindAlias on the property:
[ModelBinder(typeof(DefaultModelBinderEx))]
public class MyModel
{
[Required]
[BindAlias("new")]
public int? Amount { get; set; }
If you can't change or haven't access your model file to set the Attributes, you still can create a custom model binder, OR, make a specific object than you will map to your Model (AutoMapper is usefull)
回答4:
You could implement IModelBinder to map your incoming parameters to the object of your choosing provided the incoming parameter names are defined. Otherwise you would have to rely on parameter order and/or type to infer the proper binding which seems to be a very poor choice.
回答5:
There is no free MVC.Net Modelbinding feature that gives you what you want out of the box. When I need to do something like this, it really makes me think about my modeling which almost always makes me create a ViewModel for my view binding and a EntityModel for my repository storage.
I like to use AutoMapper to convert between these different types. Best part of using AutoMapper is that it drives you away from having to write the mapping logic yourself over and over for each Action in your controller. Just set it up once with AutoMapper in your initialization sections and just execute something like this in the future.
Mapper.Map<Bar>(barViewModel);
来源:https://stackoverflow.com/questions/8507699/how-to-bind-url-parameters-to-model-properties-with-different-names