Master-Detail使用Razor,ASP.NET MVC 3和.NET 4.0创建视图

时间:2013-10-08 12:40:14

标签: c# .net asp.net-mvc asp.net-mvc-3 razor

我是.NET的新手,如果我有任何愚蠢的错误,请耐心等待。

我正在使用ASP.NET MVC 3和.NET 4.0

我希望为具有子模型的模型提供“创建”视图。此视图应包含子模型的 部分 “创建”视图,我将使用以下简单示例进行说明:

  • 模型

    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 <select/> 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<SelectListItem> 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
            }
        }
    
  • 我想要的视图层次结构:

Person Create View Hierarchy

我为实现这一目标而尝试的解决方案如下:

第一种方法:使用@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为空。在Google上进行了一些搜索后,我发现为了提交地址字段,生成的HTML标记必须如下(注意Address_前缀):

<form...>
    <input type=text id="Name" />
    <input type=text id="Address_Zip" />
    <select id="Address_City">
        <!-- options... -->
    </select>
</form>

毋庸置疑,我的情况下生成的HTML标记不尽相同,而是以下内容(缺少Address_前缀):

<form...>
    <input type=text id="Name" />
    <input type=text id="Zip" />
    <select id="City">
        <!-- options... -->
    </select>
</form>

第二种方法:使用 EditorTemplate 作为地址模型


我做了什么:

  • 我将地址部分视图移至 View / Shared / EditorTemplates 文件夹,确保其名称与Address模型中的Person属性,即 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_),但是我得到 对象引用未设置为实例异常 对于Address.CityDropDown属性,它告诉我控制器操作中的预初始化的Address对象由于某种原因没有传递给局部视图。

第三种方法:将所有地址字段放在Person模型


这种方法没有任何问题,但我不想使用它,因为我不想拥有冗余代码,如果我想在另一个模型中有地址的创建视图。

总结


为了拥有一个可以在我的应用程序中使用的可重用部分创建视图,我该怎么做?

1 个答案:

答案 0 :(得分:3)

您使用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)
    <input type="submit" value="Save" />
}

然后三个视图呈现如下:

<form action="/" method="post">
  <input class="text-box single-line" id="Name" name="Name" type="text" value="" />
  <select id="Address_City" name="Address.City">
    <option selected="selected">Select one...</option>
    <option value="Anywhere">Anywhere</option>
    <option value="Somewhere">Somewhere</option>
    <option value="Nowhere">Nowhere</option>
  </select>
  <input class="text-box single-line" id="Address_Zip" name="Address.Zip" type="text" value="" />
  <input type="submit" value="Save" />

示例项目可在此处找到:https://github.com/bchristie/StackOverflow-Examples/tree/master/questions-19247958