MVC手动序列化复杂的对象或模型绑定

MVC manually serializing complex object or model binding

本文关键字:对象 模型 绑定 复杂 序列化 MVC      更新时间:2023-09-26

我在MVC中遇到的最大问题之一是,当我将一个复杂的属性(视图模型)附加到我的模型以用于表单时。例如,我有一个名为Customer.cs的模型。这个Customer(为了简单起见)在任何时候都有1个订单。所以我给他一个Customer.Order的属性。Customer有许多其他属性将他定义为一个独特的客户。Order属性本身有一组唯一的属性。所以我继续前进,构建我的控制器和其他模型值,最后我开始计算我的视图细节
我首先定义Form本身。

@using (Html.BeginForm("Customer", "Home", FormMethod.Post, new { @id = "customerForm" })

这个表单声明基本上告诉View,当用户单击Submit时,这个表单中的所有内容都应该被序列化并发送到Controller。首先,我为我的主模型Customer.cshtml创建一个视图。它接受一个Customer.cs模型。

我专门为我创建的这个名为Order.cshtml的复杂对象创建了一个视图。它接受了一个Order.cs模型(这样我以后就可以在其他父模型上重用它,比如Invoice,因为我很聪明,思维超前。)所以我已经编写了所有这些javascript和视图逻辑,这些逻辑依赖于视图的独立性和可与其他模型重用性。我的声明文本框看起来是这样的:

@Html.TextBoxFor(m => m. OrderDate) 

当我点击Submit时,我首先注意到的是Order对象中的值都没有返回。所以我坐在那里调试,这需要一段时间,但我最终发现这不会以这种方式工作。除非有一种方法可以单独序列化视图模型,然后将其附加到父模型,否则即使这样,您也必须编写一堆Javascript来手动覆盖默认的表单提交过程,以及您可能为客户端字段验证而提交的任何其他模型
我认为应该有一个更简单的方法来处理这个问题。我知道解决这个问题的方法,但并不好看。您"可以"为Order.cs创建视图,以接受Customer.cs模型。然后,使用文本框进行如下声明:

@Html.TextBoxFor(m => m.Order.OrderDate) 

定义视图上的所有属性。这将适用于默认绑定,一切都很好。不过,我已经用JavaScript编写的代码呢?我必须遍历并将"Order_"附加到表单上对ID的所有引用中。此外,现在这在模型之间不容易移动,每次创建使用Order对象的新模型时,我都必须重新创建此视图,因为它现在接受Customer.cs模型。我还必须重写javascript,或者想出一些奇特的方法来传递前缀(ViewData)。这似乎不正确。我做错了什么?

如果您为所有使用Order:的视图模型创建一个接口会怎么样

interface IWithOrder
{
    Order Order { get; set; }
}

在您的通用订单视图中使用此界面:

@model Project.ViewModels.IWithOrder
...
@Html.TextBoxFor(m => m.Order.OrderDate, new { Id = "OrderDate" }) 

在客户的情况下,您可以创建客户视图模型,该模型源自IWithOrder:

public class CustomerViewModel : IWithOrder
{
    public Order Order { get; set; }
    public Customer Customer { get; set; }
}

现在您可以重用Order视图,但视图模型需要从IWithOrder派生。

如果不想在js引用中附加Order_,也可以在TextBoxForhtmlAttributes参数中设置html元素的id。