【问题标题】:Model Binding not working模型绑定不起作用
【发布时间】:2012-05-31 09:58:59
【问题描述】:

我有以下 POCO 课程:

public class Location
    {
        public int LocationId { get; set; }
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
        public string Country { get; set; }
        public float? Latitude { get; set; }
        public float? Longitude { get; set; }
        public string PhoneNumber { get; set; }
        public string EmailAddress { get; set; }
        public string Website { get; set; }
        public virtual ICollection<Program> Programs { get; set; }
        public virtual ICollection<PlayerType> PlayerTypes { get; set; }
    }

public class PlayerType
    {
        public int PlayerTypeId { get; set; }
        public string Name { get; set; }
        public int SortOrder { get; set; }
        public bool IsActive { get; set; }
        public virtual ICollection<Location> Locations { get; set; }
    }

还有一个视图模型类

public class LocationViewModel
    {
        public Location Location { get; set; }
        public IList<PlayerType> SelectPlayerTypes { get; set; } 

        public LocationViewModel()
        {
            Location = new Location();
        }

    }

在我的创建表单中,我将模型定义为

@model Locator.Models.LocationViewModel

并且具有如下字段:

div class="editor-label">
    @Html.LabelFor(model => model.Location.Name)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Location.Name)
    @Html.ValidationMessageFor(model => model.Location.Name)
</div>

在我的控制器中处理我的 POST

[HttpPost]
        public ActionResult Create(LocationViewModel location)
        {
            if (ModelState.IsValid) {
                locationRepository.InsertOrUpdate(location.Location);
                locationRepository.Save();
                return RedirectToAction("Index");
            }
            location.SelectPlayerTypes = golferTypeRepository.All.Where(p => p.IsActive).ToList();
            return View(location);
        }

问题是我有一个 Location 对象,但没有一个属性可以设置为表单中输入的值。

我在这里做错了吗?

谢谢

【问题讨论】:

  • 我可能会离开,但我认为你在构造函数中初始化 Location 是把它扔掉了。您可以尝试删除该行(并在模型本身之外实例化该属性)吗?
  • 我在 Create ActionResult(不是帖子)中实例化了它,现在当我发布时,Location 为空。
  • 是的,这就是我希望你尝试的方法。哦,好吧,我猜这不是问题。
  • 当您说所有属性都不能设置为表单中输入的值时 - 您在哪里/如何确定这一点?
  • 我将 Create 构造函数更新为 public ActionResult Create(LocationViewModel model, Location location) 并且它正在工作。

标签: asp.net-mvc asp.net-mvc-3


【解决方案1】:

我的情况有点独特,但希望它对处于类似情况的人有所帮助。我让我的视图模型实现了 IValidatableObject,如果成功,此接口的 Validate 方法将返回 null。它必须返回一个空的 IEnumerable。因此绑定实际上正在发生但崩溃了。

基本上当你遇到这个问题时,使用 Fiddler 查看发布的数据,确保发布的变量与视图模型上的属性(而不是字段!)匹配,并在视图模型构造函数上放置一个断点以确保路由引擎命中正确的 POST 方法。祝你好运!

【讨论】:

    【解决方案2】:

    对于其他仍然遇到此问题的人,如果您在 post 方法中将参数命名为与您的属性之一相同,则默认模型绑定器也将失败。

    【讨论】:

      【解决方案3】:

      重申 Tod 所说的,模型绑定器需要 HTML 元素上的“名称”属性来映射属性。 我正在手动做一个快速测试表格,只使用“id”属性来识别我的元素。

      当我添加 'name' 属性时,一切都到位了。

      <input type="text" id="Address" name="Address" />
      

      【讨论】:

        【解决方案4】:

        还有一个原因: 通常我使用内置的编辑器或显示器,并且永远不会遇到这个问题。但是在这种情况下,我需要一个半自定义控件。基本上是一个带有大量数据属性的下拉菜单。

        我在做什么,因为我的选择标签是:

        <select name="@Html.IdFor(x => x.SubModel.ID)" id="@Html.IdFor(x => x.SubModel)" class="form-control select-control">
        

        现在一切都在回传,在未经训练的人看来,一切都应该正常工作和绑定。但是 IdFor 助手使用下划线呈现子模型。模型绑定器不会将下划线解释为类层次结构指示符。应该将它们分开的是一个点。来自NameFor:

        <select name="@Html.NameFor(x => x.SubModel.ID)" id="@Html.IdFor(x => x.SubModel)" class="form-control select-control">
        

        NameFor 解决了我的所有问题。

        【讨论】:

          【解决方案5】:

          入党也晚了,但是在asp.net mvc 3年之后,我发现禁用的输入没有发布,所以模型绑定器当然无法绑定它们。见here

          “表单中被禁用的元素将不会被提交”。

          最好使用readonly="readonly" 而不是禁用。见here

          【讨论】:

            【解决方案6】:

            我知道现在评论这个已经太迟了。我所做的是在 ViewModel 中添加了无参数构造函数,一切都很棒。

            【讨论】:

              【解决方案7】:

              让我在这里补充一下模型绑定器无法正常工作的另一个原因。

              我有一个带有属性ContactPhone 的模型,在此过程中我决定将此属性的名称更改为Phone,然后当我尝试创建时,该属性的模型绑定突然停止工作一个新的实例。

              问题出在我的控制器中的 Create 操作上。我使用了默认的 Visual Studio 脚手架,它创建了方法签名,如下所示:

              public ActionResult Create([Bind(Include = "Id,ContactPhone, ...")] Customer customer)
              { ... }
              

              注意Bind 属性,脚手架使用原始名称ContactPhone 创建字段,由于这是一个字符串,因此没有重构。由于未包含新字段 Phone,因此模型绑定程序忽略了它的值。

              我希望这可以节省一些人的时间。

              祝你好运!

              【讨论】:

                【解决方案8】:

                只是提供另一个可能的原因:我花了几个小时在我的代码中寻找错误,而在我的情况下,绑定器无法正常工作的原因是使用具有公共字段而不是公共属性的模型:

                public int CustomerName;
                

                它应该是:

                public int CustomerName { get; set; }
                

                从事 ASP.NET MVC 已经 3 年了,我以前从未遇到过这种情况。希望它可以减轻一些人的挫败感;)

                【讨论】:

                • 愿望成真 - 今天让我免于吹垫圈。我有所有领域,没有属性。所有的 HTML 链接都没有详细信息。感谢您添加这个额外的答案,@Grzegorz。
                • 天哪,我花了这么多时间试图弄清楚这一点!谢谢!
                • 这个答案也帮助提醒我属性需要是public
                • 这是我的问题。谢谢!
                • 天哪,这是我的问题,我一直在寻找它。对这个模型绑定器感到羞耻,Newtonsoft 可以在没有 getter 和 setter 的情况下做到这一点:(
                【解决方案9】:

                这拯救了我的一天。输入以下内容:

                public ActionResult Edit(int masterId, ConclusionView conclusion)
                

                ConclusionView 有一个名为 Conclusion 的属性,所以我差点失去理智。

                【讨论】:

                  【解决方案10】:

                  问题来了:

                  [HttpPost]
                  public ActionResult Create(LocationViewModel location)
                  

                  你看到了吗?这是您的操作参数的名称:location

                  现在查看您的视图模型,它有一个名为 Location 的属性:

                  public Location Location { get; set; }
                  

                  这会混淆模型绑定器。它不再知道您是否需要绑定LocationViewModel 或其属性。

                  所以只需重命名以避免冲突:

                  [HttpPost]
                  public ActionResult Create(LocationViewModel model)
                  

                  【讨论】:

                  • 我笑得停不下来,这让我有好几分钟都感觉要崩溃了
                  • 我也遇到过,很好的答案!
                  • 我有一个带有 Model 属性的类,用于车辆的品牌/型号。当然我传递的参数是model掌心
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-08-15
                  • 2018-02-28
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-06-18
                  相关资源
                  最近更新 更多