通过ajax将对象列表发送到ASP.NET MVC中的操作

时间:2015-02-04 13:54:29

标签: c# jquery ajax asp.net-mvc

我有一个模型的基类:

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 ......

我的错误在哪里?

1 个答案:

答案 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的部分)。

旁注:您是否真的需要回发整个表单才能返回部分视图?