MegaMatt
MegaMatt

Reputation: 23763

How can I apply an attribute that is already a global filter to a method without it running twice?

I have extended HandleErrorAttribute in MVC by creating my own attribute that handles exceptions raised during Ajax requests. That attribute is here:

public class AjaxAwareHandleErrorAttribute : HandleErrorAttribute
{
    public string PartialViewName { get; set; }

    public override void OnException(ExceptionContext filterContext)
    {
        ExceptionHelper.HandleException(filterContext.Exception, false); // custom static class and method
        base.OnException(filterContext);

        // Use partial view in case of AJAX request
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            var result = new PartialViewResult {ViewName = PartialViewName ?? "~/Views/Errors/DefaultAjaxError.cshtml"};
            filterContext.Result = result;
        }
    }
}

As you can see, there is default behavior in the case when PartialViewName is null. This is because I have it registered as a global filter in my Global.asax file:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new AjaxAwareHandleErrorAttribute());
}

So the way this is set up, I have default behavior when an exception is raised during an Ajax call, namely that DefaultAjaxError.cshtml will be returned. In cases where I want a custom message, I create a view and pass it as PartialViewName to an attribute directly on the action, like this:

[AjaxAwareHandleError(PartialViewName = "~/Views/Errors/CustomAjaxError.cshtml")]
public ActionResult SomeAjaxControllerAction()

The problem in cases where I have a controller decorated with the controller action is that the code in the AjaxAwareHandleErrorAttribute class is running twice, presumably because it's registered globally and because it's on the method as well. Is there a way I can prevent it from running twice?

Thanks.

Upvotes: 1

Views: 102

Answers (1)

SLaks
SLaks

Reputation: 887453

Set the filterContext.ExceptionHandled property to true.

Then, at the top of your override, check whether that property is true and return immediately.

Upvotes: 0

Related Questions