5

我想使用自定义操作过滤器来处理来自我的服务类的特定异常以填充模型状态,然后返回视图。

例如,以我之前的代码为例:

public ActionResult SomeAction(SomeViewModel model)
{
    try
    {
        _someService.SomeMethod(model);
    }
    catch (ServiceException ex)
    {
        ModelState.AddModelError(ex.Key, ex.ErrorMessage);
    }

    return View();
}

基本上,它会调用服务,如果抛出 ServiceException,它会知道模型数据存在问题,并将错误添加到 ModelState,然后返回视图。但我注意到了一些非常不像 DRY 的模式,因为我在每个操作方法中都有相同的 try/catch 代码。

因此,为了稍微干燥一下,我基本上创建了一个新的 HandleServiceError 操作过滤器:

public class HandleServiceErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext context)
    {
        ((Controller)context.Controller)
            .ModelState
            .AddModelError(
                ((ServiceException)context.Exception).Key, 
                ((ServiceException)context.Exception).ErrorMessage
            );
        context.ExceptionHandled = true;
    }
}

然后像这样简化了我的操作方法:

public ActionResult SomeAction(SomeViewModel model)
{
    _someService.SomeMethod(model);
    return View();
}

问题是,一旦动作过滤器处理了错误,它就不会返回到我的动作方法。我有点理解,在幕后,为什么会发生这种情况。但我仍然想找到一种方法来做我想做的事情。

这可能吗?

提前致谢。

更新:

我尝试了Darin在他的回答中提供的文章中的建议,但在尝试将构造函数注入与控制器的模型状态一起使用时遇到了问题。

例如,如果您查看他们的 Controllers\ProductController.cs 代码,他们有控制器的空构造函数,使用服务定位器创建服务,此时传入控制器的 ModelState:

public ProductController() 
{
    _service = new ProductService(new ModelStateWrapper(this.ModelState), 
                                  new ProductRepository());
}

但是如果你查看注入的构造函数,它假定 ModelState 将被注入到服务的构造函数中:

public ProductController(IProductService service)
{
    _service = service;
}

我不知道如何让 CI 与当前控制器的 ModelState 一起工作。如果我能弄清楚这一点,那么这种方法可能会奏效。

4

1 回答 1

0

您仍然可以返回相应的视图:

context.Result = new ViewResult
{
    ViewName = context.RouteData.GetRequiredString("action")
};

您还可以查看以下文章,了解有关如何在服务层执行验证的替代方法。

于 2011-03-28T06:14:50.187 回答