MVC 3:模型的AJAX post list属性
本文关键字:post list 属性 AJAX 模型 MVC | 更新日期: 2023-09-27 18:12:11
我有麻烦张贴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是空的,所以我创建它并返回它作为动作结果的一部分。这将显示值ok。但是,如果我手动编辑该值并重新发布它,则发布的值与最初检索的值相同。
我相信这可能与我给TextArea的名字有关,它不能被正确解决。使用Firebug,其中一个文本区域的源代码是:
<textarea id="MyList_0__Value" rows="1" name="MyList[0].Value" cols="10" value="Item 0">Item 0</textarea>
所以我试图确定为什么我的模型的编码没有更新(编辑)的值。
TIA
我建议您使用编辑器模板。因此,您可以将您在局部视图中编写的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,我们必须清理控制器动作,这是你最初的问题来自哪里。所以在你的控制器动作,你试图修改post值。这样做的问题是HTML帮助程序在绑定时使用ModelState值,然后再使用模型。这是设计好的。所以你放在你的模型中的值完全被助手忽略,你看到旧值,这是一个张贴到控制器动作。您必须首先将它们从模型状态中移除。