如何将HandleError与模型状态错误一起使用

时间:2011-03-28 03:58:59

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

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

例如,请使用我之前的代码:

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一起使用。如果我能弄清楚这一点,那么这种方法可能会奏效。

1 个答案:

答案 0 :(得分:0)

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

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

您还可以查看following article,了解如何在服务层执行验证。