Serving Industries Worldwide

Innovative Ways - Satisfied Clientele

What is Exception Filter and explain custom Exception Filter in ASP.NET MVC?


Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

 
 

What_is_Exception_Filter_and_explain_custom_Exception_Filterin_ASP.NET_MVC.webp

Table of Content

What is an Exception Filter?

Exception Filter provides an ability to handle the exception for all the method, controller classes in one place. Exception filters execute when some of the exceptions are thrown from an action. The exception can be anything. This is by creating a class that inherits from IExceptionFilter and FileAttribute interface.

Custom Exception Filter

Exception Filter provides a built-in HandleError attribute to handle exception filter with the built-in attribute we can’t do the following things.

  1. Cannot log the Exception using the HandleError attribute
  2. It is not possible to handle exception occurs outside the controllers.
  3. Exception handling is not possible, depending on the scenario. For Example, one error page when the request comes through AJAX and a different one is a normal request.

Let's look at how to work around these problems by creating a custom exception filter.

Creating Custom Exception Filter

Here I am creating an Employee class for the model inside the model folder.

Employee. class
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LIBData
{
   public class Employee  
    {  
        public int Id { 
get; 
set;
 }  
   
        [Required(ErrorMessage = "Name Required")]  
        public string Name { 
get; 
set;
 }  

        [Required(ErrorMessage = " Designation Required ")]  
        public string Designation{ 
get; 
set;
 }  

        [Required(ErrorMessage = "Salary Required ")]  
        public int Salary { 
get; 
set;
 }  
    }  
}

Now we need to add controller class inside the controller folder add.

EmployeeController
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using LIBUser.CustomFilter;  
using LIBUser.Models;  
   
namespace LIBUser.Controllers
{
    public class EmployeeController: Controller
    {
        public EmployeeContext  db =  new EmployeeContext();

        public ActionResult Index()
        {
            var employee = db .Employees.ToList();
            return View(employee);
        }

        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [CustomExceptionHandlerFilter]
        public ActionResult Create(Employee employee)
        {
            if (ModelState.IsValid)
            {
                if (employee.Designation== "JuniorForntEndDeveloper" && (employee.Salary < 1000 || employee.Salary > 4000))
                {
                    throw new Exception("Salary is not matching with JuniorForntEndDeveloper.");
                }
                else if (employee.Designation== "WebDeveloper" && (employee.Salary < 30000 || employee.Salary > 40000))
                {
                    throw new Exception("Salary is not matching with WebDeveloper.");
                }
                else if (employee.Designation== "Marketing Manager")
                {
                    throw new Exception("Salary is not matching with Marketing Manager");
                }
                else
                {
                    db .Employees.Add(employee);
                    db .SaveChanges();
                }
            }
            return RedirectToAction("Index");
        }
    }
}


   

Add the following line of code inside the Employee controller.

In this example, I will just demonstrate how to use a Custom Exception filter you can change your controller as per the requirements.

Now, we need to add the view for Create action method and Index action method. Right-click on create method and add view.

Create View

@model LIBData.Employee

@{
    ViewBag.Title = &quot;Create&quot;;
    Layout = &quot;~/Views/Shared/LibStudent.cshtml&quot;;
}<div class="container"><div class="card"><div class="card-header bg-dark">
            <strong class="card-title" style="color : white;"> Add Employee Details</strong></div>
<div class="card-body">

            @using (Html.BeginForm())
            {
                @Html.AntiForgeryToken()<div class="form-horizontal"><h4>Employee</h4>
<hr />
                    @Html.ValidationSummary(true, &quot;&quot;, new { @class = &quot;text-danger&quot; })<div class="form-group">
                        @Html.LabelFor(model =&gt; model.Name, htmlAttributes: new { @class = &quot;control-label col-md-2&quot; })
                        @Html.EditorFor(model =&gt; model.Name, new { htmlAttributes = new { @class = &quot;form-control&quot; } })
                        @Html.ValidationMessageFor(model =&gt; model.Name, &quot;&quot;, new { @class = &quot;text-danger&quot; })</div>
<div class="form-group">
                        @Html.LabelFor(model =&gt; model.Designation, htmlAttributes: new { @class = &quot;control-label col-md-2&quot; })
                        @Html.EditorFor(model =&gt; model.Designation, new { htmlAttributes = new { @class = &quot;form-control&quot; } })
                        @Html.ValidationMessageFor(model =&gt; model.Designation, &quot;&quot;, new { @class = &quot;text-danger&quot; })</div>
<div class="form-group">
                        @Html.LabelFor(model =&gt; model.Salary, htmlAttributes: new { @class = &quot;control-label col-md-2&quot; })
                        @Html.EditorFor(model =&gt; model.Salary, new { htmlAttributes = new { @class = &quot;form-control&quot; } })
                        @Html.ValidationMessageFor(model =&gt; model.Salary, &quot;&quot;, new { @class = &quot;text-danger&quot; })</div>
<div class="form-group"><div class="col-md-offset-2 col-md-10">
                            <input class="btn btn-default" type="submit" value="Create" /></div></div></div>
            }</div></div></div>
<div>
    @Html.ActionLink(&quot;Back to List&quot;, &quot;Index&quot;)</div>


Add the CustomExceptionHandlerFilter class for creating a custom exception handler.

Implements FilterAttribute and IExceptionFilter and overrides the OnException method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace LIBUser.Controllers
{
    public class CustomExceptionHandlerFilter: FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            ExceptionLogger logger = new ExceptionLogger()
            {
                ExceptionMessage = filterContext.Exception.Message,
                ExceptionStackTrack = filterContext.Exception.StackTrace,
                ControllerName = filterContext.RouteData.Values["controller"].ToString(),
                ActionName = filterContext.RouteData.Values["action"].ToString(),
                ExceptionLogTime = DateTime.Now
            };
            EmployeeContext dbContext = new EmployeeContext();
            dbContext.ExceptionLoggers.Add(logger);
            dbContext.SaveChanges();

            filterContext.ExceptionHandled = true;
            filterContext.Result = new ViewResult()
            {
                ViewName = "Error"
            };
        }
    }
}

Open App_Start folder inside the App_start folder contains FilterConfig class. Inside this class, we add our new CustomExceptionHandlerFilter in the following way.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using Microsoft.ApplicationInsights.DataContracts;  
using MvcCustomExceptionFilter.CustomFilter;  
   
namespace LIBUser.App_Start
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilter(GlobalFilterCollection filters)
        {
            filters.Add(new CustomExceptionHandlerFilter());
        }
    }
}

When you create a project, if you have selected the Empty MVC Template then the FilterConfig class will not be available to you, but if you have selected any ready-mate MVC template then the FilterConfig class will be available within your application. If this file is not available, then just simply create a class file with the name FilterConfig inside the App_Start folder. This FilterConfig class is the place where we used to add the Filters globally for our application. It file will be instantiated when our Web application starts.

 

Looking for Trusted ASP.Net Development Company ?

Your Search ends here.

 

Now Register our CustomExceptionHandlerFilter in the Global. asax

Global.aspx
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using System.Web.Routing;  
using MvcCustomExceptionFilter.App_Start;  
   
namespace MvcCustomExceptionFilter
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            FilterConfig.RegisterGlobalFilter(GlobalFilters.Filters);
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

Inside the shared folder of view, it contains the Error. cshtml page modifies the Error. cshtml as per your requirement. If the shared folder does not contain an Error. cshtml you can add a view inside the shared folder and place this code inside the error page.


@{
    ViewBag.Title = &quot;Error&quot;;
}<h1>Error Occured</h1>
<h1 class="alert alert-danger">An unknown error occurred while processing your request.</h1>


Open the web. config file and add the custom error mode inside the system. web




Now run the application and add the details inside the create view.

AddEmployeeDetails

[Fig:- Add Employee Details]
 

If we can add the salary that is not range to a specific position it will give an error and we will redirect to the Error page instead of yellow screen or exception. Here I insert salary for JuniorForntEndDeveloper 10000 it will get me an error because in code set salary for JuniorForntEndDeveloper between 1000 to 4000.

Exception

[Fig:-Exception]
 

After click on create button, it gives an Error and redirects to the error page.

Conclusion

Exception filter provides the built-in HandleError attribute but we cannot handle the log error and exceptions that occurs inside the controller class, however, with the help of the custom exception we can handle the errors that occur inside the controller class.

What is Exception Filter and explain custom Exception Filter in ASP.NET MVC?

What_is_Exception_Filter_and_explain_custom_Exception_Filterin_ASP.NET_MVC.webp

Table of Content

What is an Exception Filter?

Exception Filter provides an ability to handle the exception for all the method, controller classes in one place. Exception filters execute when some of the exceptions are thrown from an action. The exception can be anything. This is by creating a class that inherits from IExceptionFilter and FileAttribute interface.

Custom Exception Filter

Exception Filter provides a built-in HandleError attribute to handle exception filter with the built-in attribute we can’t do the following things.

  1. Cannot log the Exception using the HandleError attribute
  2. It is not possible to handle exception occurs outside the controllers.
  3. Exception handling is not possible, depending on the scenario. For Example, one error page when the request comes through AJAX and a different one is a normal request.

Let's look at how to work around these problems by creating a custom exception filter.

Creating Custom Exception Filter

Here I am creating an Employee class for the model inside the model folder.

Employee. class
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace LIBData
{
   public class Employee  
    {  
        public int Id { 
get; 
set;
 }  
   
        [Required(ErrorMessage = "Name Required")]  
        public string Name { 
get; 
set;
 }  

        [Required(ErrorMessage = " Designation Required ")]  
        public string Designation{ 
get; 
set;
 }  

        [Required(ErrorMessage = "Salary Required ")]  
        public int Salary { 
get; 
set;
 }  
    }  
}

Now we need to add controller class inside the controller folder add.

EmployeeController
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using LIBUser.CustomFilter;  
using LIBUser.Models;  
   
namespace LIBUser.Controllers
{
    public class EmployeeController: Controller
    {
        public EmployeeContext  db =  new EmployeeContext();

        public ActionResult Index()
        {
            var employee = db .Employees.ToList();
            return View(employee);
        }

        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Employee employee = db.Employees.Find(id);
            if (employee == null)
            {
                return HttpNotFound();
            }
            return View(employee);
        }

        public ActionResult Create()
        {
            return View();
        }

        [HttpPost]
        [CustomExceptionHandlerFilter]
        public ActionResult Create(Employee employee)
        {
            if (ModelState.IsValid)
            {
                if (employee.Designation== "JuniorForntEndDeveloper" && (employee.Salary < 1000 || employee.Salary > 4000))
                {
                    throw new Exception("Salary is not matching with JuniorForntEndDeveloper.");
                }
                else if (employee.Designation== "WebDeveloper" && (employee.Salary < 30000 || employee.Salary > 40000))
                {
                    throw new Exception("Salary is not matching with WebDeveloper.");
                }
                else if (employee.Designation== "Marketing Manager")
                {
                    throw new Exception("Salary is not matching with Marketing Manager");
                }
                else
                {
                    db .Employees.Add(employee);
                    db .SaveChanges();
                }
            }
            return RedirectToAction("Index");
        }
    }
}


   

Add the following line of code inside the Employee controller.

In this example, I will just demonstrate how to use a Custom Exception filter you can change your controller as per the requirements.

Now, we need to add the view for Create action method and Index action method. Right-click on create method and add view.

Create View

@model LIBData.Employee

@{
    ViewBag.Title = &quot;Create&quot;;
    Layout = &quot;~/Views/Shared/LibStudent.cshtml&quot;;
}<div class="container"><div class="card"><div class="card-header bg-dark">
            <strong class="card-title" style="color : white;"> Add Employee Details</strong></div>
<div class="card-body">

            @using (Html.BeginForm())
            {
                @Html.AntiForgeryToken()<div class="form-horizontal"><h4>Employee</h4>
<hr />
                    @Html.ValidationSummary(true, &quot;&quot;, new { @class = &quot;text-danger&quot; })<div class="form-group">
                        @Html.LabelFor(model =&gt; model.Name, htmlAttributes: new { @class = &quot;control-label col-md-2&quot; })
                        @Html.EditorFor(model =&gt; model.Name, new { htmlAttributes = new { @class = &quot;form-control&quot; } })
                        @Html.ValidationMessageFor(model =&gt; model.Name, &quot;&quot;, new { @class = &quot;text-danger&quot; })</div>
<div class="form-group">
                        @Html.LabelFor(model =&gt; model.Designation, htmlAttributes: new { @class = &quot;control-label col-md-2&quot; })
                        @Html.EditorFor(model =&gt; model.Designation, new { htmlAttributes = new { @class = &quot;form-control&quot; } })
                        @Html.ValidationMessageFor(model =&gt; model.Designation, &quot;&quot;, new { @class = &quot;text-danger&quot; })</div>
<div class="form-group">
                        @Html.LabelFor(model =&gt; model.Salary, htmlAttributes: new { @class = &quot;control-label col-md-2&quot; })
                        @Html.EditorFor(model =&gt; model.Salary, new { htmlAttributes = new { @class = &quot;form-control&quot; } })
                        @Html.ValidationMessageFor(model =&gt; model.Salary, &quot;&quot;, new { @class = &quot;text-danger&quot; })</div>
<div class="form-group"><div class="col-md-offset-2 col-md-10">
                            <input class="btn btn-default" type="submit" value="Create" /></div></div></div>
            }</div></div></div>
<div>
    @Html.ActionLink(&quot;Back to List&quot;, &quot;Index&quot;)</div>


Add the CustomExceptionHandlerFilter class for creating a custom exception handler.

Implements FilterAttribute and IExceptionFilter and overrides the OnException method.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace LIBUser.Controllers
{
    public class CustomExceptionHandlerFilter: FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            ExceptionLogger logger = new ExceptionLogger()
            {
                ExceptionMessage = filterContext.Exception.Message,
                ExceptionStackTrack = filterContext.Exception.StackTrace,
                ControllerName = filterContext.RouteData.Values["controller"].ToString(),
                ActionName = filterContext.RouteData.Values["action"].ToString(),
                ExceptionLogTime = DateTime.Now
            };
            EmployeeContext dbContext = new EmployeeContext();
            dbContext.ExceptionLoggers.Add(logger);
            dbContext.SaveChanges();

            filterContext.ExceptionHandled = true;
            filterContext.Result = new ViewResult()
            {
                ViewName = "Error"
            };
        }
    }
}

Open App_Start folder inside the App_start folder contains FilterConfig class. Inside this class, we add our new CustomExceptionHandlerFilter in the following way.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using Microsoft.ApplicationInsights.DataContracts;  
using MvcCustomExceptionFilter.CustomFilter;  
   
namespace LIBUser.App_Start
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilter(GlobalFilterCollection filters)
        {
            filters.Add(new CustomExceptionHandlerFilter());
        }
    }
}

When you create a project, if you have selected the Empty MVC Template then the FilterConfig class will not be available to you, but if you have selected any ready-mate MVC template then the FilterConfig class will be available within your application. If this file is not available, then just simply create a class file with the name FilterConfig inside the App_Start folder. This FilterConfig class is the place where we used to add the Filters globally for our application. It file will be instantiated when our Web application starts.

 

Looking for Trusted ASP.Net Development Company ?

Your Search ends here.

 

Now Register our CustomExceptionHandlerFilter in the Global. asax

Global.aspx
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using System.Web.Routing;  
using MvcCustomExceptionFilter.App_Start;  
   
namespace MvcCustomExceptionFilter
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            FilterConfig.RegisterGlobalFilter(GlobalFilters.Filters);
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

Inside the shared folder of view, it contains the Error. cshtml page modifies the Error. cshtml as per your requirement. If the shared folder does not contain an Error. cshtml you can add a view inside the shared folder and place this code inside the error page.


@{
    ViewBag.Title = &quot;Error&quot;;
}<h1>Error Occured</h1>
<h1 class="alert alert-danger">An unknown error occurred while processing your request.</h1>


Open the web. config file and add the custom error mode inside the system. web




Now run the application and add the details inside the create view.

AddEmployeeDetails

[Fig:- Add Employee Details]
 

If we can add the salary that is not range to a specific position it will give an error and we will redirect to the Error page instead of yellow screen or exception. Here I insert salary for JuniorForntEndDeveloper 10000 it will get me an error because in code set salary for JuniorForntEndDeveloper between 1000 to 4000.

Exception

[Fig:-Exception]
 

After click on create button, it gives an Error and redirects to the error page.

Conclusion

Exception filter provides the built-in HandleError attribute but we cannot handle the log error and exceptions that occurs inside the controller class, however, with the help of the custom exception we can handle the errors that occur inside the controller class.