TechNo
TechNo

Reputation: 675

How to use Exception filters in MVC 5

How i can implement Exception Filters in MVC5.

I want to throw the exception to NLog and redirect the page to a default error page which displays "Something is gone wrong"

I have a Filter class as follows

using System;
using System.Diagnostics;
using System.Security.Policy;
using System.Web.Mvc;
using System.Web.Mvc.Filters;
using System.Web.Routing;
using System.Web.UI.WebControls;
using Delivros.UI.Controllers;
using Delivros.UI.Areas.User.ViewModel;
using System.Web;

namespace Delivros.UI.Filters
{

public class CustomAuthenticationFilter : IAuthenticationFilter
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {

    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        Debug.WriteLine("OnAuthenticationChallenge : MyAuthenticationFilter");
    }
}
 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyAuthorizationFilter : AuthorizeAttribute
{
     public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.Cookies[System.Configuration.ConfigurationManager.AppSettings[Convert.ToString(CookieField.cookieName)]] == null)
        {

        }
        else
{
            filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary 
    {
                { "controller", "User" }, 
                { "action", "UserRegistration" } ,
                {"Area","User"}
            });

        }
    }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();
        base.OnResultExecuted(filterContext);
        filterContext.Result = new RedirectToRouteResult(
              new RouteValueDictionary 
            { 
                { "controller", "User" }, 
                { "action", "UserRegistration" } ,
                {"Area","User"}
            });
        // ActionResult home = new HomeController().Index();           
    }
}

public class MyResultFilter : IResultFilter
{
    public void OnResultExecuting(ResultExecutingContext filterContext)
    {

    }

    public void OnResultExecuted(ResultExecutedContext filterContext)
    {

    }
}

public class MyExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        filterContext.Result = new RedirectToRouteResult(
              new RouteValueDictionary 
            { 
                { "controller", "User" }, 
                { "action", "UserLogOut" } ,
                {"Area","User"}
            });

    }
}

}

But nothing is redirecting to the page...

Upvotes: 13

Views: 27281

Answers (4)

Squibly
Squibly

Reputation: 446

Below worked for me. A few things to note 1) RedirectResult points to a controller action, not a view 2) you need to set filterContext.ExceptionHandled = true; or your exception view / page will not display.

public class ErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        Log.Logger.Error(filterContext.Exception, "An Unhandled exeption occured durring the execution of a request");

        filterContext.Result = new RedirectResult("~/MyControler/MyErrorAction");
        filterContext.ExceptionHandled = true;
    }

}

Ofcourse you will also need to register the Error attribute using the GlobalFilters object from your Global.asax as shown below.

 protected void Application_Start()
 {
     GlobalFilters.Filters.Add(new ErrorAttribute());           
     ...
 }

Upvotes: 0

A. Nadjar
A. Nadjar

Reputation: 2543

Exception filters are run only when unhandled exception has been thrown inside an action method. As you asked, here is an example to redirect to another page upon exception:

public class MyExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if(!filterContext.ExceptionHandled)
        {
            filterContext.Result = new RedirectResult("~/Content/ErrorPage.html");
            filterContext.ExceptionHandled = true;
        }    
    }
}

Now, to apply this filter to either controllers or individual actions, put [MyException] on them.

You may need to check the occurence of an specific Exception inside the if clause. e.g.:

if(... && filterContext.Excaption is ArgumentOutOfRangeException)

To return a View as Exception Response:

filterContext.Result = new RedirectResult("/Home/ErrorAction");

other alternatives you might use to redirect are:

  • new RedirectToRouteResult{ ... }
  • new ViewResult{ ... }

Upvotes: 0

MerrickSoft
MerrickSoft

Reputation: 31

I believe it should be this code:

public class MyExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { 
            action = "UserLogOut", 
            controller = "User", 
            area = "User" 
        }));

    }

}

You may add an additional "if (!filterContext.ExceptionHandled)" statement before logging the values inside the result to make sure that the exception's unhandled for the moment.

Upvotes: 1

James
James

Reputation: 82136

You could derive your own HandleErrorAttribute

public class NLogExceptionHandlerAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        // log error to NLog
        base.OnException(filterContext);
    }
}

Then register it globally

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

By default, the HandleErrorAttribute will display the Error view located in the ~/Views/Shared folder but if you wanted to display a specific view you can set the View property of the attribute.

Upvotes: 21

Related Questions