asp.net-mvc-3 – 模型绑定器和隐藏字段

我有一个简化的测试场景,可用于提出这个问题:一个产品可以有很多组件,一个组件可以属于许多产品. 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; }
}

通过以下控制器操作完成组件的创建:

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();
}

并且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>

从中可以看出组件创建是通过上面的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",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" />
}

好.所以我正在努力解决这个问题:我需要[HttpPost]的模型参数来正确填充,即它应该包含一个Product,因为我无法使用null产品创建新组件.要获得产品,我需要通过产品ID查找产品.我希望我能做到:

model.Products.Add(db.Products.Find(model.Products.First().Id));

或某些这样的东西,它依赖于接收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)

但这没有产生任何东西 – 我已经读过这个助手不会迭代.我试过x => x.Products.First()但是甚至没有编译.最后,我决定放弃* For并自己编写名称:

@foreach (Product p in Model.Products)
{
    @Html.Hidden("Products[0].Id",p.Id)

虽然看起来不错,但是回发没有看到我的值(Products.Count == 0).我在一些帖子中看到格式应该看起来像[0] .Id但这也不起作用. GRR …

我收集我可以像这样编码:

@Html.Hidden("ProductId",p.Id)

然后重新声明我的控制器动作,如下所示:

[HttpPost] ActionResult Create(Component model,int ProductId)

但这似乎很有意思.很难相信这是如此困难.有人可以帮忙吗?

> e

附:如果有人关心,我有一个我可以下载的项目

解决方法

而不是编写那些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>

并在相应的编辑器模板内(〜/ Views / Shared / EditorTemplates / Product.cshtml)

@model Product
@Html.HiddenFor(x => x.Id)

相关文章

引言 本文从Linux小白的视角, 在CentOS 7.x服务器上搭建一个...
引言: 多线程编程/异步编程非常复杂,有很多概念和工具需要...
一. 宏观概念 ASP.NET Core Middleware是在应用程序处理管道...
背景 在.Net和C#中运行异步代码相当简单,因为我们有时候需要...
HTTP基本认证 在HTTP中,HTTP基本认证(Basic Authenticatio...
1.Linq 执行多列排序 OrderBy的意义是按照指定顺序排序,连续...