【问题标题】:How to use HandleError with model state errors如何将 HandleError 与模型状态错误一起使用
【发布时间】:2011-07-24 04:41:25
【问题描述】:

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

以我之前的代码为例:

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();
}

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

这可能吗?

提前致谢。

更新:

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

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

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

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

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

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

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-2 asp.net-mvc-3 exception-handling action-filter


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢。我尝试按照那篇文章使用 ModelStateWrapper 的路径,结果发现 Unity IoC 很痛苦。我不知道如何将我的 Controller.ModelState 注入我的服务层。如果我从构造函数注入转到服务定位器,我也许可以做到这一点,但我不想仅仅为此而切换到服务定位器。我已经看过了,但我没有找到任何优雅的解决方案(其中大多数似乎被黑客入侵或过于复杂)。
    • 我已经更新了我的帖子,包含更多关于此的信息。很好奇是否有办法使用构造函数注入使其工作。
    • 文章的方法要求您手动检查每个服务方法的真实性,并且没有给出任何具体的错误信息,只是“通过或失败”。此外,如果您在一个操作中调用多个服务,或者如果一个服务调用另一个服务,您必须在堆栈中一直检查真实性。 Jerad 的原始方法虽然需要 try catch,但在 IMO 上更加优雅。
    猜你喜欢
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 2015-04-19
    • 2011-01-04
    • 2023-03-17
    • 1970-01-01
    相关资源
    最近更新 更多