设计模式重构和处理MVC控制器中的非例外错误

时间:2012-03-22 18:13:32

标签: asp.net-mvc design-patterns error-handling refactoring controller

在我的MVC3应用程序中,我有一个特定于每个控制器的“查询”类,它们在域实体之间执行转换并将它们转换为视图模型。我这样做是为了保持我的控制器清洁,并且更容易单独测试控制器和查询。

但是,有些情况下,查询方法需要将非异常错误消息传递给视图(例如,未找到实体)。但是,由于我的控制器只从查询方法接收ViewModel而不是任何类型的返回代码,我发现传递此错误的唯一两个选项如下:

  1. 从查询方法中抛出异常,并使用Try / Catch块捕获控制器中的异常。

  2. 向View Model添加一个名为“ErrorMessage”的属性,该属性由查询用于执行所需内容逻辑的查询方法填充。

  3. 因为这些不是例外情况,而且我知道我不应该使用Try / Catch来控制程序流程,所以我选择使用第二种方法。虽然现在这个有用,但由于以下原因,它对我来说感觉“肮脏”:

    • 当出现错误时,控制器必须接收整个View Model才能获得ErrorMessage属性。
    • 视图必须具有硬编码逻辑和两个部分才能显示错误或正常内容
    • 虽然我可以将if (Model.ErrorMessage != null)逻辑放在我的控制器中以确定要通过哪个视图,但它仍然不像是一个“干净”的解决方案。

    我是否可以使用任何可以帮助我重构此代码并使其更清晰的设计模式?

    示例视图模型:

    public class ApplicationViewModel
    {
      public string ErrorMessage { get; set; }
      public int Id { get; set; }
      public string Name { get; set; }
      // Other properties here...
    }
    

    示例控制器方法:

    public ActionResult Retrieve(Guid guid)
    {
      return View("Application", _applicationQueries.GetApplicationViewModel(guid));
    }
    

    示例ApplicationQueries方法:

    public ApplicationViewModel GetApplicationViewModel(Guid guid)
    {
      var applicationViewModel = new applicationViewModel();
    
      if (!_applicationServices.Exists(guid))
      {
        applicationViewModel.ErrorMessage = "The requested application does not exist.";
        return applicationViewModel;
      }
    
      // More code here that checks things which might set the ErrorMessage property...
    
      var application = _applicationServices.GetApplicationByGuid((Guid)guid);
      Mapper.Map(grantApplication, grantApplicationViewModel);
      return grantApplicationViewModel;
    }
    

    来自Application.cshtml的Snippit查看错误处理:

    @model MyApp.Web.Areas.Application.Models.ApplicationViewModel
    if (Model.ErrorMessage != null)
    {
      <div>@Model.ErrorMessage</div>
    }
    else
    {
      <!-- Display "normal" content here //>
    }
    

1 个答案:

答案 0 :(得分:2)

您可以将ModelState实例传递到queries图层,并注意添加错误:

public ApplicationViewModel GetApplicationViewModel(Guid guid, ModelStateDictionary modelState)
{
    var applicationViewModel = new applicationViewModel();
    if (!_applicationServices.Exists(guid))
    {
        modelState.AddModelError("", "The requested application does not exist.");
        return applicationViewModel;
    }

    // More code here that checks things which might set the ErrorMessage property...

    var application = _applicationServices.GetApplicationByGuid((Guid)guid);
    Mapper.Map(grantApplication, grantApplicationViewModel);
    return grantApplicationViewModel;
}

并在您看来:

@model MyApp.Web.Areas.Application.Models.ApplicationViewModel

@Html.ValidationSummary()

@if (ViewData.ModelState.IsValid)
{
    <!-- Display "normal" content here //>
}