Master-Detail使用Razor,ASP.NET MVC 3和.NET 4.0创建视图
我是.NET的新手,如果我有任何愚蠢的错误,请耐心等待我。
我在.NET 4.0中使用ASP.NET MVC 3
我想为具有子模型的模型创建一个“创建”视图。 此视图应包含子模型的部分 “创建”视图,我将使用以下简单示例进行说明:
-
人物模型
class Person { public string Name { get; set; } public Address { get; set; } }
-
地址模型
class Address { public string City { get; set; } public string Zip { get; set; } //A List for creating a item in the view //containing cities fetched from the database. //The initialization is done in the controller action returning //the related partial view. public IEnumerable CityDropDown { get; set; } ) }
-
控制器动作
class MyController : Controller { public ViewResult Create() { var person = new Person(); var address = new Address(); // initialization of address.CityDropDown omitted person.Address = address; return View(MyViews.CreatePersonView, person); } [HttpPost] public ViewResult Create(Person person) { //persistance logic } }
-
我想要的视图层次结构:
我为实现这一目标而尝试的解决方案如下:
第一种方法:使用@Html.Partial(..)
或@{Html.RenderPartial(..)}
我做了什么 :
-
人物观点
@model Person @using(Html.BeginForm()){ @Html.EditorFor(m=>m.Name) @Html.Partial(MyViews.AddressPartialView, @Model.Address) }
-
地址局部视图
@model Address @Html.EditorFor(m=>m.Zip) @Html.DropDownListFor(m=>m.City, @Model.CityDropDown)
问题 :
提交表单时, person.Address
为null。 在Google上进行了一些搜索之后,我发现为了使地址字段的提交起作用,生成的HTML标记必须是以下内容(注意Address_
前缀):
不用说,在我的情况下生成的HTML标记不一样,但它是以下(缺少Address_
前缀):
第二种方法:使用EditorTemplate作为Address模型
我做了什么 :
-
我将Address局部视图移动到View / Shared / EditorTemplates文件夹,确保它与
Person
模型中的Address
属性具有相同的名称,即Address.cshtml 。 -
人物观点
@model Person @using(Html.BeginForm()){ @Html.EditorFor(m=>m.Name) @Html.EditorFor(@Model.Address) //will automatically find the Address //partial view in the EditorTemplates folder }
问题 :
使用这种方法,生成的标记实际上具有正确的前缀(即Address_
),但是我得到的Object引用没有设置为Address.CityDropDown
属性的实例exception ,它告诉我控制器动作中的预初始化的Address对象是由于某种原因没有传递到局部视图。
第三种方法:将所有Address字段放在Person模型中
这种方法没有任何问题,但我不想使用它,因为我不希望有冗余代码,如果我想在另一个模型中有地址的创建视图。
总结一下
我应该怎么做才能拥有可以在我的应用程序中使用的可重用的部分创建视图?
您使用EditorTemplates有正确的方法,但请记住,您需要填充CityDropDown
。 所以,视图应该是这样的:
Person model = new Person() { Address = new Address { CityDropDown = new SelectListItem[]{ new SelectListItem { Selected = true, Text = "Select one..." }, new SelectListItem { Text = "Anywhere", Value = "Anywhere" }, new SelectListItem { Text = "Somewhere", Value = "Somewhere" }, new SelectListItem { Text = "Nowhere", Value = "Nowhere" } } } };
然后,这将使该视图仅包括:
@Html.EditorForModel()
然后你的EditorTemplates
会从那里拿起:
〜/ Views / shared / EditorTemplates / Address.cshtml (注意:这是基于类型而不是属性名称)
@model MvcApplication.Models.Address @Html.DropDownListFor(x => x.City, Model.CityDropDown) @Html.EditorFor(x => x.Zip)
〜/查看/共享/ EditorTemplates / Person.cshtml
@model MvcApplication.Models.Person @using (Html.BeginForm()) { @Html.EditorFor(x => x.Name) @Html.EditorFor(x => x.Address) }
三个视图然后呈现如下:
示例项目可以在这里找到: https : //github.com/bchristie/StackOverflow-Examples/tree/master/questions-19247958