c# - ViewModel 中的类似属性名称未在 Controller 操作方法中绑定(bind)

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

最近我们将我们的应用程序从 MVC3 更新到 MVC4。在 MVC4 中,我们发现在我们的 ViewModel 中使用像 StudioStudioExecutive 这样的属性名称会导致发布时出现问题。在 Controller 方法中,当填充 StudioExecutive 时,我们将始终获得 Studio = null

这是我们问题的一个例子,希望这个问题有答案。

数据类:

public class TestContact
{

    public List<TestContactItem> Studio { get; set; }
    public List<TestContactItem> StudioExecutive { get; set; }

    public TestContact()
    {
        Studio = new List<TestContactItem>();
        StudioExecutive = new List<TestContactItem>();
    }
}

public class TestContactItem
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Controller 方法:

public ActionResult TestContactView()
{
    var vm = new TestContact();
    vm.Studio.Add(new TestContactItem(){Id=1, Name = "Studio Contact ID=1"});
    vm.StudioExecutive.Add(new TestContactItem() { Id = 2, Name = "Studio Exec Contact ID=2" });
    return View(vm);
 }

[HttpPost]
public ActionResult SaveTestContact(TestContact model)
{
    return Content("success");
}

使用 Ajax POST 查看/JavaScript:

@using System.Web.Script.Serialization
@model TestContact

<button type="button" onclick="SaveTestContact();">Click Here to Post</button>

<script type="text/javascript">

    $(document).ready(function() {
         globalTestModel = @Html.Raw(new JavaScriptSerializer().Serialize(Model));
    });

    function SaveTestContact() {
        // passing additional studio & studio executive parameter to controller because it was not mapping correctly to the server side viewmodel without it
        $.ajax({
            type: "POST",
            url: "/Test/SaveTestContact",
            data: JSON.stringify(globalTestModel),
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function (msg) {

            }
        });
    }
</script>

在这个例子中,我们用至少一个 Studio 和一个 StudioExecutive 填充我们的对象并渲染 View 。单击 View 中的按钮时,我们将同一对象发布到 Controller 方法,但 ViewModel 未正确绑定(bind) Studio 属性设置为 null。

*很遗憾,我无法发布图片我有对象的屏幕截图,显示 Studio 计数为 0,StudioExecutive 计数为 1

我们确实在 POST 之前放置了一个断点,以确保 JavaScript 上的序列化是正确的并且对象已被填充。

我们得出结论,这与 2 个属性的命名约定有关,一个是另一个的子字符串。任何遇到同样问题的人都可以为我们指明正确的方向。

最佳答案

我知道这不是问题的“完整答案”,但我觉得这会给问题提供更多见解,(我希望)最终会导致“完整解决方案” .

假设我们在每个 StudioStudioExecutive 字段中都有一个项目,如 OP 示例所示,并在 js 中执行以下操作:

globalTestModel = '@Html.Raw(new JavaScriptSerializer().Serialize(Model))';

$.ajax({
    type: "POST",
    url: "/Test/SaveTestContact",
    data: JSON.stringify(globalTestModel),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function (msg) {

    }
});

如前所述, Controller 方法只会接收 StudioExecutive。现在,如果我们执行相同的操作并在 js 中构建对象,如下所示,我们将得到相同的结果

o = {
    Studio: [{
        Id: 1,
        Name: 'Studio Contact ID=1',
    }],
    StudioExecutive: [{
        Id: 2,
        Name: 'Studio Exec Contact ID=2',
    }]            
};
$.ajax({
    type: "POST",
    url: "/Test/SaveTestContact",
    data: JSON.stringify(o),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function (msg) {

    }
});

现在有趣的部分来了。如果我们将另一个项目添加到 Studio 字段并以相同的方式发布,我们将得到相同的结果

// Do this in the controller and do the same ajax post
public ActionResult TestContactView()
{
    var vm = new TestContact();
    vm.Studio.Add(new TestContactItem(){Id=1, Name = "Studio Contact ID=1"});
    vm.Studio.Add(new TestContactItem(){Id=3, Name = "Studio Contact ID=3"});
    vm.StudioExecutive.Add(new TestContactItem() { Id = 2, Name = "Studio Exec Contact ID=2" });
    return View(vm);
 }

但如果我们将在 js 中构建对象,如下所示, Controller 将同时接收 Studio 和 2 个项目,以及 StudioExecutive 和一个项目。

o = {
    Studio: [{
        Id: 1,
        Name: 'Studio Contact ID=1',
    },
    {
        Id: 2,
        Name: 'Studio Contact ID=2',
    }],
    StudioExecutive: [{
        Id: 2,
        Name: 'Studio Exec Contact ID=2',
    }]            
};
// then do the ajax post

那么我们学到了什么

这告诉我们两件事:

  1. 默认模型绑定(bind)器有问题,它不能绑定(bind)两个或更多以相同名称开头的字段
  2. JSON.stringify 也可以 NOT 如果只有一项,但它可以 如果字段中有多个项目具有最短名称(例如 Studio )

关于c# - ViewModel 中的类似属性名称未在 Controller 操作方法中绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16072551/

相关文章:

javascript - *在* ajax更新后执行Javascript

c# - 从 C# 启动远程进程的问题

c# - File.Exists 总是返回 False c#

javascript - 从 iframe 内部获取鼠标绝对位置

javascript - Jquery选择器变量语法

javascript - 数据表服务器端脚本处理大量数据

javascript - 将大字符串 Ajax 发送到 PHP

c# - 有没有人有保持内存驻留并在计时器上运行操作的 .NET 程序的任何好例子?

C# Windows 服务 - 多个计时器

jQuery - 停止函数