如何将URL参数绑定到具有不同名称的模型属性

时间:2011-12-14 16:09:36

标签: asp.net-mvc model-binding

好吧,假设我有一个像这样的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参数。

5 个答案:

答案 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,但手动映射要容易得多。

<小时/> 如果您可以更改Bar类,则可以使用此属性:

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)

模型活页夹将其从视图获取的参数与名称在操作中的模型匹配,因此如果它们不匹配,则绑定将不起作用。

你有的选择:

  1. 将输入名称与模型属性名称相匹配......但您说您不能这样做,(原因不明)。
  2. 编写自定义模型Binder。 *
  3. 使用带有前缀的Bind属性 - 尽管它仍然会强制您使输入名称接近模型属性名称。
  4. 所以基本上,你不能做你想要的。


    <强>更新

    您在评论中写道,属性可以与参数名称匹配,因此,不要编写可能会成功进行绑定的自定义属性,只需编写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);