|
6 | 6 | using Newtonsoft.Json; |
7 | 7 | using Microsoft.AspNetCore.Hosting; |
8 | 8 | using ReferenceProject.Exceptions; |
| 9 | +using Microsoft.Extensions.Hosting; |
9 | 10 |
|
10 | 11 | namespace ReferenceProject.Middleware |
11 | 12 | { |
12 | | - /// <summary> |
13 | | - /// Middleware to handle exceptions. |
14 | | - /// It separates exceptions based on their type and returns different status codes and answers based on it, instead of 500 Internal Server Error code in all cases. |
15 | | - /// In addition, it writes them in the log. |
16 | | - /// </summary> |
17 | | - /// <remarks> |
18 | | - /// There is another way to do this - an exception filter. |
19 | | - /// However, a middleware is a preferred way to achieve this according to the official documentation. |
20 | | - /// To learn more see https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1#exception-filters |
21 | | - /// |
22 | | - /// See also: https://github.com/drwatson1/AspNet-Core-REST-Service/wiki#unhandled-exceptions-handling |
23 | | - /// </remarks> |
24 | | - public class ExceptionMiddleware |
25 | | - { |
26 | | - RequestDelegate Next { get; } |
27 | | - ILogger Logger { get; } |
28 | | - IHostingEnvironment Environment { get; } |
| 13 | + /// <summary> |
| 14 | + /// Middleware to handle exceptions. |
| 15 | + /// It separates exceptions based on their type and returns different status codes and answers based on it, instead of 500 Internal Server Error code in all cases. |
| 16 | + /// In addition, it writes them in the log. |
| 17 | + /// </summary> |
| 18 | + /// <remarks> |
| 19 | + /// There is another way to do this - an exception filter. |
| 20 | + /// However, a middleware is a preferred way to achieve this according to the official documentation. |
| 21 | + /// To learn more see https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1#exception-filters |
| 22 | + /// |
| 23 | + /// See also: https://github.com/drwatson1/AspNet-Core-REST-Service/wiki#unhandled-exceptions-handling |
| 24 | + /// </remarks> |
| 25 | + public class ExceptionMiddleware |
| 26 | + { |
| 27 | + RequestDelegate Next { get; } |
| 28 | + ILogger Logger { get; } |
| 29 | + IWebHostEnvironment Environment { get; } |
29 | 30 |
|
30 | | - public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger, IHostingEnvironment environment) |
31 | | - { |
32 | | - Environment = environment ?? throw new ArgumentNullException(nameof(environment)); |
33 | | - Logger = logger ?? throw new ArgumentNullException(nameof(logger)); |
34 | | - Next = next ?? throw new ArgumentNullException(nameof(next)); |
35 | | - } |
| 31 | + public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger, IWebHostEnvironment environment) |
| 32 | + { |
| 33 | + Environment = environment ?? throw new ArgumentNullException(nameof(environment)); |
| 34 | + Logger = logger ?? throw new ArgumentNullException(nameof(logger)); |
| 35 | + Next = next ?? throw new ArgumentNullException(nameof(next)); |
| 36 | + } |
36 | 37 |
|
37 | | - public async Task InvokeAsync(HttpContext context) |
38 | | - { |
39 | | - var body = context.Response.Body; |
40 | | - try |
41 | | - { |
42 | | - await Next(context); |
43 | | - } |
44 | | - catch (Exception ex) |
45 | | - { |
46 | | - // If context.Response.HasStarted == true, then we can't write to the response stream anymore. So we have to restore the body. |
47 | | - // If we don't do that we get an exception. |
48 | | - context.Response.Body = body; |
49 | | - await HandleExceptionAsync(context, ex); |
50 | | - } |
51 | | - } |
| 38 | + public async Task InvokeAsync(HttpContext context) |
| 39 | + { |
| 40 | + var body = context.Response.Body; |
| 41 | + try |
| 42 | + { |
| 43 | + await Next(context); |
| 44 | + } |
| 45 | + catch (Exception ex) |
| 46 | + { |
| 47 | + // If context.Response.HasStarted == true, then we can't write to the response stream anymore. So we have to restore the body. |
| 48 | + // If we don't do that we get an exception. |
| 49 | + context.Response.Body = body; |
| 50 | + await HandleExceptionAsync(context, ex); |
| 51 | + } |
| 52 | + } |
52 | 53 |
|
53 | | - async Task HandleExceptionAsync(HttpContext context, Exception ex) |
54 | | - { |
55 | | - int statusCode = 500; |
| 54 | + async Task HandleExceptionAsync(HttpContext context, Exception ex) |
| 55 | + { |
| 56 | + int statusCode = 500; |
56 | 57 |
|
57 | | - context.Response.ContentType = "application/json"; |
58 | | - context.Response.StatusCode = statusCode; |
| 58 | + context.Response.ContentType = "application/json"; |
| 59 | + context.Response.StatusCode = statusCode; |
59 | 60 |
|
60 | | - // We can decide what the status code should return |
61 | | - if (ex is KeyNotFoundException) |
62 | | - { |
63 | | - context.Response.StatusCode = StatusCodes.Status404NotFound; |
64 | | - } |
65 | | - else if (ex is DuplicateKeyException) |
66 | | - { |
67 | | - context.Response.StatusCode = StatusCodes.Status400BadRequest; |
68 | | - } |
| 61 | + // We can decide what the status code should return |
| 62 | + if (ex is KeyNotFoundException) |
| 63 | + { |
| 64 | + context.Response.StatusCode = StatusCodes.Status404NotFound; |
| 65 | + } |
| 66 | + else if (ex is DuplicateKeyException) |
| 67 | + { |
| 68 | + context.Response.StatusCode = StatusCodes.Status400BadRequest; |
| 69 | + } |
69 | 70 |
|
70 | | - await context.Response.WriteAsync( |
71 | | - JsonConvert.SerializeObject( |
72 | | - new ErrorResponse(ex, Environment.IsDevelopment()))); |
| 71 | + await context.Response.WriteAsync( |
| 72 | + JsonConvert.SerializeObject( |
| 73 | + new ErrorResponse(ex, Environment.IsDevelopment()))); |
73 | 74 |
|
74 | | - if (context.Response.StatusCode == StatusCodes.Status500InternalServerError) |
75 | | - { |
76 | | - Logger.LogError(ex, "Unhandled exception occurred"); |
77 | | - } |
78 | | - else |
79 | | - { |
80 | | - Logger.LogDebug(ex, "Unhandled exception occurred"); |
81 | | - } |
82 | | - } |
| 75 | + if (context.Response.StatusCode == StatusCodes.Status500InternalServerError) |
| 76 | + { |
| 77 | + Logger.LogError(ex, "Unhandled exception occurred"); |
| 78 | + } |
| 79 | + else |
| 80 | + { |
| 81 | + Logger.LogDebug(ex, "Unhandled exception occurred"); |
| 82 | + } |
| 83 | + } |
83 | 84 |
|
84 | | - class ErrorResponse |
85 | | - { |
86 | | - public ErrorResponse(Exception ex, bool includeFullExceptionInfo) |
87 | | - { |
88 | | - Error = new ExceptionDescription(ex); |
89 | | - if(includeFullExceptionInfo) |
90 | | - { |
91 | | - Error.Exception = ex; |
92 | | - } |
93 | | - } |
| 85 | + class ErrorResponse |
| 86 | + { |
| 87 | + public ErrorResponse(Exception ex, bool includeFullExceptionInfo) |
| 88 | + { |
| 89 | + Error = new ExceptionDescription(ex); |
| 90 | + if (includeFullExceptionInfo) |
| 91 | + { |
| 92 | + Error.Exception = ex; |
| 93 | + } |
| 94 | + } |
94 | 95 |
|
95 | | - public ExceptionDescription Error { get; set; } |
96 | | - } |
| 96 | + public ExceptionDescription Error { get; set; } |
| 97 | + } |
97 | 98 |
|
98 | | - class ExceptionDescription |
99 | | - { |
100 | | - public ExceptionDescription(Exception ex) |
101 | | - { |
102 | | - Message = ex.Message; |
103 | | - } |
| 99 | + class ExceptionDescription |
| 100 | + { |
| 101 | + public ExceptionDescription(Exception ex) |
| 102 | + { |
| 103 | + Message = ex.Message; |
| 104 | + } |
104 | 105 |
|
105 | | - public string Message { get; set; } |
106 | | - public Exception Exception { get; set; } |
107 | | - } |
108 | | - } |
| 106 | + public string Message { get; set; } |
| 107 | + public Exception Exception { get; set; } |
| 108 | + } |
| 109 | + } |
109 | 110 | } |
0 commit comments