Monday 5 September 2022

Global Exception Handler in c# .Net Core

 Default exception will handled by ExceptionFilter, incase we need to override this then we can derived from IExceptionFilter and we can customize it.

Predefined interface for Exception filter is below


///predefine interface for exception is below
namespace Microsoft.AspNetCore.Mvc.Filters
{
    //
    // Summary:
    //     A filter that runs after an action has thrown an System.Exception.
    public interface IExceptionFilter : IFilterMetadata
    {
        //
        // Summary:
        //     Called after an action has thrown an System.Exception.
        //
        // Parameters:
        //   context:
        //     The Microsoft.AspNetCore.Mvc.Filters.ExceptionContext.
        void OnException(ExceptionContext context);
    }
}


Let us create a class and inherit from IExceptionFilter file name like GlobalExceptionFilter.cs

Above interface contains  OnException  method so when we derived from tat interface we need to provide definition.



using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Net;
namespace GlobalException
{
public class GlobalExceptionFilter : IExceptionFilter
{

    /// <summary>
    /// Global method to log the Exception thismethod will hit when exception happen
    /// </summary>
    /// <param name="context"></param>
    public void OnException(ExceptionContext context)
    {
        if (context != null)
        {
            /// Find the response status code if it's null then send InternalServerError
            HttpStatusCode statusCode = (context.Exception as WebException != null &&
                        ((HttpWebResponse)(context.Exception as WebException).Response) != null) ?
                        ((HttpWebResponse)(context.Exception as WebException).Response).StatusCode
                        : HttpStatusCode.InternalServerError;

            context.ExceptionHandled = true;
            HttpResponse response = context.HttpContext.Response;
            response.StatusCode = (int)statusCode;
            response.ContentType = "application/json";
            /// use own logger to store exception like below
            //logger.Error(context.Exception);


        }
    }            
}
}

Now we need create Startup.cs class and map in program.cs file like below.

 public class Program
    {
        protected Program()
        {

        }
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }

we mentioned above like all configuration based on Startup class.

Now startup class we need add like below.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NLog;
using NLog.Extensions.Logging;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Mvc.NewtonsoftJson;
using System;

namespace GlobalExceptionSample.API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            var config = new ConfigurationBuilder()
          .SetBasePath(System.IO.Directory.GetCurrentDirectory())
          .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();

            LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));

            Configuration = configuration;
           
        }

        public static IConfiguration Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            ///any default implementation we can include as AddSingleton like below
            ///services.AddSingleton<ILog, Log>();
            /*----Here we are adding Global Exception filter as GlobalExceptionFilter*/
            services.AddMvc(config => {
                            config.Filters.Add(typeof(GlobalExceptionFilter));
                         });

            services.AddControllers()
                    .AddNewtonsoftJson(options =>
                    {
                        options.SerializerSettings.ContractResolver = new DefaultContractResolver();
                    });

            services.AddCors();
            services.AddAuthentication(IISDefaults.AuthenticationScheme);
           
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseAuthentication();
            app.UseRouting();
            app.UseCors(
              options => options.SetIsOriginAllowed(x => _ = true)
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials());
            app.UseAuthorization();
           
        }
    }
}

so in startup class below highlighted code is called exception filter config.

services.AddMvc(config => {
                            config.Filters.Add(typeof(GlobalExceptionFilter));
                         });



No comments:

Post a Comment