简体   繁体   English

MVC 3:模型的AJAX发布列表属性

[英]MVC 3: AJAX post list property of model

I'm having trouble posting an ajax call with my model which has a list. 我无法在具有列表的模型中发布ajax调用。

My model is: 我的模型是:

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

in my view, i'm trying to display the list items of MyList as: 在我看来,我试图将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>

this view is a partial view, and it's called from the "main" view like this: 该视图是局部视图,从“主”视图中调用,如下所示:

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

My ajax post is: 我的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);
    }
}

my controller is: 我的控制器是:

        [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);

        }
    }

this concept works perfectly for me when using a direct property of my model. 当使用模型的直接属性时,此概念对我来说非常有效。 eg if I try to set/get the property of Str. 例如,如果我尝试设置/获取Str的属性。 However, for the MyList items, they never seem to get serialized properly in the Json command. 但是,对于MyList项目,它们似乎从未在Json命令中正确序列化。 It retains the values which were part of the original model. 它保留原始模型中的值。 ie the first time I call this, MyList is null so I create it and return it as part of the Action Result. 即,当我第一次调用此函数时,MyList为null,因此我将其创建并作为操作结果的一部分返回。 This displays the values ok. 这将显示确定。 However, if I manually edit the value and re-post it, the value which is posted is the same as was originally retrieved. 但是,如果我手动编辑该值并重新过帐,则过帐的值与最初检索的值相同。

I believe it's possibly something to do with the name I'm giving the TextArea and it can't be resolved properly. 我相信这可能与我给TextArea提供的名称有关,并且无法正确解析。 Using Firebug, the source for one of the text areas given is: 使用Firebug,给定文本区域之一的来源是:

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

So I'm trying to determine why the Encoding of my model doesn't have the updated (edited) values. 因此,我试图确定为什么我的模型的编码没有更新(编辑)的值。

TIA TIA

I would recommend you using editor templates. 我建议您使用编辑器模板。 So you could replace the foreach loop you have written in your partial view with this: 因此,您可以将在局部视图中编写的foreach循环替换为:

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

and then define an editor template for the it which will be rendered for each element of the list ( ~/Views/Test1/EditorTemplates/MyListItem.cshtml or ~/Views/Shared/EditorTemplates/MyListItem.cshtml ): 然后为其定义一个编辑器模板,该模板将为列表的每个元素呈现( ~/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);

The editor template will take care of properly naming the input fields so that the default model binder properly deserializes them back. 编辑器模板将负责正确命名输入字段,以便默认模型绑定程序正确地反序列化它们。

Now in your main view you could also use editor template instead of the partial: 现在,在主视图中,您还可以使用编辑器模板代替部分模板:

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

and then the editor template that I shown earlier will be placed by convention in ~/Views/Test1/EditorTemplates/MyModel.cshtml or ~/Views/Shared/EditorTemplates/MyModel.cshtml . 然后按照约定将我之前显示的编辑器模板放置在~/Views/Test1/EditorTemplates/MyModel.cshtml~/Views/Shared/EditorTemplates/MyModel.cshtml

OK, so far so good. 好的,到目前为止很好。 The last step is to send an AJAX request. 最后一步是发送AJAX请求。 This could be done in a separate javascript file: 这可以在一个单独的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);
    }
});

Clean and simple. 干净简单。

Now that we have cleaned the view and the javascript we have to clean the controller action which is where your original problem comes from. 现在,我们已经清理了视图和JavaScript,现在必须清理控制器操作,这是您最初的问题所在。 So in your controller action you are trying to modify POSTed values. 因此,在您的控制器操作中,您尝试修改POSTed值。 The problem with this is that HTML helpers use ModelState values when binding and after that they use the model. 问题是HTML助手在绑定时使用ModelState值,然后再使用模型。 This is by design. 这是设计使然。 So the values you put in your model are completely ignored by the helpers and you see old values which were the one posted to the controller action. 因此,您输入到模型中的值将被助手完全忽略,并且您看到的旧值是发布到控制器操作中的值。 You will have to remove them from the model state first. 您必须首先将它们从模型状态中删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM