0

现在,我有一个 ASP MVC Web 应用程序以及一个模型项目、一个服务项目、一个实用程序项目和一些用作一个或多个域模型的存储库的数据存储项目。我对每一层的分离感到非常满意,但我被困在从服务层返回到 Web 应用程序的内容上。

例如,当用户尝试注册时,控制器会收到一个 RegisterViewModel。各个部分(电子邮件、密码等)被发送到服务层,该服务层使用 guid、状态、createdate 等构造成员域对象,将其发送到存储库进行存储,最后返回成员对象以供 Web 应用程序重定向到/会员/{guid}。

但是,如果电子邮件已经存在,服务层应该如何通知 Web 应用程序呢?在更复杂的情况下,我可能必须检查多个域对象和业务规则的存在/有效性,因此必须一次性返回多个错误。此外,我不希望异常冒泡到 Web 层,因此服务层会捕获所有异常,但需要以某种方式通知 Web 层。

即使我找到了返回所有这些的方法,Web 层也会有负担处理所有这些并为用户提供各种反馈。控制器代码会很庞大并且错误修剪。演示文稿的服务结果是否有最佳实践?我应该消除单独的服务层并将代码放在控制器中吗?欢迎任何想法。

4

2 回答 2

0

首先,您需要确定是否为分发目的编写服务层。

如果您不打算将服务层分发到不同的进程/机器,

  1. 创建消息类
  2. 创建消息类数组并将其存储在 HttpContext.Items
  3. 现在将任何层中的任何新消息添加到该数组中
  4. 在视图/控制器中使用它

HttpContext.Items 在请求的整个生命周期内都可用,您可以一直使用它直到视图。

如果您使用 DI 框架,则可以通过使用每个生命周期对象的请求来实现相同的目的。

如果你想分发对象,从你的服务层抛出异常没有错。

于 2012-01-25T02:40:25.313 回答
0

我为此编写了操作模型库,它允许您编写如下代码:

public OperationResult Register(RegisterInput input) {

   var errors = new ErrorBuilder();

   if (errors.NotValid(input) // Invoke DataAnnotations validation
      || errors.Not(this.repo.FindUserByEmail(input.Email) == null, "Email '{0}' already exists.", () => input.Email))
      return errors;

   // Do stuff

   return HttpStatusCode.OK;
}

...并且在控制器中,错误消息被复制到 ModelState:

[HttpPost]
public ActionResult Register(RegisterInput input) {

   var result = this.service.Register(input);

   if (result.IsError)
      return View().WithErrors(result);

   // Do stuff
}

查看使用此模式编写的MvcAccount项目的源代码。

于 2012-01-25T07:02:55.267 回答