I am using PostSharp aspects for exception handling inside of Controller in ASP.NET MVC project. Simplified code is like this:
[ExceptionAspect(AspectPriority = 1)]
public ActionResult MarkeSettings()
{
try{
SaveData();
NotifyUser("success");
return RedirectToAction("A");
}
catch(Exception ex){
NotifyUser(ex.Message);
return RedirectToAction("B");
}
}
I have class ExceptionAspect
that inherits from OnExceptionAspect
class. In OnException(MethodExecutionArgs args)
method I set args.FlowBehavior = FlowBehavior.Continue;
.
So, how can I get rid of this try/catch
block and control the program execution flow and take an appropriate action for ReturnRedirectToAction()
? I read about Sharing state between advices , but couldn't figure out how to apply it on my problem.
When you apply ExceptionAspect
to your controller's method, it wraps the method with the try/catch
block and calls OnException(MethodExecutionArgs args)
from the introduced catch block.
This means that you can move your common exception handling code from the catch block to the OnException
method inside the aspect. I suppose that you want to redirect user to a specific action when exception happens. RedirectToAction
is a protected method of the controller that returns RedirectToRouteResult
. So you would need to construct and return a correct RedirectToRouteResult
instance in the OnException
method. To change the return value of the method set the args.ReturnValue
to the desired value, and args.FlowBehavior
to FlowBehavior.Return
.
Below is the example of the OnExceptionAspect
implementation:
[Serializable]
public class RedirectOnExceptionAttribute : OnExceptionAspect
{
public string ToAction { get; set; }
public override void OnException(MethodExecutionArgs args)
{
// NotifyUser(args.Exception.Message);
args.FlowBehavior = FlowBehavior.Return;
object controller = ((ControllerBase) args.Instance).ControllerContext.RouteData.Values["controller"];
args.ReturnValue = new RedirectToRouteResult(
new RouteValueDictionary
{
{"action", this.ToAction},
{"controller", controller}
});
}
}
Applying to controller method:
[RedirectOnException(ToAction = "B")]
public ActionResult MarkeSettings()
{
SaveData();
NotifyUser("success");
return RedirectToAction("A");
}