好吧,假设我有一个像这样的URL,它通过HTTP动词GET
映射到我在下面的控制器操作:
GET /foo/bar?sort=asc&r=true
如何在我的控制器操作上将其绑定到我的模型Bar
:
class Bar {
string SortOrder { get; set; }
bool Random { get; set; }
}
public ActionResult FooBar(Bar bar) {
// Do something with bar
return null;
}
请注意,属性名称不会也不一定与URL参数的名称匹配。此外,这些是可选的url参数。
答案 0 :(得分:12)
它不支持开箱即用,但你可以这样做:
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
}
您可以实现自定义IModelBinder
,但手动映射要容易得多。
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;
}
答案 1 :(得分:5)
模型活页夹将其从视图获取的参数与名称在操作中的模型匹配,因此如果它们不匹配,则绑定将不起作用。
你有的选择:
所以基本上,你不能做你想要的。
<强>更新强>
您在评论中写道,属性可以与参数名称匹配,因此,不要编写可能会成功进行绑定的自定义属性,只需编写ViewModel(VM fromMVC ...)来调整url参数名称
MVC团队不建议编写自定义模型绑定器:
一般情况下,我们建议人们不要编写自定义模型粘合剂,因为它们很难正确使用并且很少需要它们 来自here
答案 2 :(得分:3)
很久以前我遇到了同样的问题,并使用了Andras Zoltan的这个堆栈解决方案:Asp.Net MVC 2 - Bind a model's property to a different named value
我在我的类上设置了ModelBinder属性,在属性上设置了BindAlias:
[ModelBinder(typeof(DefaultModelBinderEx))]
public class MyModel
{
[Required]
[BindAlias("new")]
public int? Amount { get; set; }
如果您无法更改或未访问模型文件来设置属性,您仍然可以创建自定义模型绑定器,或者,创建一个特定对象,而不是映射到模型(AutoMapper是有用的)< / p>
答案 3 :(得分:1)
如果定义了传入的参数名称,您可以实现IModelBinder将传入的参数映射到您选择的对象。否则你将不得不依赖参数顺序和/或类型来推断正确的绑定,这似乎是一个非常糟糕的选择。
答案 4 :(得分:1)
没有免费的MVC.Net Modelbinding功能可以为您提供开箱即用的功能。当我需要做这样的事情时,它真的让我思考我的建模,这几乎总是让我为我的视图绑定创建一个ViewModel,为我的存储库存储创建一个EntityModel。
我喜欢使用AutoMapper在这些不同类型之间进行转换。使用AutoMapper的最佳部分是它可以驱使您不必为控制器中的每个Action反复编写映射逻辑。只需在初始化部分使用AutoMapper进行一次设置,然后再执行类似的操作。
Mapper.Map<Bar>(barViewModel);