【问题标题】:Best pratice for completing MVC model properties which aren't bound?完成未绑定的 MVC 模型属性的最佳实践?
【发布时间】:2013-03-29 15:36:50
【问题描述】:

我正在尝试为仅部分编辑的模型找到使用 MVC 的最佳方式。

下面是一个简单的例子。

型号

using System.ComponentModel.DataAnnotations;
public class SimpleModel
{
    public int Id { get; set; }
    public string Parent { get; set; }
    [Required]
    public string Name { get; set; }
}

查看

using System.ComponentModel.DataAnnotations;
public class SimpleModel
{
    public int Id { get; set; }
    public string Parent { get; set; }
    [Required]
    public string Name { get; set; }
}

控制器

using System.Web.Mvc;

public class SimpleController : Controller
{
    public ActionResult Edit(int id)
    { return View(Get(id)); }

    [HttpPost]
    public ActionResult Edit(int id, SimpleModel model)
    {
        if (model.Name.StartsWith("Child")) //Some test that is not done client-side.
        {
            Save(model);
            //Get the saved data freshly.
            //model = Get(id);
        }
        else
        {
            ModelState.AddModelError("", "Name should start with 'Child'");
        }
        //Is this the way to set the Parent property?
        //var savedModel = Get(id);
        //model.Parent = savedModel.Parent;
        return View(model);
    }

    //Mock a database.
    SimpleModel savedModel;

    private void Save(SimpleModel model)
    { savedModel = new SimpleModel() { Id = model.Id, Name = model.Name }; }

    private SimpleModel Get(int id)
    {
        if (savedModel == null)
        { return new SimpleModel() { Id = id, Parent = "Father", Name = "Child " + id.ToString() }; }
        else
        { return new SimpleModel() { Id = savedModel.Id, Parent = "Father", Name = savedModel.Name }; }
    }
}

名称字段是可编辑的。父字段仅供参考,不应更新。因此,它是使用 DisplayFor 渲染的。

在发布后,我收到了一个属性 Parent 设置为 null 的模型。这没问题,因为它不会被保存。但是,当我只是将接收到的模型返回到视图时,将不再显示 Parent 字段。当模型有效时,我可以轻松地从数据库中再次获取它,从而取回 Parent 字段的值。

当模型无效时,我希望允许用户更正输入并再次尝试保存。在那里,我应该使用接收到的模型的输入值,但也应该显示显示的值。

实际上,要显示的字段要多得多以供参考,通常来自不同的数据库实体,而不是正在编辑的实体。

我看到了将字段作为视图中的隐藏字段传递的建议,但是我非常不愿意从客户端读取不应更新的数据。

有没有比手动将这些值复制到模型中或将它们作为隐藏字段传递更优雅的方法?

【问题讨论】:

    标签: asp.net-mvc-4 model-binding


    【解决方案1】:

    将这些不可编辑的属性提供给另一个模型并让它处理这些属性怎么样?

    查看模型

    public class PersonViewModel
    {
        public int Id { get; set; }
    
        [Required]
        public string FirstName { get; set; }
    
        [Required]
        public string LastName { get; set; }
    
        public PersonDetailsModel DetailsModel { get; set; }
    }
    

    细节模型

    public class PersonDetailsModel
    {
        public string Mother { get; set; }
        public string Father { get; set; }
    
        public PersonDetailsModel() { }
    
        public PersonDetailsModel(int personId)
        {
            // pull required model data from databases
            var db = DBParentContext;
            Mother = db.Parent.Where(m => m.ChildId == personId)
            Father = db.Parent.Where(m => m.ChildId == personId)
        }
    }
    

    控制器

    public class PersonController : Controller
    {
        [HttpPost]
        public ActionResult Edit(PersonViewModel viewModel)
        {
            viewModel.DetailsModel = new PersonDetailsModel(viewModel.Id)
    
            if (ModelState.IsValid) {
                // ~
            }
            return View(viewModel)
        }
    }
    

    查看

    @model PersonViewModel
    
    @Html.DisplayFor(m => m.DetailsModel.Mother)
    @Html.DisplayFor(m => m.DetailsModel.Father)
    @Html.TextBoxFor(m => m.FirstName)
    @Html.TextBoxFor(m => m.LastName)
    

    由于像你的母亲这样的细节是不可编辑的,所以它们并不是“编辑”模型的真正一部分,所以我会像这样框起来并尝试让其他东西来处理它们。

    【讨论】:

    • 这根本解决不了他的问题。他不想每次都从数据库中获取信息。
    • 实际上,我并不介意从数据库中提取它。我只是在寻找一种避免复制属性等的方法。实际上,我只是缺少 Webforms 的视图状态 :-(
    • 这个答案看起来像是一种将可编辑值与参考值分开的便捷方法。将参考值的模型添加为编辑模型的属性是一种允许强类型视图的好方法,而无需从视图状态中提取数据。谢谢。
    • @MystereMan 好吧,据我了解,问题在于将有关不可编辑属性的问题分开,这样一个模型就不会全部处理。 OP 说I can easily get it again from the database。两天前我在工作中遇到了基本相同的问题,我决定每次都应该从数据库中提取信息,这样我就可以确定信息是实时的。只是一个建议^^
    【解决方案2】:

    如果您不打算更新 Parent 字段,那么它是否隐藏并不重要,因为您不会在发布时更新它。

    在这种情况下我会使用隐藏,只是确保不要更新该字段。

    【讨论】:

      猜你喜欢
      • 2017-12-01
      • 2016-02-27
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多