在Asp.Net MVC 3应用程序复杂的子对象的集合? [英] Collection of complex child objects in Asp.Net MVC 3 application?

查看:83
本文介绍了在Asp.Net MVC 3应用程序复杂的子对象的集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够更新模型,并在同一视图子对象的所有集合。我已经提到了这些例子:<一href=\"http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx\">http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx和<一个href=\"http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/\">http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

例如,我有一个对象顾问,有WorkExperiences的集合。这一切都是在一个实体框架模型。在视图中,咨询对象的简单属性是没有问题的,但在收集我不能让一个文本框,以示对。我试图按照上述链接的例子,但它不工作。问题是,在这些实施例的模型仅仅是一个表(未用子列表属性的对象)。而且,该模型再次的EF模型。出于某种原因,似乎并不如这些例子工作。

只是为了简单起见,我试着做沿着菲尔Haacks例如线的东西,和刚刚获得的视图来显示文本框:

  @for(INT I = 0; I&LT; Model.WorkExperiences.Count;我++)
{
    Html.TextBoxFor(M = GT; m.WorkExperiences [I] .Name点);
}

我试图创建的控制器中的视图模型一个新的WorkExperience对象:

 公众的ActionResult创建(INT ID)
    {
        咨询顾问= _repository.GetConsultant(ID);
        DetailsViewModel VM =新DetailsViewModel();
        vm.WorkExperiences = consultant.WorkExperiences.ToList();
        vm.WorkExperiences.Add(新WorkExperience());
        返回查看(VM);
    }

但视图不显示的WorkExperience Name属性的任何空白文本框。如果在另一方面,我只是创建用于添加新WorkExperience对象,传递一个新的空WorkExperience对象模型独立的视图,这工作得很好:

  @ Html.EditorFor(型号=&GT; model.Name)

这给了我一个空的文本框,我可以保存新的对象。但是,根据上面的链接的例子,为什么我不能做到这一点在同一个视图作为顾问对象,具有收藏?

顺便说一句,这是形式的后续问题到一个较早的一个,那向我指出上面的链接,但我从来没有给它一个最终的解决方案。看到问题,如果需要更多的信息:<一href=\"http://stackoverflow.com/questions/5013578/create-views-for-object-properties-in-model-in-mvc-3-application\">Create查看对象的属性模型在MVC 3应用程序?

更新:

据答案,下面的评论,这里是与视图和EditorTemplate更新:

视图:

  @model Consultants.ViewModels.DetailsViewModel@ {
    ViewBag.Title =指数;
}&LT; H2&GT;指数&LT; / H&GT;&所述p为H.;
    @ Html.ActionLink(增加工作经验,CreateWorkExperience,新{ID = ViewBag.Consultant.Id})
&所述; / P&GT;
&LT;表&gt;
    &所述; TR&GT;
        百分位&GT;&LT; /第i
        &LT;第i个
            名称
        &LT; /第i    &LT; / TR&GT;@foreach(在Model.WorkExperiences VAR项){
    &所述; TR&GT;
        &所述; TD&GT;
            @ Html.ActionLink(编辑,编辑,新{ID = item.Id})|
            @ Html.ActionLink(详细信息,详细信息,新{ID = item.Id})|
            @ Html.ActionLink(删除,删除,新{ID = item.Id})
        &LT; / TD&GT;
        &所述; TD&GT;
            @项目名
        &LT; / TD&GT;    &LT; / TR&GT;}&LT; /表&gt;@for(INT I = 0; I&LT;型号WorkExperiences.Count;我++)
{
    Html.EditorFor(M =方式&gt;米WorkExperiences [I]);
}

(请注意,这一切是不是真的我怎么会在最后设计的,所有我现在追求的是让WorkExperience对象显示为一个空的文本框填写,并要能添加和删​​除这些文本框在菲尔哈克的和史蒂芬·桑德森的例子。)

该EditorTemplate:

  @model Consultants.Models.WorkExperience
@ Html.TextBoxFor(M =&GT; m.Name);

这东西与EditorTemplate工程菲尔哈克的样本项目,我下载尝试,但在这里,与EF模型或任何问题很好,我没有得到任何文本框都没有。视图中的表就在那里作为测试,因为在表中我得到的行,WorkExperiences,我是否添加一个空WorkExperience对象或填写其属性没关系,行显示为每个对象。但同样,没有文本框...


解决方案

  

例如,我有一个对象顾问,有WorkExperiences的集合。这一切都是在实体框架模型。


这就是你应该改进的第一件事:引进视图模型并且不使用你的域模型到视图

这是说,让我们继续前进的模板。所以,你可以完全消除需要编写循环在你的看法。

因此​​,这里是你的看法如何可能是这样的:

  @model Consultants.ViewModels.DetailsViewModel@ {
    ViewBag.Title =指数;
}&LT; H2&GT;指数&LT; / H&GT;&所述p为H.;
    @ Html.ActionLink(增加工作经验,CreateWorkExperience,新{ID = ViewBag.Consultant.Id})
&所述; / P&GT;
&LT;表&gt;
    &所述; TR&GT;
        百分位&GT;&LT; /第i
        &LT;第i个
            名称
        &LT; /第i
    &LT; / TR&GT;
    @ Html.DisplayFor(X =&GT; x.WorkExperiences)
&LT; /表&gt;@ Html.EditorFor(x.WorkExperiences)

所以你可以我们正在使用的显示模板,编辑模板。现在让我们来定义它们。

显示模板(〜/查看/共享/ DisplayTemplates / WorkExperience.cshtml

  @model AppName.Models.WorkExperience
&所述; TR&GT;
    &所述; TD&GT;
        @ Html.ActionLink(编辑,编辑,新{ID = Model.Id})|
        @ Html.ActionLink(详细信息,详细信息,新{ID = Model.Id})|
        @ Html.ActionLink(删除,删除,新{ID = Model.Id})
    &LT; / TD&GT;
    &所述; TD&GT;
        @型号名称
    &LT; / TD&GT;
&LT; / TR&GT;

编辑模板(〜/查看/共享/ EditorTemplates / WorkExperience.cshtml

  @model AppName.Models.WorkExperience
@ Html.TextBoxFor(X =&GT; x.SomePropertyOfTheWorkExperienceModelYouWantToEdit)
...

在这里重要的是命名约定。模板的名称应该是该项目的集合中的类型的名称。因此,例如,如果在您的视图模型,你有一个属性。

 公开的IEnumerable&LT;富&GT; {搞定;组; }

相应的模板应该叫 Foo.cshtml 并应位于〜/查看/共享/ DisplayTemplates 〜/查看/共享/ EditorTemplates 取决于它的作用。

所以,你可以看到我们已经摆脱了讨厌的循环。现在,不仅是观点看起来很干净,但你得到的输入字段的正确名称,以便您可以绑定值回后采取行动。

I want to be able to update a model and all its collections of child objects in the same view. I have been referred to these examples: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx and http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/ .

For example, I have an object Consultant, that has a collection of "WorkExperiences". All this is in an Entity Framework model. In the view, the simple properties of the Consultant object is no problem, but the collection I cannot get a textbox to show up for. I tried following the examples in the links above, but it doesn't work. The problem is, in those examples the model is just a list (not an object with a child list property). And also, the model again is an EF model. And for some reason that doesn't seem to work as in those examples.

Just to make it simple, I tried to do something along the lines of Phil Haacks example, and just get the View to show the textbox:

@for (int i = 0; i < Model.WorkExperiences.Count; i++)
{
    Html.TextBoxFor(m => m.WorkExperiences[i].Name);
}

I tried to create a new WorkExperience object in the controller for the ViewModel:

    public ActionResult Create(int id)
    {
        Consultant consultant = _repository.GetConsultant(id);
        DetailsViewModel vm = new DetailsViewModel();
        vm.WorkExperiences = consultant.WorkExperiences.ToList();
        vm.WorkExperiences.Add(new WorkExperience());           
        return View(vm);
    }

But the View doesn't show any empty textbox for the WorkExperience Name property. If on the other hand I create a separate View just for adding a new WorkExperience object, passing a new empty WorkExperience object as the model, this works fine:

@Html.EditorFor(model => model.Name)

That gives me an empty textbox, and I can save the new object. But why can't I do this in the same view as the Consultant object, with collections according to the examples in the links above?

BTW, this is sort of a follow-up question to an earlier one, that pointed me to the above links, but I never got to a final solution for it. See that question if more info is needed: Create Views for object properties in model in MVC 3 application?

UPDATE:

According to answers and comments below, here's an update with the View and an EditorTemplate:

The View:

@model Consultants.ViewModels.DetailsViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Add work experience", "CreateWorkExperience", new { id = ViewBag.Consultant.Id })
</p>
<table>
    <tr>
        <th></th>
        <th>
            Name
        </th>

    </tr>

@foreach (var item in Model.WorkExperiences) {
    <tr>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
            @Html.ActionLink("Details", "Details", new { id = item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.Id })
        </td>
        <td>
            @item.Name
        </td>

    </tr>

}

</table>

@for (int i = 0; i < Model. WorkExperiences.Count; i++)
{
    Html.EditorFor(m => m. WorkExperiences[i]);
}

(Please note that all this is not really how I'll design it in the end, all I am after right now is to get the WorkExperience object to show up as an empty textbox to fill out, and to be able to add and delete such textboxes as in Phil Haack's and Steven Sanderson's examples.)

The EditorTemplate:

@model Consultants.Models.WorkExperience


@Html.TextBoxFor(m => m.Name);

This stuff with the EditorTemplate works fine in Phil Haack's sample project, which I downloaded to try, but here, with the EF model or whatever the problem is, I don't get any textbox at all. The table in the view is just there as a test, because in the table I do get the rows for WorkExperiences, whether I add an empty WorkExperience object or fill out its properties doesn't matter, the rows show up for each object. But again, no textbox...

解决方案

For example, I have an object Consultant, that has a collection of "WorkExperiences". All this is in an Entity Framework model.

That's the first thing you should improve: introduce view models and don't use your domain models into the view.

This being said let's move on to the templates. So you can completely eliminate the need to write loops in your views.

So here's how your view might look like:

@model Consultants.ViewModels.DetailsViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Add work experience", "CreateWorkExperience", new { id = ViewBag.Consultant.Id })
</p>
<table>
    <tr>
        <th></th>
        <th>
            Name
        </th>
    </tr>
    @Html.DisplayFor(x => x.WorkExperiences)
</table>

@Html.EditorFor(x.WorkExperiences)

So as you can we are using a display template and an editor template. Let's define them now.

Display template (~/Views/Shared/DisplayTemplates/WorkExperience.cshtml):

@model AppName.Models.WorkExperience
<tr>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
        @Html.ActionLink("Details", "Details", new { id = Model.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id = Model.Id })
    </td>
    <td>
        @Model.Name
    </td>
</tr>

Editor template (~/Views/Shared/EditorTemplates/WorkExperience.cshtml):

@model AppName.Models.WorkExperience
@Html.TextBoxFor(x => x.SomePropertyOfTheWorkExperienceModelYouWantToEdit)
...

What is important here is the naming convention. The name of the template should be the name of the type of the item in the collection. So for example if in your view model you have a property

public IEnumerable<Foo> { get; set; }

the corresponding template should be called Foo.cshtml and should be located in ~/Views/Shared/DisplayTemplates or ~/Views/Shared/EditorTemplates depending on its role.

So as you can see we have gotten rid of the nasty loops. Now not only that the views look clean, but you get correct names for the input fields so that you can bind the values back in the post action.

这篇关于在Asp.Net MVC 3应用程序复杂的子对象的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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