编辑和保存复杂的对象 [英] Editing and saving complex objects

查看:167
本文介绍了编辑和保存复杂的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你有下列对象:

public class Address
{
  public String Line1 { get; set; }
  public String Line2 { get; set; }
  public String City { get; set; }
  public String State { get; set; }
  public String ZipCode { get; set; }

  public Address()
  {
  }
}

public class Contact
{
  public String FirstName { get; set; }
  public String LastName { get; set; }
  public String Telephone { get; set; }

  public Address BillingAddress { get; set; }
  public List<Address> ShippingAddresses { get; set; }

  public Contact()
  {
    // Assume anything that _could_ be null wouldn't be. I'm excluding
    // most "typical" error checking just to keep the examples simple
    this.BillingAddress = new Address();
    this.ShippingAddresses = new List<Address>();
  }
}

假设属性与装修[必需] [显示] 和其他属性。

Assume the properties are decorated with [Required], [Display] and other attributes.

然后我的控制器(简化演示的缘故):

Then my controller (simplified for the sake of demo):

public ActionResult Edit(String id)
{
  Contact contact = ContactManager.FindByID(id);
  return View(model: contact);
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contact)
{
  if (ModelState.IsValid) //always fails
  {
    ContactManager.Save(contact);
    return RedirectToAction("Saved");
  }
  return View(model: contact);
}

我一直在MVC编辑这样一个对象看到的演示,但他们都在不断突破的对象的集合在自己的形式(例如编辑联系人,然后编辑一个特定的地址掀起了接触)。我,另一方面,我试图编辑同一个页面中的所有这些信息,我有没有成功。例如:

I keep seeing demos on editing an object like this in MVC, but they are constantly breaking out collections of an object in to their own form (e.g. Edit the contact, then edit a specific address off of a contact). I, on the other hand, am trying to editing all this information within the same page and am having no success. For example:

@model Contact

// simplified for brevity
@using (Html.BeginForm())
{
  @Html.LabelFor(x => x.FirstName): @Html.EditorFor(x => x.FirstName)
  @Html.LabelFor(x => x.LastName): @Html.EditorFor(x => x.LastName)
  @Html.LabelFor(x => x.Telephone): @Html.EditorFor(x => x.Telephone)

  <div>
    @Html.LabelFor(x => x.BillingAddress.Line1): @Html.EditorFor(x => x.BillingAddress.Line1)
    @Html.LabelFor(x => x.BillingAddress.Line2): @Html.EditorFor(x => x.BillingAddress.Line2)
    @Html.LabelFor(x => x.BillingAddress.City): @Html.EditorFor(x => x.BillingAddress.City)
    @Html.LabelFor(x => x.BillingAddress.State): @Html.EditorFor(x => x.BillingAddress.State)
    @Html.LabelFor(x => x.BillingAddress.ZipCode): @Html.EditorFor(x => x.BillingAddress.ZipCode)
  </div>

  <div>
  @foreach (Address addr in Model.ShippingAddresses)
  {
    <div>
      @Html.LabelFor(x => addr.Line1): @Html.EditorFor(x => addr.Line1)
      @Html.LabelFor(x => addr.Line2): @Html.EditorFor(x => addr.Line2)
      @Html.LabelFor(x => addr.City): @Html.EditorFor(x => addr.City)
      @Html.LabelFor(x => addr.State): @Html.EditorFor(x => addr.State)
      @Html.LabelFor(x => addr.ZipCode): @Html.EditorFor(x => addr.ZipCode)
    </div>
  }
  </div>
}

我一直到运行的问题是, ModelState.IsValid 从来没有当我去保存信息回通行证。是否有一个把戏这样做,还是只是MVC的范围之外?我想借此对象如联系和转储一个页面进行编辑的所有信息,并将其成功地重新保存,但我似乎无法得到它上班。 (我的下一个步骤是阿贾克斯扳平所以你可以动态地添加页/删除ShipingAddresses,但我需要保存第一个工作 - K.I.S.S)

The problem I keep running in to is that the ModelState.IsValid never passes when I go to save the information back. Is there a trick to doing this, or is it just outside the realm of MVC? I would like to take an object like Contact and dump all the information on one page for editing, and have it re-save successfully, but I can't seem to get it to work. (My next step is to tie in ajax so you could dynamically add/remove "ShipingAddresses" on that page, but I need the save to work first--K.I.S.S)

问题:


  • ModelState.IsValid 几乎都是假

  • 收集物品表单元素经常具有相同的名称,所以在这个演示每个线路1 ShippingAddresses 集合转储到页面 NAME =addr_Line1,而不是像 ShippingAddresses [0] _Line1 像我期望

  • ModelState.IsValid is almost always false
  • Form elements for collection items frequently have the same names, so in this demo every Line1 in the ShippingAddresses collection dumps to the page as name="addr_Line1" instead of something like ShippingAddresses[0]_Line1 like I'd expect.

推荐答案

我猜 ModelState.IsValid 是假的,因为你没有正确填充送货地址集合。这是因为您没有为您的输入字段使用专有名词。看看在<一个href=\"http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx\">following文章更好地理解什么格式做的模型绑定您的期望输入字段,以便能够重建值返回来命名。

I guess ModelState.IsValid is false because you didn't populate the shipping addresses collection properly. This happened because you didn't use proper names for your input fields. Take a look at the following article to understand better what format does the model binder expects your input fields to be named in order to be able to reconstruct values back.

您code未产生正确的输入名称的原因是因为你用这个foreach循环中的观点失去了轨道导航上下文。

The reason your code is not generating correct input names is because you used this foreach loop in which the view lost track of the navigation context.

因此​​,尝试这样的:

So try like this:

@for (var i = 0; i < Model.ShippingAddresses.Count; i++)
{
    <div>
        @Html.LabelFor(x => x.ShippingAddresses[i].Line1): 
        @Html.EditorFor(x => x.ShippingAddresses[i].Line1)

        @Html.LabelFor(x => x.ShippingAddresses[i].Line2): 
        @Html.EditorFor(x => x.ShippingAddresses[i].Line2)

        @Html.LabelFor(x => x.ShippingAddresses[i].City): 
        @Html.EditorFor(x => x.ShippingAddresses[i].City)

        @Html.LabelFor(x => x.ShippingAddresses[i].State): 
        @Html.EditorFor(x => x.ShippingAddresses[i].State)

        @Html.LabelFor(x => x.ShippingAddresses[i].ZipCode): 
        @Html.EditorFor(x => x.ShippingAddresses[i].ZipCode)
    </div>    
}

备注:请注意,我还与EditorFor呼吁有效地生成这些字段输入字段替换重复的标签

Remark: notice that I have also replaced your duplicate labels with an EditorFor call to effectively generate input fields for those fields.

甚至更好的使用编辑器模板是这样的:

or even better using editor templates like this:

@model Contact

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.FirstName): 
    @Html.EditorFor(x => x.FirstName)

    @Html.LabelFor(x => x.LastName): 
    @Html.EditorFor(x => x.LastName)

    @Html.LabelFor(x => x.Telephone): 
    @Html.EditorFor(x => x.Telephone)

    @Html.EditorFor(x => x.BillingAddress)

    @Html.EditorFor(x => x.ShippingAddresses)
}

,然后定义将自动为 ShippingAddresses 集合中的每个元素被渲染(自定义编辑模板〜/查看/共享/ EditorTemplates / Address.cshtml

and then define a custom editor template which will automatically be rendered for each element of the ShippingAddresses collection (~/Views/Shared/EditorTemplates/Address.cshtml):

@model Address
<div>
    @Html.LabelFor(x => x.Line1): 
    @Html.EditorFor(x => x.Line1)

    @Html.LabelFor(x => x.Line2): 
    @Html.EditorFor(x => x.Line2)

    @Html.LabelFor(x => x.City): 
    @Html.EditorFor(x => x.City)

    @Html.LabelFor(x => x.State): 
    @Html.EditorFor(x => x.State)

    @Html.LabelFor(x => x.ZipCode): 
    @Html.EditorFor(x => x.ZipCode)
</div>

现在,你应该不再担心会输错名字。不但如此,但要重复使用为您的帐单地址和发货地址的集合地址编辑模板。它使你的看法DRYier。

Now you should no longer worry about getting wrong input names. And not only this but you are reusing the address editor template for both your billing address and the collection of shipping addresses. It makes your views DRYier.

这篇关于编辑和保存复杂的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆