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
};
}
You can’t.
OnResultedExecutedhappens 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
OnActionExecutedevent, 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.