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

sna*_*ahi 6 .net c# asp.net-mvc razor asp.net-mvc-3

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

我在.NET 4.0中使用ASP.NET MVC 3

我想为具有子模型的模型创建一个"创建"视图.此视图应包含子模型的部分 "创建"视图,我将使用以下简单示例进行说明:

  • 模型

    class Person
    {
        public string Name { get; set; }
        public Address { get; set; }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 地址模式

    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; } )
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 控制器动作

        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
            }
        }
    
    Run Code Online (Sandbox Code Playgroud)
  • 我想要的视图层次结构:

人创建视图层次结构

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

第一种方法:使用@Html.Partial(..)@{Html.RenderPartial(..)}


我做了什么 :

问题 :

提交表单时,person.Address为null.在Google上进行了一些搜索之后,我发现为了使地址字段的提交起作用,生成的HTML标记必须是以下内容(注意Address_前缀):

<form...>
    <input type=text id="Name" />
    <input type=text id="Address_Zip" />
    <select id="Address_City">
        <!-- options... -->
    </select>
</form>
Run Code Online (Sandbox Code Playgroud)

不用说,在我的情况下生成的HTML标记不一样,但它是以下(Address_缺少前缀):

<form...>
    <input type=text id="Name" />
    <input type=text id="Zip" />
    <select id="City">
        <!-- options... -->
    </select>
</form>
Run Code Online (Sandbox Code Playgroud)

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


我做了什么 :

  • 我将地址局部视图移动到文件夹View/Shared/EditorTemplates,确保它AddressPerson模型中的属性具有相同的名称,即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
    }
    
    Run Code Online (Sandbox Code Playgroud)

问题 :

使用这种方法,生成的标记实际上具有正确的前缀(即Address_),但是我得到的Object引用没有设置Address.CityDropDown属性的实例异常,它告诉我控制器动作中的预初始化的Address对象没有传递给局部视图由于某种原因.

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


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

总结一下


我应该怎么做才能拥有可以在我的应用程序中使用的可重用的部分创建视图?

Bra*_*tie 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" }
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

这将使该视图仅包含:

@Html.EditorForModel()
Run Code Online (Sandbox Code Playgroud)

然后你EditorTemplates会从那里拿起:

~/Views/shared/EditorTemplates/Address.cshtml(注意:这是基于类型而不是属性名称)

@model MvcApplication.Models.Address
@Html.DropDownListFor(x => x.City, Model.CityDropDown)
@Html.EditorFor(x => x.Zip)
Run Code Online (Sandbox Code Playgroud)

〜/Views/Shared/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" />
}
Run Code Online (Sandbox Code Playgroud)

然后三个视图呈现如下内容:

<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" />
Run Code Online (Sandbox Code Playgroud)

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