5

注意:我使用的是MVC3+Razor、EF4、CF-CTP5

  1. 如何让视图能够在客户端上为每个组织动态添加多个地址类,并在发布时与模型强绑定?

  2. 如果 (ModelState.IsValid == false) 如果您输入 3 个地址并发布无效模型,它如何重新填充数字地址及其适当的值?

这是我的模型:

public class Organization
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
    ...
}

public class Address
{
    public int Id { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    public int Type { get; set; }
}

我试图弄清楚如何让组织的创建操作(/组织/创建)像这样处理创建(这样地址和电话号码是提交模型的一部分):

[HttpPost]
public ActionResult Create(Organization organization)
{
    if (ModelState.IsValid)
    {
        _db.Organizations.Add(organization);
        _db.SaveChanges();
        return RedirectToAction("Details", organization.Id);
    }

    return View(organization);

}
4

3 回答 3

1

您的问题非常广泛:) 这只是您可以实现要求的一种方式,我相信有比我更好的方式。

我将从你的第二个问题开始:

如果 (ModelState.IsValid == false),如果您输入 3 个地址并发布无效模型,它如何重新填充数字地址及其适当的值?

如果我正确理解您的要求,那对我来说看起来很简单。答案是简单地编写您的视图以呈现模型类内容并将无效模型返回给客户端,就像您在Create操作中所做的那样。

如果您的表单(及其字段)已使用ValidationSummary/ValidationMessagehtml 助手进行修饰,您还将看到验证消息。

  1. 如何让视图能够在客户端上为每个组织动态添加多个地址类,并在发布时与模型强绑定?

您可以有一个显示组织属性的主视图,然后有另一个显示相关地址的视图。您可以在此处放置一个超链接或一个按钮,以打开一个对话框以添加新地址对象,然后在完成后刷新地址列表。同样,您可以将编辑和删除按钮作为列表中的图标。

地址列表是一个完全在客户端处理的标记,要正确绑定到服务器端模型类,它的输入属性应该遵守一些简单的命名规则。

要使 Default Model Binder 类正确绑定您的表单,请为您的Organization类使用以下代码段

@using (Html.BeginForm()) {
    @Html.HiddenFor(o => o.Id)
    @Html.ValidationSummary( true )
    <fieldset>
        <legend>My Organization</legend>
        <div class="editor-label">@Html.LabelFor( model => model.Name )</div>
        <div class="editor-field">
            @Html.EditorFor( model => model.Name )
            @Html.ValidationMessageFor( model => model.Name )
        </div>
        <br />
        <div id="container">
            <div>Address List</div>
            @foreach (Address a in Model.Addresses ) {
                Html.EditorFor(a);
            }
        </div>
        <div style="text-align:right;margin-top:14px;">
            <input type="submit" id="btnSubmit" value="Save" />
        </div>
    </fieldset>
}

要自动绑定,表单的结果代码应如下所示

<form action="..." id="..." method="post">
    <input type="hidden" name="Id" value="2">
    <input type="hidden" name="Name" value="Acme Corporation">

    <!-- markup for each address -->
    <input type="hidden" name="Addresses[0].Id" value="1">
    <input type="hidden" name="Addresses[0].Line1" value="Line 1">
    <input type="hidden" name="Addresses[0].Line2" value="Line 2">
    ... and so on...
</form>

将其属性命名为Addresses[index].PropertyName. 如果您在客户端上添加新地址,这并不重要:只要您的代码遵守此规则,您就可以让默认的模型绑定器为您完成这项工作。

希望这可以帮助

于 2011-01-03T22:09:05.823 回答
0

我不确定我是否正确理解了您的问题,但关于问题 1,我认为您正在寻找 ViewModel。大概是这样。。

组织视图模型.cs

public class OrganizationViewModel
{
  public OrganizationViewModel(Organization org, IList<Address> addresses)
     {
       this.Organization = org;
       this.Addresses = addresses
     }
     public Organization Organization {get;set;}
     public IList<Address> Addresses {get;set;}
}

组织控制器.cs

public class OrganizationController : Controller
{
  private readonly IOrganizationService _organizationService: //or whatever method you use
  public OrganizationController(IOrganizationService orgService)
     {
       this._organizationService = orgService;
     }

   public ActionResult Item(int id)
     {
       var org = _organizationService.GetOrganizationById(id);
       var addresses = _organizationService.GetOrgAddressesByOrgId(id);
       return View(new OrganizationViewModel(program, addresses));
     }
}

项目.cshtml

@model OrganizationViewModel
<h1>@Model.Organization.Name</h1>
<ul>
@foreach(var a in Model.Addresses)
{
<li>@a.Line1</li>
<li>@a.Line2</li>}
</ul>

在我尝试回答第 2 题之前,也许您应该指出我是否正确理解了第 1 题。希望这会有所帮助。

于 2011-01-28T15:15:01.490 回答
0

我设法使用 LINQ to SQL 做到了这一点。现在我尝试改用实体框架,但它确实让一切变得更加复杂。所以我没有适合你的解决方案,但也许我的 L2S 解决方案可能会有所帮助?

使用从我的数据库生成的模型,我可以在我看来这样做:

@for (int i = 0; i < Model.Contact.EmailAddresses.Count; ++i)
{
    <li>
        @Html.TextBoxFor(x => x.Contact.EmailAddresses[i].EmailAddress)
        @Html.HiddenFor(x => x.Contact.EmailAddresses[i].EmailAddressID)
    </li>
} 

我有一个视图模型类:

class ContactViewModel
{
    Contact contact { get; set; }
}

这工作得很好,在我的控制器操作中,我得到了我的 Contact 对象,它的 Contact.ContactEmailAddresses 列表就像我预期的那样填充。

但是对于 EF,我不能再使用从数据库生成的 EmailAddresses 属性上的 [i] 了。我想出的最好的是:

@Html.TextBox("Contact.EmailAddresses[" + i + "].EmailAddress", Model.Contact.EmailAddresses.ElementAt(i).EmailAddress)
于 2011-03-04T18:21:50.517 回答