This repository has been archived by the owner on Dec 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Complete redesign: -Changed how developer configures the error response container -Changed how developer creates new custom details -Added Swagger example documentation models -Simplified/cleaned up how developer sets up ExceptionAll in Program.cs
- Loading branch information
1 parent
e83d092
commit c31ca9c
Showing
68 changed files
with
1,279 additions
and
909 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 77 additions & 60 deletions
137
ExceptionAll.APIExample/Controllers/WeatherForecastController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,100 @@ | ||
using ExceptionAll.Details; | ||
using ExceptionAll.Interfaces; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.AspNetCore.Mvc; | ||
using Microsoft.Extensions.Logging; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Threading.Tasks; | ||
using ExceptionAll.Models; | ||
using Microsoft.AspNetCore.Authorization; | ||
|
||
namespace ExceptionAll.APIExample.Controllers | ||
namespace ExceptionAll.APIExample.Controllers; | ||
|
||
[ApiController] | ||
[Route("[controller]")] | ||
public class WeatherForecastController : ControllerBase | ||
{ | ||
[ApiController] | ||
[Route("[controller]")] | ||
public class WeatherForecastController : ControllerBase | ||
private static readonly string[] Summaries = new[] | ||
{ | ||
private static readonly string[] Summaries = new[] | ||
{ | ||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | ||
}; | ||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | ||
}; | ||
|
||
private readonly ILogger<WeatherForecastController> _logger; | ||
private readonly IActionResultService _actionResultService; | ||
private readonly ILogger<WeatherForecastController> _logger; | ||
private readonly IActionResultService _actionResultService; | ||
|
||
public WeatherForecastController(ILogger<WeatherForecastController> logger, | ||
IActionResultService actionResultService) | ||
{ | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
_actionResultService = actionResultService ?? throw new ArgumentNullException(nameof(actionResultService)); | ||
} | ||
public WeatherForecastController(ILogger<WeatherForecastController> logger, | ||
IActionResultService actionResultService) | ||
{ | ||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | ||
_actionResultService = actionResultService ?? throw new ArgumentNullException(nameof(actionResultService)); | ||
} | ||
|
||
[HttpGet] | ||
public async Task<IActionResult> GetAll() | ||
[HttpGet] | ||
[ProducesResponseType(typeof(ApiErrorDetails), (int)HttpStatusCode.InternalServerError)] | ||
public async Task<IActionResult> GetAll() | ||
{ | ||
await Task.Delay(0); | ||
var rng = new Random(); | ||
var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast | ||
{ | ||
await Task.Delay(0); | ||
var rng = new Random(); | ||
var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast | ||
{ | ||
Date = DateTime.Now.AddDays(index), | ||
TemperatureC = rng.Next(-20, 55), | ||
Summary = Summaries[rng.Next(Summaries.Length)] | ||
}) | ||
.ToArray(); | ||
throw new Exception("This is simulating an uncaught exception"); | ||
} | ||
Date = DateTime.Now.AddDays(index), | ||
TemperatureC = rng.Next(-20, 55), | ||
Summary = Summaries[rng.Next(Summaries.Length)] | ||
}) | ||
.ToArray(); | ||
throw new Exception("This is simulating an uncaught exception"); | ||
} | ||
|
||
[HttpGet] | ||
[Route("api/GetNullRefError")] | ||
public async Task<IActionResult> GetNullRefError(string param) | ||
[HttpGet] | ||
[Route("api/GetNullRefError")] | ||
public async Task<IActionResult> GetNullRefError(string param, string otherParam) | ||
{ | ||
param = null; | ||
await Task.Delay(0); | ||
throw new ArgumentNullException(nameof(param)); | ||
} | ||
|
||
// If the developer doesn't want to use the template in all instances, | ||
// wrapping the code in try catch will let you use your own logic | ||
[HttpGet] | ||
[Route("api/GetWithoutExceptionAllError")] | ||
public async Task<IActionResult> GetWithoutExceptionAllError() | ||
{ | ||
await Task.Delay(0); | ||
try | ||
{ | ||
param = null; | ||
await Task.Delay(0); | ||
throw new ArgumentNullException(nameof(param)); | ||
throw new Exception("Some exception"); | ||
} | ||
|
||
// If the developer doesn't want to use the template in all instances, | ||
// wrapping the code in try catch will let you use your own logic | ||
[HttpGet] | ||
[Route("api/GetWithoutExceptionAllError")] | ||
public async Task<IActionResult> GetWithoutExceptionAllError() | ||
catch (Exception e) | ||
{ | ||
await Task.Delay(0); | ||
try | ||
{ | ||
throw new Exception("Some exception"); | ||
} | ||
catch (Exception e) | ||
{ | ||
Console.WriteLine(e); | ||
return BadRequest(e.Message); | ||
} | ||
Console.WriteLine(e); | ||
return BadRequest(e.Message); | ||
} | ||
} | ||
|
||
// If the developer needs to manually error handle, they can call | ||
// the 'GetResponse' manually | ||
[HttpGet] | ||
[Route("api/GetSomething")] | ||
public async Task<IActionResult> GetSomethingWithQuery([FromQuery]string test) | ||
// If the developer needs to manually error handle, they can call | ||
// the 'GetResponse' manually | ||
[HttpGet] | ||
[Route("api/GetSomething")] | ||
[ProducesResponseType(typeof(BadRequestDetails), StatusCodes.Status400BadRequest)] | ||
[ProducesResponseType(typeof(NotFoundDetails), StatusCodes.Status404NotFound)] | ||
[ProducesResponseType(typeof(InternalServerErrorDetails), StatusCodes.Status500InternalServerError)] | ||
public async Task<IActionResult> GetSomethingWithQuery([FromQuery] string test) | ||
{ | ||
await Task.Delay(0); | ||
|
||
var errors = new List<ErrorDetail> | ||
{ | ||
await Task.Delay(0); | ||
return _actionResultService.GetResponse<NotFoundDetails>(ControllerContext, | ||
$"No item exists with name of {test}"); | ||
} | ||
new("Error #1", "Something wrong happened here"), | ||
new("Error #2", "Something wrong happened there") | ||
}; | ||
|
||
return _actionResultService.GetResponse<NotFoundDetails>( | ||
ControllerContext, | ||
$"No item exists with name of {test}", | ||
errors); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,36 @@ | ||
using ExceptionAll.Details; | ||
using ExceptionAll.Dtos; | ||
using ExceptionAll.Interfaces; | ||
using ExceptionAll.Interfaces; | ||
using ExceptionAll.Models; | ||
using FluentValidation; | ||
using Microsoft.AspNetCore.Http; | ||
using Microsoft.Extensions.Logging; | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace ExceptionAll.APIExample | ||
namespace ExceptionAll.APIExample; | ||
|
||
public class ExceptionAllConfiguration : IExceptionAllConfiguration | ||
{ | ||
public static class ExceptionAllConfiguration | ||
public List<IErrorResponse> ErrorResponses => new() | ||
{ | ||
public static List<IErrorResponse> GetErrorResponses() | ||
{ | ||
return new List<IErrorResponse>() | ||
{ | ||
ErrorResponse | ||
.CreateErrorResponse() | ||
.WithTitle("Bad Request - Fluent Validation") | ||
.ForException<ValidationException>() | ||
.WithReturnType<BadRequestDetails>() | ||
.WithLogAction((x, e) => x.LogError(e, "Something bad happened")), | ||
ErrorResponse | ||
.CreateErrorResponse() | ||
.WithTitle("Argument Null Exception") | ||
.WithStatusCode(500) | ||
.WithMessage("The developer goofed") | ||
.ForException<ArgumentNullException>() | ||
.WithLogAction((x, e) => x.LogDebug(e, "Oops I did it again")) | ||
}; | ||
|
||
ErrorResponse | ||
.CreateErrorResponse() | ||
.WithTitle("Bad Request") | ||
.ForException<ArgumentNullException>() | ||
.WithReturnType<BadRequestDetails>() | ||
.WithLogAction((x, e) => x.LogError(e, "Something bad happened")) | ||
}; | ||
public Dictionary<string, Func<HttpContext, object>>? ContextConfiguration => new() | ||
{ | ||
{ "Path", x => x?.Request.Path.Value ?? string.Empty }, | ||
{ "Query", x => x.Request.QueryString.Value ?? string.Empty }, | ||
{ "TraceIdentifier", x => x?.TraceIdentifier ?? string.Empty }, | ||
{ "LocalIpAddress", x => x?.Connection.LocalIpAddress?.ToString() ?? string.Empty }, | ||
{ | ||
"CorrelationId", | ||
x => x.Request.Headers["x-correlation-id"] | ||
.ToString() | ||
} | ||
} | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,55 @@ | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Hosting; | ||
using Microsoft.Extensions.Logging; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace ExceptionAll.APIExample | ||
{ | ||
public class Program | ||
using ExceptionAll.APIExample; | ||
using ExceptionAll.Helpers; | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.OpenApi.Models; | ||
using Swashbuckle.AspNetCore.Filters; | ||
using System.IO; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
|
||
// Add services to the container. | ||
|
||
builder.Services.AddExceptionAll<ExceptionAllConfiguration>() | ||
.WithExceptionAllSwaggerExamples(); | ||
|
||
builder.Services.AddControllers(); | ||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle | ||
builder.Services.AddEndpointsApiExplorer(); | ||
|
||
builder.Services.AddSwaggerGen( | ||
c => | ||
{ | ||
public static void Main(string[] args) | ||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "ExceptionAll.APIExample", Version = "v1" }); | ||
c.EnableAnnotations(); | ||
c.ExampleFilters(); | ||
|
||
if (File.Exists("/ExceptionAll-swagger.xml")) | ||
{ | ||
CreateHostBuilder(args).Build().Run(); | ||
c.IncludeXmlComments("/ExceptionAll-swagger.xml"); | ||
} | ||
}); | ||
|
||
var app = builder.Build(); | ||
|
||
app.Services.AddExceptionAll(); | ||
|
||
// Configure the HTTP request pipeline. | ||
|
||
app.UseSwagger(); | ||
|
||
app.UseSwaggerUI( | ||
c => | ||
{ | ||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "ExceptionAll.APIExample v1"); | ||
c.DisplayRequestDuration(); | ||
c.EnableTryItOutByDefault(); | ||
}); | ||
|
||
app.UseHttpsRedirection(); | ||
|
||
app.UseAuthorization(); | ||
|
||
app.MapControllers(); | ||
|
||
public static IHostBuilder CreateHostBuilder(string[] args) => | ||
Host.CreateDefaultBuilder(args) | ||
.ConfigureWebHostDefaults(webBuilder => | ||
{ | ||
webBuilder.UseStartup<Startup>(); | ||
}); | ||
} | ||
} | ||
app.Run(); |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.