diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491f31 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/GlobalErrorHandling-End/.vs +/GlobalErrorHandling-End/GlobalErrorHandling/obj +/GlobalErrorHandling-End/GlobalErrorHandling/bin +/GlobalErrorHandling-End/LoggerService/obj +/GlobalErrorHandling-End/LoggerService/bin diff --git a/GlobalErrorHandling-End/GlobalErrorHandling.sln b/GlobalErrorHandling-End/GlobalErrorHandling.sln new file mode 100644 index 0000000..6f2aa32 --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29418.71 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalErrorHandling", "GlobalErrorHandling\GlobalErrorHandling.csproj", "{AF62693C-1877-485B-865D-C3CAEB2CBA12}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoggerService", "LoggerService\LoggerService.csproj", "{B61D597A-BF38-4F7D-BE39-C024B59C114D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AF62693C-1877-485B-865D-C3CAEB2CBA12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF62693C-1877-485B-865D-C3CAEB2CBA12}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF62693C-1877-485B-865D-C3CAEB2CBA12}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF62693C-1877-485B-865D-C3CAEB2CBA12}.Release|Any CPU.Build.0 = Release|Any CPU + {B61D597A-BF38-4F7D-BE39-C024B59C114D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B61D597A-BF38-4F7D-BE39-C024B59C114D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B61D597A-BF38-4F7D-BE39-C024B59C114D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B61D597A-BF38-4F7D-BE39-C024B59C114D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EF9B2F79-1783-4500-B905-45712FB7606D} + EndGlobalSection +EndGlobal diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/Controllers/ValuesController.cs b/GlobalErrorHandling-End/GlobalErrorHandling/Controllers/ValuesController.cs new file mode 100644 index 0000000..e2e3257 --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Controllers/ValuesController.cs @@ -0,0 +1,31 @@ +using System; +using LoggerService; +using Microsoft.AspNetCore.Mvc; + +namespace GlobalErrorHandling.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class ValuesController : ControllerBase + { + private ILoggerManager _logger; + public ValuesController(ILoggerManager logger) + { + _logger = logger; + } + + [HttpGet] + public IActionResult Get() + { + _logger.LogInfo("Fetching all the Students from the storage"); + + var students = DataManager.GetAllStudents(); //simulation for the data base access + + throw new AccessViolationException("Violation Exception while accessing the resource."); + + _logger.LogInfo($"Returning {students.Count} students."); + + return Ok(students); + } + } +} \ No newline at end of file diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/CustomExceptionMiddleware/ExceptionMiddleware.cs b/GlobalErrorHandling-End/GlobalErrorHandling/CustomExceptionMiddleware/ExceptionMiddleware.cs new file mode 100644 index 0000000..ad54e01 --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/CustomExceptionMiddleware/ExceptionMiddleware.cs @@ -0,0 +1,57 @@ +using GlobalErrorHandling.Models; +using LoggerService; +using Microsoft.AspNetCore.Http; +using System; +using System.Net; +using System.Threading.Tasks; + +namespace GlobalErrorHandling.CustomExceptionMiddleware +{ + public class ExceptionMiddleware + { + private readonly RequestDelegate _next; + private readonly ILoggerManager _logger; + + public ExceptionMiddleware(RequestDelegate next, ILoggerManager logger) + { + _logger = logger; + _next = next; + } + + public async Task InvokeAsync(HttpContext httpContext) + { + try + { + await _next(httpContext); + } + catch (AccessViolationException avEx) + { + _logger.LogError($"A new violation exception has been thrown: {avEx}"); + await HandleExceptionAsync(httpContext, avEx); + } + catch (Exception ex) + { + _logger.LogError($"Something went wrong: {ex}"); + await HandleExceptionAsync(httpContext, ex); + } + } + + private async Task HandleExceptionAsync(HttpContext context, Exception exception) + { + context.Response.ContentType = "application/json"; + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + + var message = exception switch + { + AccessViolationException => "Access violation error from the custom middleware", + _ => "Internal Server Error from the custom middleware." + }; + + await context.Response.WriteAsync(new ErrorDetails() + { + StatusCode = context.Response.StatusCode, + Message = message + }.ToString()); + } + } +} diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/DataManager.cs b/GlobalErrorHandling-End/GlobalErrorHandling/DataManager.cs similarity index 80% rename from GlobalErrorHandling-Start/GlobalErrorHandling/DataManager.cs rename to GlobalErrorHandling-End/GlobalErrorHandling/DataManager.cs index 408b43c..6e1d96e 100644 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/DataManager.cs +++ b/GlobalErrorHandling-End/GlobalErrorHandling/DataManager.cs @@ -1,12 +1,9 @@ -using System; +using GlobalErrorHandling.Models; using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using GlobalErrorHandling.Models; namespace GlobalErrorHandling { - public static class DataManager + public class DataManager { public static List GetAllStudents() { diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/Extensions/ExceptionMiddlewareExtensions.cs b/GlobalErrorHandling-End/GlobalErrorHandling/Extensions/ExceptionMiddlewareExtensions.cs new file mode 100644 index 0000000..c45edb3 --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Extensions/ExceptionMiddlewareExtensions.cs @@ -0,0 +1,42 @@ +using GlobalErrorHandling.CustomExceptionMiddleware; +using GlobalErrorHandling.Models; +using LoggerService; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Http; +using System.Net; + +namespace GlobalErrorHandling.Extensions +{ + public static class ExceptionMiddlewareExtensions + { + public static void ConfigureExceptionHandler(this IApplicationBuilder app, ILoggerManager logger) + { + app.UseExceptionHandler(appError => + { + appError.Run(async context => + { + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + context.Response.ContentType = "application/json"; + + var contextFeature = context.Features.Get(); + if (contextFeature != null) + { + logger.LogError($"Something went wrong: {contextFeature.Error}"); + + await context.Response.WriteAsync(new ErrorDetails() + { + StatusCode = context.Response.StatusCode, + Message = "Internal Server Error." + }.ToString()); + } + }); + }); + } + + public static void ConfigureCustomExceptionMiddleware(this IApplicationBuilder app) + { + app.UseMiddleware(); + } + } +} diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/GlobalErrorHandling.csproj b/GlobalErrorHandling-End/GlobalErrorHandling/GlobalErrorHandling.csproj new file mode 100644 index 0000000..a26d17e --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/GlobalErrorHandling.csproj @@ -0,0 +1,21 @@ + + + + net5.0 + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/GlobalErrorHandling.csproj.user b/GlobalErrorHandling-End/GlobalErrorHandling/GlobalErrorHandling.csproj.user new file mode 100644 index 0000000..2a7762e --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/GlobalErrorHandling.csproj.user @@ -0,0 +1,17 @@ + + + + ProjectDebugger + + + GlobalErrorHandling + ApiControllerEmptyScaffolder + root/Controller + 600 + True + False + True + + False + + \ No newline at end of file diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/Models/ErrorDetails.cs b/GlobalErrorHandling-End/GlobalErrorHandling/Models/ErrorDetails.cs new file mode 100644 index 0000000..3283340 --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Models/ErrorDetails.cs @@ -0,0 +1,15 @@ +using System.Text.Json; + +namespace GlobalErrorHandling.Models +{ + public class ErrorDetails + { + public int StatusCode { get; set; } + public string Message { get; set; } + + public override string ToString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/Models/Student.cs b/GlobalErrorHandling-End/GlobalErrorHandling/Models/Student.cs similarity index 60% rename from GlobalErrorHandling-Start/GlobalErrorHandling/Models/Student.cs rename to GlobalErrorHandling-End/GlobalErrorHandling/Models/Student.cs index 5be9144..ea142e1 100644 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/Models/Student.cs +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Models/Student.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace GlobalErrorHandling.Models +namespace GlobalErrorHandling.Models { public class Student { diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/Program.cs b/GlobalErrorHandling-End/GlobalErrorHandling/Program.cs new file mode 100644 index 0000000..9cbb5a4 --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Program.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; + +namespace GlobalErrorHandling +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/Properties/launchSettings.json b/GlobalErrorHandling-End/GlobalErrorHandling/Properties/launchSettings.json new file mode 100644 index 0000000..7349f3b --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Properties/launchSettings.json @@ -0,0 +1,13 @@ +{ + "profiles": { + "GlobalErrorHandling": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "api/values", + "applicationUrl": "http://localhost:55761", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/Startup.cs b/GlobalErrorHandling-End/GlobalErrorHandling/Startup.cs similarity index 61% rename from GlobalErrorHandling-Start/GlobalErrorHandling/Startup.cs rename to GlobalErrorHandling-End/GlobalErrorHandling/Startup.cs index 2c626ad..10bafd8 100644 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/Startup.cs +++ b/GlobalErrorHandling-End/GlobalErrorHandling/Startup.cs @@ -1,10 +1,11 @@ -using System; using System.IO; +using GlobalErrorHandling.Extensions; using LoggerService; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using NLog; namespace GlobalErrorHandling @@ -13,7 +14,7 @@ public class Startup { public Startup(IConfiguration configuration) { - LogManager.LoadConfiguration(String.Concat(Directory.GetCurrentDirectory(), "/nlog.config")); + LogManager.LoadConfiguration(string.Concat(Directory.GetCurrentDirectory(), "/nlog.config")); Configuration = configuration; } @@ -23,18 +24,31 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddSingleton(); - services.AddMvc(); + + services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerManager logger) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } - app.UseMvc(); + //app.ConfigureExceptionHandler(logger); + app.ConfigureCustomExceptionMiddleware(); + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); } } } diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/appsettings.Development.json b/GlobalErrorHandling-End/GlobalErrorHandling/appsettings.Development.json similarity index 80% rename from GlobalErrorHandling-Start/GlobalErrorHandling/appsettings.Development.json rename to GlobalErrorHandling-End/GlobalErrorHandling/appsettings.Development.json index fa8ce71..e203e94 100644 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/appsettings.Development.json +++ b/GlobalErrorHandling-End/GlobalErrorHandling/appsettings.Development.json @@ -1,6 +1,5 @@ -{ +{ "Logging": { - "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", diff --git a/GlobalErrorHandling-End/GlobalErrorHandling/appsettings.json b/GlobalErrorHandling-End/GlobalErrorHandling/appsettings.json new file mode 100644 index 0000000..d9d9a9b --- /dev/null +++ b/GlobalErrorHandling-End/GlobalErrorHandling/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/nlog.config b/GlobalErrorHandling-End/GlobalErrorHandling/nlog.config similarity index 89% rename from GlobalErrorHandling-Start/GlobalErrorHandling/nlog.config rename to GlobalErrorHandling-End/GlobalErrorHandling/nlog.config index f31c804..a6fd586 100644 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/nlog.config +++ b/GlobalErrorHandling-End/GlobalErrorHandling/nlog.config @@ -5,10 +5,6 @@ internalLogLevel="Trace" internalLogFile="c:/GlobalErrorHandlingLogs/internal_logs/internallog.txt"> - - - - - netcoreapp2.0 + net5.0 - + diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling.sln b/GlobalErrorHandling-Start/GlobalErrorHandling.sln deleted file mode 100644 index 96c425f..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2018 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GlobalErrorHandling", "GlobalErrorHandling\GlobalErrorHandling.csproj", "{EE171A5A-17A3-4C16-8A1B-5E72A33DA4E4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoggerService", "LoggerService\LoggerService.csproj", "{57214E50-4D1C-463A-A200-1EA829DE8BBE}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EE171A5A-17A3-4C16-8A1B-5E72A33DA4E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE171A5A-17A3-4C16-8A1B-5E72A33DA4E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE171A5A-17A3-4C16-8A1B-5E72A33DA4E4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE171A5A-17A3-4C16-8A1B-5E72A33DA4E4}.Release|Any CPU.Build.0 = Release|Any CPU - {57214E50-4D1C-463A-A200-1EA829DE8BBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {57214E50-4D1C-463A-A200-1EA829DE8BBE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {57214E50-4D1C-463A-A200-1EA829DE8BBE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {57214E50-4D1C-463A-A200-1EA829DE8BBE}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E5D03030-7E40-4C80-8768-44A70842D9B1} - EndGlobalSection -EndGlobal diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/Controllers/ValuesController.cs b/GlobalErrorHandling-Start/GlobalErrorHandling/Controllers/ValuesController.cs deleted file mode 100644 index c466c31..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/Controllers/ValuesController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using LoggerService; -using Microsoft.AspNetCore.Mvc; - -namespace GlobalErrorHandling.Controllers -{ - [Route("api/[controller]")] - public class ValuesController : Controller - { - private ILoggerManager _logger; - - public ValuesController(ILoggerManager logger) - { - _logger = logger; - } - - [HttpGet] - public IEnumerable Get() - { - return new string[] { "value1", "value2" }; - } - } -} diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/GlobalErrorHandling.csproj b/GlobalErrorHandling-Start/GlobalErrorHandling/GlobalErrorHandling.csproj deleted file mode 100644 index 57bfdc1..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/GlobalErrorHandling.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - - netcoreapp2.0 - - - - - - - - - - - - - - - - - - - diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/GlobalErrorHandling.csproj.user b/GlobalErrorHandling-Start/GlobalErrorHandling/GlobalErrorHandling.csproj.user deleted file mode 100644 index 0776e7f..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/GlobalErrorHandling.csproj.user +++ /dev/null @@ -1,9 +0,0 @@ - - - - ProjectDebugger - - - GlobalErrorHandling - - \ No newline at end of file diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/Program.cs b/GlobalErrorHandling-Start/GlobalErrorHandling/Program.cs deleted file mode 100644 index 0290050..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/Program.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -namespace GlobalErrorHandling -{ - public class Program - { - public static void Main(string[] args) - { - BuildWebHost(args).Run(); - } - - public static IWebHost BuildWebHost(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup() - .Build(); - } -} diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/Properties/launchSettings.json b/GlobalErrorHandling-Start/GlobalErrorHandling/Properties/launchSettings.json deleted file mode 100644 index a332b15..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/Properties/launchSettings.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:55760/", - "sslPort": 0 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": false, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "GlobalErrorHandling": { - "commandName": "Project", - "launchBrowser": false, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "http://localhost:55761/" - } - } -} diff --git a/GlobalErrorHandling-Start/GlobalErrorHandling/appsettings.json b/GlobalErrorHandling-Start/GlobalErrorHandling/appsettings.json deleted file mode 100644 index 26bb0ac..0000000 --- a/GlobalErrorHandling-Start/GlobalErrorHandling/appsettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "Debug": { - "LogLevel": { - "Default": "Warning" - } - }, - "Console": { - "LogLevel": { - "Default": "Warning" - } - } - } -} diff --git a/README.md b/README.md index a18f5b1..4faa1d2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# global-error-handling-aspnetcore -start +# Global Error Handling in ASP.NET Core Web API - END -https://code-maze.com/global-error-handling-dotnetcore/ \ No newline at end of file +https://code-maze.com/global-error-handling-aspnetcore/