处理 OnResultExecuted 引发的错误

发布于 2024-11-17 05:13:58 字数 1373 浏览 0 评论 0原文

我已经实现了一个 ActionFilterAttribute 负责 NHibernate 事务管理。事务在 OnResultedExecuted 重写中提交,这偶尔会导致抛出异常。

我能够在控制器 OnException 覆盖中成功拦截这些异常,但是页面仍然会重定向,就好像事务成功一样。

我想要做的是返回导致错误的相同视图操作,并将异常消息添加到 ModelState 中。

我尝试了很多不同的方法,但似乎都不起作用..这是我最新的尝试:

[HttpPost]
[Transaction]
[HandleError]
public ActionResult Enroll(EnrollNewEmployeeCommand command)
{
    if(command.IsValid())
    {
        try
        {
            _commandProcessor.Process(command);
        }
        catch(Exception exception)
        {
            ModelState.AddModelError("", exception.Message);
            return View(command);
        }
        return this.RedirectToAction(x => x.Index());  // redirects to index even if an error occurs
    }
    return View(command);
}


protected override void OnException(ExceptionContext filterContext)
{
    //dont interfere if the exception is already handled
    if (filterContext.ExceptionHandled)
        return;

    ModelState.AddModelError("", filterContext.Exception.Message);

    filterContext.ExceptionHandled = true;

    // want to return original view with updated modelstate
    filterContext.Result = new ViewResult
    {
        ViewName = filterContext.RequestContext.RouteData.Values["action"].ToString(),
        ViewData = filterContext.Controller.ViewData
    };
}

I've implemented an ActionFilterAttribute responsible for NHibernate transaction management. Transactions are committed in the OnResultedExecuted override, which occasionally will result in an exception being thrown.

I'm able to successfully intercept these exceptions in the controllers OnException override, however the page still redirects as if the transaction were successful.

What I'd like to be able to do is return the same view action that caused the error with the exceptions message added to the ModelState.

I've tried a number of different things, none of which seem to work.. here's my latest attempt:

[HttpPost]
[Transaction]
[HandleError]
public ActionResult Enroll(EnrollNewEmployeeCommand command)
{
    if(command.IsValid())
    {
        try
        {
            _commandProcessor.Process(command);
        }
        catch(Exception exception)
        {
            ModelState.AddModelError("", exception.Message);
            return View(command);
        }
        return this.RedirectToAction(x => x.Index());  // redirects to index even if an error occurs
    }
    return View(command);
}


protected override void OnException(ExceptionContext filterContext)
{
    //dont interfere if the exception is already handled
    if (filterContext.ExceptionHandled)
        return;

    ModelState.AddModelError("", filterContext.Exception.Message);

    filterContext.ExceptionHandled = true;

    // want to return original view with updated modelstate
    filterContext.Result = new ViewResult
    {
        ViewName = filterContext.RequestContext.RouteData.Values["action"].ToString(),
        ViewData = filterContext.Controller.ViewData
    };
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

铁憨憨 2024-11-24 05:13:58

我想要做的是返回导致错误的相同视图操作,并将异常消息添加到 ModelState

您不能。 OnResultedExecuted 发生得太晚了。视图渲染已结束,您无法再修改此阶段将发送到客户端的内容。

如果您希望仍然能够修改返回给客户端的结果,那么您的最后机会是OnResultExecuting。所以你可以在那里提交你的交易。我想不会有那么严重的惩罚。

相反,我什至会在 OnActionExecuted 事件中提交事务,因为在这个阶段,您所拥有的应该是传递给视图进行渲染的完全初始化的视图模型。这就是您的事务边界应该结束的地方。视图呈现的过程应该排除在任何事务和数据库内容之外。它只是从视图模型渲染 HTML(或其他东西),简单明了。

What I'd like to be able to do is return the same view action that caused the error with the exceptions message added to the ModelState

You can't. OnResultedExecuted happens too late. The view rendering has ended and you can no longer modify what will be sent to the client at this stage.

Your last chance if you want to still be able to modify the returned result to the client is OnResultExecuting. So you could commit your transactions there. Wouldn't be so penalizing I guess.

At the contrary, I would even commit transactions in the OnActionExecuted event, as at this stage all you've got should be a fully initialized view models passed to the view for rendering. That's where your transaction boundaries should end. The process of rendering of the views should be excluded from any transactions and DB stuff. It's just HTML (or something) rendering from a view model, plain and simple.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文