MVC + DDD - 模型与参数化域对象构造函数绑定
MVC + DDD - Model binding with parameterised Domain object constructors
我有一个应用程序试图在一定程度上遵循领域驱动设计。我有一个域层,里面的 classes 有参数化的构造函数。
我的 ViewModels 当然有无参数的构造函数,以允许模型绑定。但是一页给我带来了问题。
我的一个页面显示了一个汽车列表,用户可以编辑其中的详细信息,然后通过JQuery POST 将一辆汽车的数据发送到后端。 Car 是一个域对象,只有一个带参数的构造函数(我在构造函数内部进行业务逻辑检查)。
我的后台代码是这样的
[AjaxOnly]
public JsonResult Update(Car car)
{
//...
}
当然这会失败,因为 Car 是一个域 class 并且没有无参数构造函数。
我想知道这种情况下是否有公认的最佳实践。我可以想到两个,可能是三个选项:
1) 为 Cars 域创建无参数构造函数 class。用
装饰它
[Obsolete("For model binding only")]
防止用户直接调用。然后在我的 JsonResult 方法中立即调用参数化构造函数。不幸的是,这意味着在模型中将我的私有设置器更改为 public。
2) 接受 FormCollection,提取值,并调用参数化构造函数。这类似于 1) 但不需要更改私有设置器。
3) 也许是自定义模型活页夹?我已经为 IoC 为我的 MVC 控制器执行此操作,但不知道它如何用于非控制器。
是否有处理此问题的最佳实践方法?
你的描述有点贫血领域模型的味道。您的 Update
方法让我想到了 DDD 的 CRUD 方法。这是错误的。
您的 Car
域模型应该具有每种类型的可更新命令(例如 UpdatePrice
、UpdateAvailability
假设您正在开发管理限界上下文)。因此,您的表示层,换句话说,您的 ASP.NET 应用程序应该具有:
[AjaxOnly]
public JsonResult UpdateColor(UpdateColorViewModel vm)
{
Car car = repository.getById(vm.id);
try
car.UpdateColor(vm.color);
catch
// return some sort of errors
// return some sort of ok
}
如果您没有,严格来说,贫血领域模型,那么您的问题就是您的 UI。要应用 DDD,您需要 task-based UI design。没有好的 task-based UI 你就卡住了;身体上(你的建筑),更糟糕的是,精神上;在贫血模型中,因为您的系统不知道用户在做什么。
一旦您知道,在您的 UI 层中,用户在做什么;您可以提供从 UI 到域层操作的命令,并且您永远不必 "create" 具有更新属性的现有汽车版本。只需使用执行操作所需的信息创建命令即可。
marianoc84(对他+1)给你一个简单但有效的例子。
我有一个应用程序试图在一定程度上遵循领域驱动设计。我有一个域层,里面的 classes 有参数化的构造函数。
我的 ViewModels 当然有无参数的构造函数,以允许模型绑定。但是一页给我带来了问题。
我的一个页面显示了一个汽车列表,用户可以编辑其中的详细信息,然后通过JQuery POST 将一辆汽车的数据发送到后端。 Car 是一个域对象,只有一个带参数的构造函数(我在构造函数内部进行业务逻辑检查)。
我的后台代码是这样的
[AjaxOnly]
public JsonResult Update(Car car)
{
//...
}
当然这会失败,因为 Car 是一个域 class 并且没有无参数构造函数。
我想知道这种情况下是否有公认的最佳实践。我可以想到两个,可能是三个选项:
1) 为 Cars 域创建无参数构造函数 class。用
装饰它[Obsolete("For model binding only")]
防止用户直接调用。然后在我的 JsonResult 方法中立即调用参数化构造函数。不幸的是,这意味着在模型中将我的私有设置器更改为 public。
2) 接受 FormCollection,提取值,并调用参数化构造函数。这类似于 1) 但不需要更改私有设置器。
3) 也许是自定义模型活页夹?我已经为 IoC 为我的 MVC 控制器执行此操作,但不知道它如何用于非控制器。
是否有处理此问题的最佳实践方法?
你的描述有点贫血领域模型的味道。您的 Update
方法让我想到了 DDD 的 CRUD 方法。这是错误的。
您的 Car
域模型应该具有每种类型的可更新命令(例如 UpdatePrice
、UpdateAvailability
假设您正在开发管理限界上下文)。因此,您的表示层,换句话说,您的 ASP.NET 应用程序应该具有:
[AjaxOnly]
public JsonResult UpdateColor(UpdateColorViewModel vm)
{
Car car = repository.getById(vm.id);
try
car.UpdateColor(vm.color);
catch
// return some sort of errors
// return some sort of ok
}
如果您没有,严格来说,贫血领域模型,那么您的问题就是您的 UI。要应用 DDD,您需要 task-based UI design。没有好的 task-based UI 你就卡住了;身体上(你的建筑),更糟糕的是,精神上;在贫血模型中,因为您的系统不知道用户在做什么。
一旦您知道,在您的 UI 层中,用户在做什么;您可以提供从 UI 到域层操作的命令,并且您永远不必 "create" 具有更新属性的现有汽车版本。只需使用执行操作所需的信息创建命令即可。
marianoc84(对他+1)给你一个简单但有效的例子。