Created
May 21, 2024 14:52
-
-
Save Bardin08/14b742c85725a9eb556b2308306dce65 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
using ErrorOr; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.AspNetCore.Mvc.Infrastructure; | |
using Microsoft.AspNetCore.Mvc.ModelBinding; | |
using Microsoft.Extensions.Options; | |
using System.Diagnostics; | |
using Trumpet.Api.Common.Http; | |
namespace Trumpet.Api.Common.Errors; | |
public sealed class TrumpetProblemDetailsFactory : ProblemDetailsFactory | |
{ | |
private readonly Action<ProblemDetailsContext>? _configure; | |
private readonly ApiBehaviorOptions _options; | |
public TrumpetProblemDetailsFactory( | |
IOptions<ApiBehaviorOptions> options, | |
IOptions<ProblemDetailsOptions>? problemDetailsOptions = null) | |
{ | |
_options = options?.Value ?? throw new ArgumentNullException(nameof(options)); | |
_configure = problemDetailsOptions?.Value?.CustomizeProblemDetails; | |
} | |
public override ProblemDetails CreateProblemDetails( | |
HttpContext httpContext, | |
int? statusCode = null, | |
string? title = null, | |
string? type = null, | |
string? detail = null, | |
string? instance = null) | |
{ | |
statusCode ??= 500; | |
var problemDetails = new ProblemDetails | |
{ | |
Status = statusCode, | |
Title = title, | |
Type = type, | |
Detail = detail, | |
Instance = instance | |
}; | |
ApplyProblemDetailsDefaults(httpContext, problemDetails, statusCode.Value); | |
return problemDetails; | |
} | |
public override ValidationProblemDetails CreateValidationProblemDetails( | |
HttpContext httpContext, | |
ModelStateDictionary modelStateDictionary, | |
int? statusCode = null, | |
string? title = null, | |
string? type = null, | |
string? detail = null, | |
string? instance = null) | |
{ | |
ArgumentNullException.ThrowIfNull(modelStateDictionary); | |
statusCode ??= 400; | |
var problemDetails = new ValidationProblemDetails(modelStateDictionary) | |
{ | |
Status = statusCode, | |
Type = type, | |
Detail = detail, | |
Instance = instance | |
}; | |
if (title != null) | |
problemDetails.Title = title; | |
ApplyProblemDetailsDefaults(httpContext, problemDetails, statusCode.Value); | |
return problemDetails; | |
} | |
private void ApplyProblemDetailsDefaults(HttpContext httpContext, ProblemDetails problemDetails, int statusCode) | |
{ | |
problemDetails.Status ??= statusCode; | |
if (_options.ClientErrorMapping.TryGetValue(statusCode, out var clientErrorData)) | |
{ | |
problemDetails.Title ??= clientErrorData.Title; | |
problemDetails.Type ??= clientErrorData.Link; | |
} | |
var traceId = Activity.Current?.Id ?? httpContext?.TraceIdentifier; | |
if (traceId != null) problemDetails.Extensions["traceId"] = traceId; | |
if (httpContext?.Items[HttpContextItemKeys.Errors] is List<Error> errors) | |
problemDetails.Extensions.Add("errorCodes", errors.Select(e => e.Code)); | |
_configure?.Invoke(new ProblemDetailsContext { HttpContext = httpContext!, ProblemDetails = problemDetails }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment