Custom Exception Filter in MVC

Custom Exception Filter in MVC Application

In this article, I am going to discuss how to create and use Custom Exception Filter in MVC Application. Please read our previous article before proceeding to this article where we discussed the Exception Filter i.e. the built-in exception filter attribute HandleError in details. We are also going to work with the same example that we created in our previous article.

As we already discussed in our previous article, we cannot do the following things using the built-in HandleErrorr attribute

  1. We cannot log the Exception using the HandleError attribute.
  2. It is not possible to handle the exceptions raised outside the controllers.
  3. Exception Handling is not possible Based on Scenario.

Let us see how to overcome the above problems by creating a Custom Exception Filter. Here in this article, I will show you how to log the exception in a text file but if you want then you can log the exception in the database too. Here our focus is on how to create the custom exception filter not how to log the exception.

Adding Log Folder:

Add a folder with the name Log into the project’s root directory. In this folder, we are going to log all the exceptions raised in our application using a text (i.e. Log.txt) file.

Creating Custom Exception Filter in MVC:

Here we need to create a class file by implementing the IExceptionFilter interface. So let’s have a look at the definition of IExceptionFilter interface as shown below.

Creating Custom Exception Filter in MVC

As you can see this interface belongs to System.Web.Mvc namespace and having only a single method declaration. The Custom Exception class that we are going to create is going to implement the above OnException method only.

So, create a class file with the name LogCustomExceptionFilter.cs within the Models folder and then copy and paste the following code in it.

using System;
using System.IO;
using System.Web;
using System.Web.Mvc;

namespace ExceptionFilterInMVC.Models
{
    public class LogCustomExceptionFilter : FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)
            {
                var exceptionMessage = filterContext.Exception.Message;
                var stackTrace = filterContext.Exception.StackTrace;
                var controllerName = filterContext.RouteData.Values["controller"].ToString();
                var actionName = filterContext.RouteData.Values["action"].ToString();
                
                string Message = "Date :" + DateTime.Now.ToString() + ", Controller: " + controllerName + ", Action:" + actionName +
                                 "Error Message : " + exceptionMessage
                                + Environment.NewLine + "Stack Trace : " + stackTrace;

                //saving the data in a text file called Log.txt
                //You can also save this in a dabase
                File.AppendAllText(HttpContext.Current.Server.MapPath("~/Log/Log.txt"), Message);
                
                filterContext.ExceptionHandled = true;
                filterContext.Result = new ViewResult()
                {
                    ViewName = "Error"
                };
            }
        }
    }
}

As you can see, the above class is derived from the FilterAttribute class. This is required we want to use this class as like a Filter attribute. The class implementing the IExceptionFilter interface and its OnException() method. This method contains the logic for storing the exception information in a text (i.e. .txt) file.

Registering the Custom Exception Filter in MVC:

As a filter, you can use it at three different levels i.e. at the action level, at the Controller level and globally. Let’s register this filter globally so that it will be applicable for all the action methods of all controllers of our application. To register it globally, open the FilterConfig class which is present in the App_Start folder and then modify the class as shown below. If the FilterConfig class is not already present there then just create a class file with the name FilterConfig.cs within the App_Start folder.

FilterConfig.cs

using System.Web.Mvc;
using ExceptionFilterInMVC.Models;
namespace ExceptionFilterInMVC.App_Start
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new LogCustomExceptionFilter());
        }
    }
}

Note: While creating the project, if you have selected the Empty MVC Template then the above class (i.e. FilterConfig) will not present with you, but if you have selected any readymade MVC template then the above class will be available with your application. If this class file is not present then just create a class file with the name FilterConfig within the App_Start folder. This FilterConfig class is the centralized place where we used to add the Filters globally for our application. This will be instantiated when the Web application starts.

Modifying the Global.asax

As we know, the Application_Start() method of Global.asax file is the first method that is going to be executed when the application starts. So, from here we need to call the RegisterGlobalFilters() method of FilterConfig class so that all our filters which are registered globally will be instantiated at the time of application startup. So modify the Application_Start() method of the Global.asax file as shown below.

using System.Web.Mvc;
using System.Web.Routing;
using ExceptionFilterInMVC.App_Start;
namespace ExceptionFilterInMVC
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            //calling RegisterGlobalFilters to register filters globally
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        }
    }
}
Modifying the Error.cshtml view:

Open the Error.cshtml file which is present inside the Shared folder which is inside the views folder. If Error.cshtml file is not present then just create it. Once you open the Error.cshtml file then copy and paste the following code in it.

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Error</title>
</head>
<body>
    <hgroup>
        <h1>Unknwo Error</h1>
        <h2>An unknown error has occurred. We are working on it. Please try after some time</h2>
    </hgroup>
</body>
</html>
Modifying the HomeController:

Please modify the Home Controller as shown below to throw different types of exception from different action methods.

using System;
using System.Web.Mvc;
using ExceptionFilterInMVC.Models;

namespace ExceptionFilterInMVC.Controllers
{
    [LogCustomExceptionFilter]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            throw new Exception("Something went wrong");
        }
        public ActionResult About()
        {
            throw new NullReferenceException();
        }
        public ActionResult Contact()
        {
            throw new DivideByZeroException();
        }
    }
}

That’s it. We are done with our implementation. Now, run the application and try to execute all the action methods and then check the Log.txt file which should be created inside the Log folder. In the next article, I will discuss how to display different error pages based on the different status code in ASP.NET MVC application.

SUMMARY

In this article, I try to explain how to create and register Custom Exception Filter in MVC application step by step with a simple logging example. I hope you understood how to create and use the Custom Exception Filter in ASP.NET MVC application. 

Leave a Reply

Your email address will not be published. Required fields are marked *