c# - MVC 下拉列表复杂父模型

标签 c# jquery asp.net-mvc entity-framework

我猜我在这里错过了一个简单的原则,有人会很快指出。我本质上有一个 Person 对象,其中包含一些基本属性,然后是几个用于电话和地址的 Lists<> 。电话和地址各有一个类型(家庭/工作/等)。地址还有州和县。

当我执行“管理”操作时,我正在为 CountyId、StateProvinceID 等设置 ViewBag。但是当我有第二个地址或电话时,这些下拉列表似乎没有正确的选择值。

我确信这是一个可悲的基本问题,我在这里做错了......

已解决...

我知道我缺少一些基本的东西,答案是简单地为地址和电话对象创建自定义 View 模型。这些新的 View 模型可以包含每个选择列表的列表...

模型示例

public CustomerModel()
    {
        IsActive = true;
        if (Phones == null)
        {
            Phones = new List<Phone>();
        }
        if (Addresses == null)
        {
            Addresses = new List<Address>();
        }
    }

    public Guid Id { get; set; }
    public Guid OrganizationId { get; set; }

    [Required]
    public String FirstName { get; set; }
    public String MiddleName { get; set; }
    [Required]
    public String LastName { get; set; }

    [RegularExpression(".+\\@.+\\..+", ErrorMessage = "Please enter a valid email address.")]
    public String EmailAddress { get; set; }

    [DataType(DataType.Date)]
    public DateTime? DateOfBirth { get; set; }

    public List<Phone> Phones { get; set; }
    public List<Address> Addresses { get; set; }
}

家长查看示例

<tbody id="tblAddressRows">
    @foreach (var address in Model.Addresses)
    {
        Html.RenderPartial("_AddressRow", address);
    }
</tbody>

部分 View 示例

<td>
    @Html.HiddenFor(a => a.Id)
    @Html.DropDownList("AddressTypeId", ViewData["AddressTypeId"] as SelectList)
</td>
<td class="AddressLines">
    @Html.EditorFor(a => a.AddressLine1)
    @Html.EditorFor(a => a.AddressLine2)
</td>
<td>
    @Html.EditorFor(a => a.City)
</td>
<td>
    @Html.DropDownListFor(m => m.StateProvinceId,  ViewData["StateProvinceId"] as SelectList, new {@class = "State"})
</td>
<td>
    @Html.EditorFor(a => a.PostalCode, new {@class = "ZipCode"})
</td>
<td>
    @Html.DropDownList("CountyId", ViewData["CountyId"] as SelectList, new {@class = "County"})
</td>

Controller 示例

//
// GET: /Customer/Manage/5
public ActionResult Manage(Guid id)
{
    CustomerModel customer = DataService.GetCustomer(id, HttpContext.User.Identity.Name);
    if (customer == null)
    {
        return HttpNotFound();
    }
    ViewBag.AddressTypeId = new SelectList(DataService.GetOrganizationAddressTypes(HttpContext.User.Identity.Name), "Id", "Name");
    ViewBag.PhoneTypeId = new SelectList(DataService.GetOrganizationPhoneTypes(HttpContext.User.Identity.Name), "Id", "Name");
    ViewBag.StateProvinceId = new SelectList(DataService.GetStates(), "Id", "Name");
    ViewBag.CountyId = new SelectList(DataService.GetCounties(0), "Id", "Name");
    return View(customer);
}

最佳答案

这里有很多问题,其中一些你还没有注意到。但你会的。

首先,您不应该将下拉列表的集合命名为与您选择的值相同的名称。 MVC 以一些不明显的方式使用 ViewBagViewState ,如果这样做你会遇到很多麻烦。将项目列表更改为 StateProvinceListCountyList 以及 PhoneTypeListAddressTypeList

第二件事是您将无法将值正确地发送回 Controller ,因为您正在使用部分 View 来渲染集合的子项,并将该项作为模型传递给 View 。 MVC 基于模型作为根来渲染对象,并假设情况如此,它会创建名称。如果您将项目发布到接受父类的操作方法,则模型绑定(bind)器将无法正确绑定(bind)部分呈现的值(因为 MVC 将它们呈现为该子模型,而不是该子模型的集合) .

您应该使用 EditorTemplate,它可以做几件事。首先,EditorTemplate 将自动迭代所有集合,其次它会使用考虑到父类的正确名称来呈现表单控件的名称。

在此处阅读有关 EditorTemplates 的更多信息:

http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html

旁白:

为什么对 StateProvince 使用 DropDownListFor 而对 County 和 Address 使用 DropDownList?如果可以的话,请始终使用强类型版本,这有助于防止表单项命名错误。

另一件事,为什么构造函数中要使用 if block ?根据定义,构造函数仅在构造对象时被调用,因此属性将始终为 null(好吧,有人可以从您的类派生并在子类构造函数中设置这些属性,但如果这是您的代码,您就会知道这一点)

关于c# - MVC 下拉列表复杂父模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15825189/

相关文章:

asp.net-mvc - 无法将 App_Data 中的 .mdf/.ldf checkin TFS

c# - C# 和 Objective c 中的字符串加密

c# - ObjectDataSource 没有找到 SelectCountMethod

jquery - Fancybox 调整大小以适合内容,无标题

javascript - 获取 {{#each}} 的 .html()

c# - 如何将 Web API 添加到现有的 ASP.NET MVC Core 6 Web 应用程序

c# - 列表<>求和重载

c# - 无法设置 AuthenticationHeaderValue

javascript - 如何在Angular表分页中获取增量序列号

asp.net-mvc - 创建值从 0 到 10 的 asp.net mvc 下拉列表的最简单方法?