ekk*_*kis 3 defaultmodelbinder razor asp.net-mvc-3 html.hiddenfor
我有一个简化的测试场景,可用于提出这个问题:一个产品可以有很多组件,一个组件可以属于许多产品.EF生成了类,我将它们修改如下:
public partial class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Component> Components { get; set; }
}
public partial class Component
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
通过以下控制器操作完成组件的创建:
public ActionResult Create(int ProductId)
{
Product p = db.Products.Find(ProductId);
Component c = new Component();
c.Products.Add(p);
return PartialView(c);
}
[HttpPost]
public ActionResult Create(Component model)
{
db.Components.Add(model);
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
并且GET方法返回的视图如下所示:
@model Test.Models.Product
<fieldset>
<legend>Product</legend>
<div class="display-label">Name</div>
<div class="display-field">@Model.Name</div>
</fieldset>
@Html.Action("Create", "Component", new {ProductId = Model.Id})
<p>
@Html.ActionLink("Edit", "Edit", new { id=Model.Id }) |
@Html.ActionLink("Back to List", "Index")
</p>
Run Code Online (Sandbox Code Playgroud)
从中可以看出组件创建是通过上面的相同页面处理的Html.Action- 该视图的代码如下:
@model Test.Models.Component
@using Test.Models
<script type="text/javascript">
function Success() {
alert('ok');
}
function Failure() {
alert('err');
}
</script>
@using (Ajax.BeginForm("Create", "Component", new AjaxOptions
{
HttpMethod = "Post",
OnSuccess = "Success",
OnFailure = "Failure"
}))
{
<fieldset>
<legend>Components</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>
@Html.HiddenFor(x => x.Products.First().Id)
@Html.HiddenFor(x => x.Products)
@foreach (Product p in Model.Products)
{
@Html.Hidden("Products[0].Id", p.Id)
}
@foreach (Product p in Model.Products)
{
@Html.Hidden("[0].Id", p.Id)
}
</fieldset>
<input type="submit" value="go" />
}
Run Code Online (Sandbox Code Playgroud)
好.所以我正在努力解决这个问题:我需要model[HttpPost] 的参数来正确填充,即它应该包含一个Product,因为我无法使用null产品创建新组件.要获得产品,我需要通过产品ID查找产品.我希望我能做到:
model.Products.Add(db.Products.Find(model.Products.First().Id));
Run Code Online (Sandbox Code Playgroud)
或某些依赖于model接收id的东西.这意味着视图必须将id放在那里,大概是在隐藏的字段中,从我的视图代码中可以看出,我已经多次尝试填充这个,所有这些都失败了.
通常我更喜欢*For方法,因为它们负责产生正确的命名法.如果.Products是单数(.Product),我可以引用它x => x.Product.Id,一切都会好,但由于它是复数,我不能这样x => x.Products.Id做我尝试x => x.Products.First().Id编译并生成正确的值但得到名称Id(这是错的,因为模型绑定器认为它是,Component.Id而不是Component.Products[0].Id.
我的第二次尝试是让HiddenFor迭代(就像我想的那样EditorFor):
@Html.HiddenFor(x => x.Products)
Run Code Online (Sandbox Code Playgroud)
但这没有产生任何东西 - 我已经读过这个助手不会迭代.我试过x => x.Products.First()但是甚至没有编译.最后,我决定放弃*For并自己编写名称:
@foreach (Product p in Model.Products)
{
@Html.Hidden("Products[0].Id", p.Id)
Run Code Online (Sandbox Code Playgroud)
虽然看起来不对,但是回发没有看到我的值(Products.Count== 0).我在一些帖子中看到格式应该看起来像[0].Id但是这也不起作用.GRR ...
我收集我可以像这样编码:
@Html.Hidden("ProductId", p.Id)
Run Code Online (Sandbox Code Playgroud)
然后重新声明我的控制器动作,如下所示:
[HttpPost] ActionResult Create(Component model, int ProductId)
Run Code Online (Sandbox Code Playgroud)
但这似乎很有意思.很难相信这是如此困难.有人可以帮忙吗?
ps我有一个项目,如果有人关心,我可以下载
Dar*_*rov 13
而不是编写这些foreach循环尝试使用编辑器模板:
<fieldset>
<legend>Components</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>
@Html.EditorFor(x => x.Products)
</fieldset>
Run Code Online (Sandbox Code Playgroud)
并在相应的编辑器模板(~/Views/Shared/EditorTemplates/Product.cshtml)内
@model Product
@Html.HiddenFor(x => x.Id)
Run Code Online (Sandbox Code Playgroud)