6

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

人员创建视图层次结构

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

第一种方法:使用@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为空。在谷歌上搜索了一下,我发现为了地址字段的提交工作,生成的 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,它告诉我控制器操作中的预初始化地址对象未传递给出于某种原因的部分观点。

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


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

总结一下


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

4

1 回答 1

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)

~/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" />
}

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

<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

于 2013-10-08T12:56:52.903 回答