在阅读有关使用服务层进行验证的this文章后,我有些疑惑。
第一:如文章所示,将整个模型视图传递给服务是否可以?我已经看到一些例子,而不是传递控制器使用的整个模型(如bool success = _productService.CreateProduct(productModel)
),他们称这样的服务:
bool success = _productService.CreateProduct(productModel.Name, productModel.Category, productModel.Cost)
两种方法的优点/缺点是什么?
第二:我可以看到使用相同服务验证模型和完成实际工作的逻辑。另一方面,这意味着该服务必须处理两个问题:数据验证和数据处理。这意味着同一服务中的代码更多,可测试性更差,对吧?
因此,不是上面的示例代码,最好是:
bool valid = _productValidationService(productModel);
if(valid){
_productService.CreateProduct(productModel);
//or maybe _productService.CreateProduct(productModel.Name, productModel.Category, productModel.Cost);
}
有哪些优点/缺点?有没有我看不到的东西?你用什么 ?什么是标准方法?
答案 0 :(得分:1)
我更喜欢将整个模型传递给服务而不是单个属性,以避免使方法混乱。就验证逻辑而言,你说它必须处理两个问题:业务逻辑验证和实际保存。我认为这两个问题属于该服务。此服务的使用者不应该只能在不首先验证的情况下调用save,并且在服务中执行这两项操作可确保不会发生这种情况。此外,实际保存可以由服务方法委派给一个或多个CRUD存储库调用。
所以在控制器中:
string error;
if (!_productService.TryCreateProduct(productModel, out error))
{
ModelState.AddModelError("key", error);
return View(viewModel);
}
在您链接的文章中,以下方法用于初始化服务并将其传递给模型状态,以便直接写入错误:
_productService = new ProductService(
_productRepository,
new ModelStateValidationWrapper(this.ModelState)
);
以后你可以直接:
_productService.CreateProduct(productModel);
这也是一种有效且好的方法。唯一的问题是控制器内部的以下行_productService = new ProductService(...
非常糟糕,因为它将控制器与服务的特定实现紧密耦合。该服务应该由DI框架注入,但问题是传递ModelState,因为它会创建循环依赖。这里有some threads来解决这个问题。