【问题标题】:MVC 3: AJAX post list property of modelMVC 3:模型的 AJAX 帖子列表属性
【发布时间】:2011-10-23 16:27:05
【问题描述】:

我在使用具有列表的模型发布 ajax 调用时遇到问题。

我的模型是:

public class MyListItem
{
    public int Id { get; set; }
    public string Value { get; set; }
}

public class MyModel
{
    public int Integer { get; set; }
    public string Str { get; set; }
    public List<MyListItem> MyList { get; set; }        

    public MyModel()
    {
        Str = "Initial";
        Integer = 1;
    }
}

在我看来,我正在尝试将 MyList 的列表项显示为:

    <div>
    @{
            if (Model.MyList != null)
            { 
                int i = 0;
                foreach (var item in Model.MyList)
                {                       
                    <label>@item.Value</label>
                    @Html.Hidden("MyList[" + i + "].Id", item.Id);
                    @Html.TextArea("MyList[" + i + "].Value", item.Value, 1, 10, new { Value = item.Value });
                    <div />

                    i++;
                }
            }
    }
</div>

这个视图是一个局部视图,它是从“主”视图中调用的,如下所示:

<form id="mine2">
    @{Html.RenderPartial("Test2", Model);}
</form>

我的 ajax 帖子是:

    function OnAddToListAjax() {
    var actionUrl = '@Url.Action("AddToList", "Test1")';
    var alist = @Html.Raw(Json.Encode(Model));

    try
    {
        $.ajax(
        {
            url: actionUrl,
            type: "POST",
            dataType: "HTML",
            contentType: 'application/json',
            processData: false,
            //data: JSON.stringify({myModel: existing, list: alist}),
            data: JSON.stringify({myModel: alist}),
            traditional: true,
            success: function(result) {
                //alert(result);
                $('#mine2').html(result);
            },
            error: function (req, status, error) {
                HandleError(req);
            }
        });
    }
    catch (err)
    {
        alert(err);
    }
}

我的控制器是:

        [HttpPost]
    public ActionResult AddToList(MyModel myModel)//, MyList list)
    {
        try
        {

            //var list = new MyList();
            if (myModel.MyList == null)
                myModel.MyList = new MyList();
            myModel.Str += " Changed";

            //throw new Exception("This is broken!");
            myModel.MyList.Add(new MyListItem { Id = myModel.MyList.Count, Value = string.Format("Item {0}", myModel.MyList.Count) });
            //myModel.MyList = list;

            return PartialView("Test2", myModel);
        }
        catch (Exception ex)
        {
            myModel.ErrorModel = new ErrorModel() { ErrorDetails = "Error adding to list", ErrorString = ex.Message };
            return PartialView("Test2", myModel);

        }
    }

当使用我的模型的直接属性时,这个概念非常适合我。例如,如果我尝试设置/获取 Str 的属性。但是,对于 MyList 项目,它们似乎从未在 Json 命令中正确序列化。它保留了作为原始模型一部分的值。即我第一次调用它时,MyList 为空,所以我创建它并将它作为操作结果的一部分返回。这显示值正常。但是,如果我手动编辑该值并重新发布它,则发布的值与最初检索的值相同。

我相信这可能与我给 TextArea 的名称有关,并且无法正确解决。使用 Firebug,给定文本区域之一的来源是:

<textarea id="MyList_0__Value" rows="1" name="MyList[0].Value" cols="10" value="Item 0">Item 0</textarea>

所以我试图确定为什么我的模型的编码没有更新(编辑)的值。

TIA

【问题讨论】:

    标签: c# asp.net-mvc-3 razor


    【解决方案1】:

    我建议您使用编辑器模板。因此,您可以用以下代码替换您在局部视图中编写的 foreach 循环:

    @model MyModel
    <div>
        @if (Model.MyList != null)
        {
            @Html.EditorFor(x => x.MyList)
        }
    </div>
    

    然后为它定义一个编辑器模板,它将为列表的每个元素呈现(~/Views/Test1/EditorTemplates/MyListItem.cshtml~/Views/Shared/EditorTemplates/MyListItem.cshtml):

    @model MyListItem
    @Html.LabelFor(x => x.Value, Model.Value)
    @Html.HiddenFor(x => x.Id);
    @Html.TextAreaFor(x => x.Value, 1, 10);
    

    编辑器模板将负责正确命名输入字段,以便默认模型绑定器正确反序列化它们。

    现在在您的主视图中,您还可以使用编辑器模板而不是部分:

    @model MyModel
    @using (Html.BeginForm("AddToList", "Test1", FormMethod.Post, new { id = "myForm" }))
    {
        @Html.EditorForModel()
    }
    

    然后我之前展示的编辑器模板将按照约定放置在~/Views/Test1/EditorTemplates/MyModel.cshtml~/Views/Shared/EditorTemplates/MyModel.cshtml

    好的,到目前为止一切顺利。最后一步是发送 AJAX 请求。这可以在一个单独的 javascript 文件中完成:

    var myForm = $('#myForm');
    $.ajax({
        url: myForm.attr('action'),
        type: myForm.attr('method'),
        data: myForm.serialize(),
        success: function(result) {
            $('#mine2').html(result);
        },
        error: function (req, status, error) {
            HandleError(req);
        }
    });
    

    干净简单。

    现在我们已经清理了视图和 javascript,我们必须清理控制器操作,这是您最初的问题所在。因此,在您的控制器操作中,您正在尝试修改 POSTed 值。这样做的问题是 HTML 助手在绑定时使用 ModelState 值,然后他们使用模型。这是设计使然。因此,您在模型中输入的值会被帮助程序完全忽略,您会看到 old values 这是发布到控制器操作的值。您必须先将它们从模型状态中移除。

    【讨论】:

    • 谢谢。我必须吸收你写的东西。感谢您的回复。
    猜你喜欢
    • 2014-02-20
    • 2012-10-26
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多