ASP.NET MVC,使用具有强类型帮助程序的viewmodel

时间:2013-12-01 14:21:14

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

当您在ASP.NET MVC中使用强类型帮助程序(HTML.EditorFor等)和viewmodel时,我有一个关于设置viewmodel的问题。我正在使用MVC5,但我想我的问题也适用于其他版本。

对于这个例子,我正在创建CRUD过程。

在该示例中,用户输入人员的姓名和地址,并从下拉列表中选择城市。

以下是模型:

    public class Person
    {
        [Key]
        public int PersonID { get; set; }
        [ForeignKey("City")]
        public int CityID { get; set; }
        public string Name {get; set;}
        public string address {get; set;}

        //Navigational property
        public virtual City City { get; set; }
    }

这是viewmodel:

public class PersonCreateViewModel
{
    public SelectList cities {get; set;}
    public Person person { get; set; }
}

以下是控制器中用于传回创建页面视图的操作方法:

 public ActionResult Create()
    {
        CreateViewModel viewmodel = new CreateViewModel();

        viewmodel.cities = new SelectList(db.Cities, "CityID", "name");
        return View(viewmodel);
    }

以下是我观点的一部分:

        <div class="form-group">
            @Html.LabelFor(model => model.person.name, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
            @Html.EditorFor(model => model.person.name)
            @Html.ValidationMessageFor(model => model.person.name)
        </div>
    </div>

    <div class="form-group">
            @Html.LabelFor(model => model.person.address, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
            @Html.EditorFor(model => model.person.address)
            @Html.ValidationMessageFor(model => model.person.address)
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(model => model.person.CityID, "CityID", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("cities")
            @Html.ValidationMessageFor(model => model.person.CityID)
        </div>
    </div>

我为我的观点声明了模型:

@model TestProjects.ViewModels.PersonCreateViewModel

最后,控制器中的http post方法:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include="PersonID,CityID,nameaddress")] Person person)
    {

        if (ModelState.IsValid)
        {
            //Add to database here and return

        }

        //return back to view if invalid db save
        return View(person);
    }

所以有一次我完成了所有这些工作。然后我决定使用ViewModel方法。我仍然没有工作,但这里有一些问题:

在视图中,我使用model.person.address引用模型的属性。这是正确的方法吗?我注意到,当它生成html时,它将字段命名为person_address等。

那么我应该只更改http post控制器mehtod中的Bind属性来反映这一点吗?但是,如果我更改此属性,属性将不再与导致断开连接的person对象匹配。

或者我应该更改我的视图模型?而不是让人在我的ViewModel中键入,将模型中的所有字段复制/粘贴到ViewModel中?我想这也可以,但这是它的典型方式吗?如果视图模型中的模型只有一个实例,那么列出模型的每个属性似乎是多余的?

1 个答案:

答案 0 :(得分:4)

  

在视图中,我使用model.person.address引用模型的属性。这是正确的方法吗?我注意到,当它生成html时,它将字段命名为person_address等。

是的,这是引用模型属性的正确方法。更准确地说,由于助手表达式中的model是对Func输入参数的引用,因此它可以是任何内容。以下也适用:

@Html.EditorFor(banana => banana.person.address)
  

那么我应该只更改http post控制器mehtod中的Bind属性来反映这一点吗?但是,如果我更改此属性,属性将不再与导致断开连接的person对象匹配。

根本不需要绑定参数。你应该做的是完全从你的视图模型中引用你的数据实体(即Person)(否则使用视图模型有点无意义,因为它无论如何都与你的数据实体紧密耦合)并提供视图所需的视图模型属性,例如:

public class PersonCreateViewModel
{
    public SelectList Cities { get; set; }

    public string Address { get; set; }
    public string Name { get; set; }
    ...
}

然后他们应该默认绑定到同一个模型,假设你的观点是正确的:

public ActionResult Create (PersonCreateViewModel model)
{
    // Map PersonCreateViewModel properties to Person properties
}