【问题标题】:ASP.Net MVC4 bind a "create view" to a model that contains ListASP.Net MVC4 将“创建视图”绑定到包含列表的模型
【发布时间】:2014-07-27 04:20:48
【问题描述】:

您好,在互联网领域,我有一个有趣的难题要问您:

如果该对象包含纯粹使用 MVC 视图/部分视图的其他对象列表,是否可以绑定视图以创建对象?

伙计,结果很复杂……让我给你一个简短的代码示例来说明我的意思:

Models:
public class ComplexObject
{
    public string title { get; set; }
    public List<ContainedObject> contents { get; set; }
}

public class ContainedObject
{
    public string name { get; set; }
    public string data { get; set; }
}

很好很简单对吧?好的,因此对于“title”属性来说,创建其中之一的强类型视图非常简单:

something like:
@Html.TextBoxFor(x => x.title)

但我想不出使用 MVC 绑定“ContainedObjects”列表的好方法。我得到的最接近的是使用“列表”脚手架模板创建一个强类型的 IEnumerable 部分视图,并将其包含在页面上。

不添加样式等,该局部视图的默认外观是:

@model IEnumerable<MVCComplexObjects.Models.ContainedObject>

<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.data)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.data)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
            @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
        </td>
    </tr> 
}

</table>

但坦率地说,我不知道如何将其包含在新的 ComplexObject 的创建中。换句话说,我可以通过绑定显示已经存在的 ContainedObjects 列表,如下所示: @Html.Partial("PartialCreate", Model.contents)

但我想我真正想要的是:

@Html.PartialFor("PartialCreate", x => x.contents)

我应该注意,我使用 Javascript 进行编码并没有太多麻烦(我将包含下面的代码),但我真的很想知道是否有一种方法可以完全使用 MVC 来做到这一点。我最近从 WebForms 转换过来(我几乎只是用 AJAX 调用替换了我所有的回发),这种事情在我从事的项目中经常出现。

无论如何,这是我目前的做法:

HTML -

Name: <input type="text" id="enterName" />
Data: <input type="text" id="enterData" />
<a id="addItem">Add Item</a>

<ul id="addedItems">
</ul>

<a id="saveAll">Save Complex Object</a>

Javascript -

<script>
var contents = [];
$(document).ready(function () {

    $('#addItem').click(function () {
        var newItem = { name: $('#enterName').val(), data: $('#enterData').val() };
        contents.push(newItem);
        $('#addedItems').html('');
        for (var i = 0; i < contents.length; i++) {
            $('#addedItems').append(
                "<li>" + contents[i].name + ", " + contents[i].data + "</li>"
            );
        }
    });

    $('#saveAll').click(function () {

        var toPost = { title: "someTitle", contents: contents };

        $.ajax({
                url: '/Home/SaveNew',
                type: 'POST',
                data: JSON.stringify(toPost),
                dataType: 'json',
                contentType: 'application/json; charset=utf-8',
                success: function (data, textStatus, jqXHR) {
                    alert("win");
                },
                error: function (objAJAXRequest, strError) {
                    alert("fail");
                }
            });
    });

});
</script>

这不是一个糟糕的解决方案或任何东西,我只是不想每次我想保存一个新对象时都必须执行 Javascript 调用,而是在其他任何地方使用标准的 Razr 代码。我希望全面保持一致。

有没有其他人遇到过这个问题并找到了解决方案?

【问题讨论】:

  • 我不需要 javascript 方法,因为它永远不会“提交”。
  • 为什么不在您的 ajax 帖子中序列化表单?
  • 我不确定我是否在这里关注你@Maess,AJAX 部分在这里工作正常,因为我没有表单我不需要序列化它,我只是构建一个 JSON 对象并将其发送到我的控制器/操作。我正在寻找的是一种纯粹通过 Razor 语法和对象绑定来做到这一点的方法。
  • 如果您不想发布表单,则没有一种纯粹的剃刀方式可以做到这一点。您可以从 razor 发布一个带有 ajax 的 for,但它需要一个表单。否则,您的解决方案很好。
  • 弗兰基,我正遇到这种情况,人们不断将我发送到同一个 4 岁的 mvc 2 帖子,该帖子谈论“接近”的事情......我在这里发布了我的问题stackoverflow.com/questions/15373158/…如果您找到解决方案,我会非常感兴趣!

标签: asp.net-mvc


【解决方案1】:

【讨论】:

  • 第二篇文章比第一篇更有帮助,但两者都不是我想要的。第一篇文章侧重于如何提交静态大小的列表,而不是任意大小的列表。第二篇文章描述了如何编辑项目列表,但没有描述如何创建一个包含可变大小项目列表的全新对象。但是,我可以看到我如何能够劫持该模式以生成用于提交的动态输入列表。我现在给你一个投票,但我不认为这是解决问题的真正“解决方案”。
【解决方案2】:

我最近发现自己需要完成相同的任务,并且和您一样,不想添加一堆 javascript。我正在使用 MVC4,据我所知,似乎没有一种开箱即用的方法可以将模型的可枚举属性绑定到视图。 :(

但是,正如您在问题中所展示的,可以从视图中的模型中检索可枚举属性。诀窍就是将更新返回给控制器。离开您的示例模型,您的视图可能如下所示(您不需要制作部分模型):

@model MVCComplexObjects.Models.ComplexObject

<p>
@Html.ActionLink("Create New", "Create")
</p>

@using (Html.BeginForm("SaveNew", "Home", FormMethod.Post))
{
    <table>

        <tr>
            <th>
                @Html.DisplayNameFor(model => model.contents[0].name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.contents[0].data)
            </th>
            <th></th>
        </tr>

        @for (int i = 0; i < Model.contents.Count; i++)
        {
            <tr>
                <td>
                    @Html.TextBox("updatedContents["+i+"].name", Model.contents[i].name)
                </td>
                <td>
                    @Html.TextBox("updatedContents["+i+"].data", Model.contents[i].data)
                </td>
                <td>
                    @* Got rid of the edit and detail links here because this form can now act as both *@
                    @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
                </td>
            </tr> 
        }

    </table>

    <input type="submit" value="Save" />
}

您的控制器操作如下所示:

[HttpPost]
public ActionResult SaveNew(ICollection<ContainedObject> updatedContents)
{
    foreach (var co in updatedContents)
    {
        //Update the contained object...
    }

    return RedirectToAction("Index");
}

基本上,我们在视图中定义了一个新的集合对象,以便 MVC 在表单提交时传递给您的操作方法。新对象(本例中为“updatedContents”)与在 ComplexObject 模型中定义和填充的列表属性(本例中为“contents”)基本相同。

这是一个多一点的工作,但确实实现了不需要任何 javascript 来回发的目标。一切都可以使用标准 MVC 完成。

【讨论】:

  • 这是一种超级偷偷摸摸的做法……我喜欢它。
猜你喜欢
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多