对集合使用getter时,ASP.NET MVC3模型绑定器数据无效



使用此联系人模型

public class Contact
{
    public string Name { get; set; }
    public ICollection<Phone> Phones { get; set; }
    public Phone PrimaryPhone
    {
        get { return Phones.FirstOrDefault(x => x.Primary) ?? new Phone(); }
    }
}
public class Phone
{
    public bool Primary { get; set; }
    public string PhoneNumber { get; set; }
    public string Type { get; set; }
}

这个控制器

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
    [HttpPost]
    public ActionResult Index(Contact contact)
    {
        return View();
    }
}

当我使用jQuery POST到HomeController索引时

(function ($) {
        var myData = {
            Name: 'Wesley Crusher',
            Phones: [
                { Primary: false, PhoneNumber: '111-111-1111', Type: 'Business' },
                { Primary: true,  PhoneNumber: '222-222-2222', Type: 'Personal' },
                { Primary: false, PhoneNumber: '333-333-3333', Type: 'Business' }
            ],
            PrimaryPhone: { Primary: true, PhoneNumber: '111-111-1111', Type: 'Business' }
        };
        $.ajax({
            url: '@Url.Action("Index", "Home")',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify(myData)
        });
    })(jQuery)

模型绑定器错误构建了ICollection Phones数据为:

  • [0]Primary=false,PhoneNumber="111-111-1111",Type="Business"MVC3ModelBinderJsonTesting.Models.Phone
  • [1] Primary=true,PhoneNumber="111-111-1111",Type="Business"MVC3ModelBinderJsonTesting.Models.Phone
  • [2] Primary=false,PhoneNumber="333-333-3333",Type="Business"MVC3ModelBinderJsonTesting.Models.Phone

电话号码"111-111-1111"重复出现,类型为"商务"而非"个人"这种预期行为是出于某种原因还是一个错误?

如果你愿意,我可以发布一个示例项目,让我知道。

我认为这是因为它不是基元。它是一个复杂的对象,因此模型绑定器会尝试设置其属性。

模型绑定更适合绑定表示来自表单的输入的"输入模型"。在输入模型上使用业务逻辑计算属性可能不是您所看到的最佳方法。

您可能会将其作为一个扩展方法(遗憾的是,不支持扩展属性),而不是输入模型的属性。甚至是一种合适的方法。将其作为财产会让模型装订工认为这是一场公平的游戏。

如果它是一个get-only基元类型,它不会尝试设置它。

我认为发布PrimaryPhone是造成问题的原因。尝试删除

PrimaryPhone: { Primary: true, PhoneNumber: '111-111-1111', Type: 'Business' }

由于此属性只有一个getter,并且将由Primary属性正确确定,因此它应该仍然具有有效数据。

最新更新