Customize ProblemDetails results with Minimal API
Is there currently any way to override the way that ProblemDetails are constructed in ResultExtensions when using Minimal API? When using full blown Controllers, this is something very easy to do by manipulating AddResultConvention, but I don't see anything similar for Minimal API, as ToMinimalApiResult hard codes the format of the ProblemDetails, which doesn't entirely fit our needs.
If this is not possible, are there any plans to implement this? I could write my own extension method, but it seems a bit of a waste to throw out all the logic that's already present in the Ardalis.Result package, so I wanted to check first.
@Gamingdevil Thanks for opening an issue! There are currently no plans to implement this but we are always open to proposals assuming the implementation isn't too much to maintain on our end. The result convention code for controllers is a lot of overhead that hadn't been ported to minimal APIs since out of the box behavior was "good enough" for most cases. Could you describe your use case vs the existing behavior as it is a bit more and maybe propose a solution that would work for you?
@KyleMcMaster I actually just wanted a little more control of the response values. We like to have some more info in our (Validation)ProblemDetails than you have in your default implementation; e.g. we include the actual validation failures in the "errors" extension on the ValidationProblemDetails.
Currently, I implemented it like this, where our actual transformation logic is in the ToProblemDetails extensions
public static Microsoft.AspNetCore.Http.IResult ToMinimalApiResultWithProblemDetails(this Ardalis.Result.Result result)
{
return result.ToMinimalApiResultWithProblemDetails<Ardalis.Result.Result>();
}
public static Microsoft.AspNetCore.Http.IResult ToMinimalApiResultWithProblemDetails<T>(this Result<T> result)
{
return result.Status switch
{
ResultStatus.Invalid => Results.BadRequest(result.ToValidationProblemDetails()),
ResultStatus.NotFound => Results.NotFound(result.ToProblemDetails()),
ResultStatus.Error => Results.UnprocessableEntity(result.ToProblemDetails()),
ResultStatus.Conflict => Results.Conflict(result.ToProblemDetails()),
ResultStatus.CriticalError => Results.Problem(result.ToProblemDetails()!),
_ => result.ToMinimalApiResult(),
} ?? result.ToMinimalApiResult();
}
It works, but it's slightly annoying that I basically had to duplicate a large part of the logic you've already implemented, and so was wondering if there was a cleaner way to do this. I realise that the convention code is overkill for this particular problem, but it would still be nice if we could somehow plug into your existing code.
Also, as an aside, why is the ToMinimalApiResult(this IResult result) overload marked as internal, when the wrappers for Result and Result<T> don't really add any logic? Perhaps I'm missing something.
Thank you for your consideration.