处理 OnResultExecuted 引发的错误
我已经实现了一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不能。
OnResultedExecuted
发生得太晚了。视图渲染已结束,您无法再修改此阶段将发送到客户端的内容。如果您希望仍然能够修改返回给客户端的结果,那么您的最后机会是
OnResultExecuting
。所以你可以在那里提交你的交易。我想不会有那么严重的惩罚。相反,我什至会在
OnActionExecuted
事件中提交事务,因为在这个阶段,您所拥有的应该是传递给视图进行渲染的完全初始化的视图模型。这就是您的事务边界应该结束的地方。视图呈现的过程应该排除在任何事务和数据库内容之外。它只是从视图模型渲染 HTML(或其他东西),简单明了。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.