在 MVC 3 应用程序中为模型中的对象属性创建视图?
我有一个 Asp.Net MVC 3 应用程序,其中包含一个由 EF 访问的数据库“Consultants”。现在,数据库中的顾问表与其他几个表存在一对多关系,以获取简历类型信息(工作经验等)。因此,用户应该能够填写一次他们的姓名等,但应该能够添加一些“工作经历”,等等。
但这些外键表是模型中的复杂对象,在创建“创建视图”时,我只获得简单的属性作为编辑器字段。我该如何设计一个或多个视图以便也可以填充复杂的对象?我在脑海中描绘了一个视图,其中简单的属性是简单的字段,然后是某种控件,您可以在其中单击“添加工作经验”,并且将添加所需的任意数量。但我该如何做到这一点并仍然使用模型绑定呢?事实上,我根本不知道该怎么做。 (顺便说一句,程序和语言代表一般的软件体验和自然语言能力,而不是编程语言,以防您想知道其中的关系)。
任何想法都非常感谢!
这是默认情况下通过 add View 命令创建的创建视图:
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Consultant</legend>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UserName)
@Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
这是 EF 数据库图:
更新:
根据根据建议,我尝试了史蒂文·桑德森的博客解决方案,但我无法让它正常工作。我在主视图中添加了此内容:
<div id="editorRows">
@foreach (var item in Model.Programs)
{
Html.RenderPartial("ProgramEditorRow", item);
}
</div>
<input type="button" value="Add program" id="addItem" />
我还添加了 javascript:
<script type="text/javascript">
var url = '@Url.Action("BlankEditorRow", "Consultant")';
$(document).ready(function () {
$("#addItem").click(function () {
$.ajax({
url: url,
cache: false,
success: function (html) {
alert(html);
$("#editorRows").append(html); }
});
return false;
});
});
</script>
部分视图:
@model Consultants.Models.Program
@using Consultants.Helpers
<div class="editorRow">
@*@using (Html.BeginCollectionItem("programs"))
{*@
@Html.TextBoxFor(model => model.Name)
@*}*@
</div>
以及控制器中的操作方法:
public ActionResult Create()
{
Consultant consultant = new Consultant();
return View(consultant);
}
public ActionResult BlankEditorRow()
{
return PartialView("ProgramEditorRow", new Program());
}
请注意,我在部分视图中注释掉了 Html.BeginCollectionItem 部分,因为我无法让它工作。它只给我史蒂文·桑德森谈到的隐藏字段,而不是实际的文本框。所以我尝试注释掉该部分,然后只有一个文本框。好吧,这让我得到了文本框,但我无法在 post 方法中获取该信息。我使用 Consultant 对象作为返回参数,但 Programs 属性不包含 Program。也许这与我无法让 BeginCollectionItem 帮助器工作有关,但无论如何我不明白如何做到这一点,或者如何访问据称添加到视图中的程序。对于一个简单的对象,我将通过 _repository.AddToConsultants(consultant) 之类的方法在 post 方法中添加新对象,当我保存到 EF 时,它会获取其 id。但是我如何对程序对象执行同样的操作并通过 EF 将其保存到数据库中?
I have an Asp.Net MVC 3 application with a database "Consultants", accessed by EF. Now, the Consultant table in the db has a one-to-many relationship to several other tables for CV type information (work experience, etc). So a user should be able to fill in their name etc once, but should be able to add a number of "work experiences", and so on.
But these foreign key tables are complex objects in the model, and when creating the Create View I only get the simple properties as editor fields. How do I go about designing the View or Views so that the complex objects can be filled in as well? I picture a View in my mind where the simple properties are simple fields, and then some sort of control where you can click "add work experience", and as many as needed would be added. But how would I do that and still utilize the model binding? In fact, I don't know how to go about it at all. (BTW, Program and Language stand for things like software experience in general, and natural language competence, not programming languages, in case you're wondering about the relationships there).
Any ideas greatly appreciated!
Here's the Create View created by the add View command by default:
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Consultant</legend>
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UserName)
@Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
And here's the EF database diagram:
Update:
According to suggestion, I tried Steven Sanderson's blog solution, but I can't get it to work properly. I added this in the main view:
<div id="editorRows">
@foreach (var item in Model.Programs)
{
Html.RenderPartial("ProgramEditorRow", item);
}
</div>
<input type="button" value="Add program" id="addItem" />
I also added the javascript:
<script type="text/javascript">
var url = '@Url.Action("BlankEditorRow", "Consultant")';
$(document).ready(function () {
$("#addItem").click(function () {
$.ajax({
url: url,
cache: false,
success: function (html) {
alert(html);
$("#editorRows").append(html); }
});
return false;
});
});
</script>
A partial view:
@model Consultants.Models.Program
@using Consultants.Helpers
<div class="editorRow">
@*@using (Html.BeginCollectionItem("programs"))
{*@
@Html.TextBoxFor(model => model.Name)
@*}*@
</div>
And action methods in the controller:
public ActionResult Create()
{
Consultant consultant = new Consultant();
return View(consultant);
}
public ActionResult BlankEditorRow()
{
return PartialView("ProgramEditorRow", new Program());
}
Note that I commented out the Html.BeginCollectionItem part in the partial view, because I can't get that to work. It only gives me the hidden field Steven Sanderson talks about, but not the actual textbox. So I tried commenting that part out and just had a textbox. Well, that gets me the textbox, but I can't get to that info in the post method. I use the Consultant object as return parameter, but the Programs property contains no Program. Perhaps this has to do with the fact that I cannot get the BeginCollectionItem helper to work, but in any case I don't understand how to do that, or how to get to the Program supposedly added in the view. With a simple object I would add the new object in the post method by something like _repository.AddToConsultants(consultant), and when I save to EF it gets its id. But how do I do the same thing with the program object and save it to the database via EF?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Phil Haack 写了一篇很棒的博客文章,解释了如何对列表进行绑定建模。它是 MVC2 特有的,但我不确定版本 3 是否对此进行了改进。
模型绑定到列表。
在允许用户添加任意数量的项目的情况下,您可能希望使用 JavaScript 创建新的输入字段。 Steven Sanderson 在此展示了如何实现这一目标:
编辑可变长度列表,ASP.NET MVC 2 样式。
这些资源应该可以帮助您一路实现目标。
Phil Haack has written a great blog post which explains how to model bind to a list. It's specific to MVC2, but I'm not sure if version 3 has improved on this.
Model Binding To A List.
In a scenario where the user is allowed to add an arbitrary number of items, you'll probably want to create new input fields using JavaScript. Steven Sanderson shows here how to achieve that:
Editing a variable length list, ASP.NET MVC 2-style.
Those resources should get you all the way there.
您可以查看 以下关于编写自定义对象模板的博客文章。另外,请勿在视图中使用 EF 模型。设计视图模型,这些视图模型是专门针对给定视图的需求而定制的类,并在 EF 模型和应传递给视图的视图模型之间进行控制器映射。 AutoMapper 是一个可以简化此映射的好工具。
You may take a look at the following blog post about writing custom object templates. Also don't use EF models in your views. Design view models that are classes specifically tailored to the needs of a given view and have your controller map between the EF models and the view models that should be passed to the view. AutoMapper is a good tool that could simplify this mapping.