我有一个模型的基类:
public abstract class ViewModel {
public string Title{ get; set; }
public abstract string Type { get; }
}
我创建了两个类:
public class SomeViewModel: ViewModel {
public override string Type { get { return "a type" } }
public int Id { get; set; }
}
public class AnotherModel: ViewModel {
public override string Type { get { return "another type" } }
public string System { get; set; }
}
现在,我有一个使用这些类的视图(我向视图发送List<ViewModel>
)
@model List<ViewModel>
...
<form>
@Html.DisplayFor(model => model)
</form>
我在ViewModel.cshtml
文件夹
DisplayTemplates
的视图
@model ViewModel
@if(Model is AnotherModel) {
// do something and print value
AnotherModel conv = Model as AnotherModel;
@Html.TextboxFor(model => conv.System)
} else {
// put some inputs here
}
@Html.HiddenFor(model => model.Type)
现在我有一个javascript ajax。我想将一个对象列表发送到一个呈现局部视图的动作
ajax:
$.ajax({
url: 'My/GetData',
dataType: "html",
type: "POST",
data: { id: 3, myList: $("form").serialize() }
success: function(data) {
// print html
}
});
和行动看起来像:
[HttpPost]
public ActionResult GetData(int id, List<ViewModel> myList){
...
return PartialView("myView", someModel)
}
问题是myList
参数,长度(计数)总是0 ...我希望是2 ......
我的错误在哪里?
答案 0 :(得分:0)
myList
不包含任何元素的原因无疑是因为控件名称与属性名称不匹配,但是您遇到的问题不仅仅是这些。派生模型中的Type
属性只有一个getter,所以即使集合确实正确绑定(它不会如下所述),Type
的值也是一个空字符串,因为没有setter在属性上(IsReadonly
的{{1}}属性设置为ModelMetadata
,因此true
忽略它),您将无法知道对象的类型。
接下来,DefaultModelBinder
只会初始化DefaultModelBinder
的实例,而不是您的派生类型,因此只有那些带有公共getter / setter的ViewModel
属性才会被绑定(例如{ {1}} ViewModel
的属性不存在)
我假设你的模型必须比你所展示的要复杂得多(否则就没有意义了)这意味着你的模板(它应该是Id
而不是SomeViewModel
!)必须被许多其他逻辑污染,以确定要渲染的属性和方式(以及调试的噩梦)。
简单的解决方案是创建一个视图模型,其中包含每种类型的集合(可能还包括您要发布的EditorTemplate
属性,但不确定它是什么或如何与您的模型相关)然后为每种类型使用DisplayTemplate
id
/Views/Shared/EditorTemplates/AnotherModel.cshtml
EditorTemplate
/Views/Shared/EditorTemplates/SomeViewModel.cshtml
public class TypeVM
{
public List<SomeViewModel> SomeTypes { get; set; }
public List<AnotherModel> AnotherTypes { get; set; }
}
并在视图中
@model SomeViewModel
....
@Html.TextBoxFor(m => m.Id)
如果您需要使用ajax提交,那么
@model SomeViewModel
....
@Html.TextBoxFor(m => m.System)
并发回
@model TypeVM
....
@Html.EditorFor(m => m.SomeTypes)
@Html.EditorFor(m => m.AnotherTypes)
这意味着在组中呈现不同的类型。如果这不合适,则需要创建自定义var url = '@Url.Action("GetData", "My")'; // don't hard code your url's!
var data = $("form").serialize();
$.post(url, data, function(data) {
// update DOM
});
,您可以使用[HttpPost]
public ActionResult GetData(TypeVM model)
来读取ModelBinder
属性并初始化每个派生类型并设置相应的属性。这是一项艰巨的任务,但The Features and Foibles of ASP.NET MVC Model Binding
可能会帮助您开始学习如何处理它(关于抽象模型Binder的部分)。
旁注:您是否真的需要回发整个表单才能返回部分视图?