-
Hello, I want to know why methods ValidationProblem produces different output when they are called on Results or TypedResults class. Results.ValidationProblem(errorMessages) produces {Microsoft.AspNetCore.Http.HttpResults.ProblemHttpResult} with {Microsoft.AspNetCore.Http.HttpValidationProblemDetails} in detail TypedResults.ValidationProblem(errorMessages) produces {Microsoft.AspNetCore.Http.HttpResults.ValidationProblem} with {Microsoft.AspNetCore.Http.HttpValidationProblemDetails} in detail. I have my own IProblemDetailsWriter registered in DI before default one and when I use method on Results class it is hit. But when the TypedResults method is used my writer is not hit. In my code I'm using Results but I want to use MinimalApis.Extensions for input parameters validation with DataAnnotations. And there is used TypedResults. using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Net;
var builder = WebApplication.CreateBuilder(args);
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IProblemDetailsWriter, ValidationDetailsWriter>());
builder.Services.AddProblemDetails();
var app = builder.Build();
app.MapGet("results", () => { return Results.ValidationProblem(new Dictionary<string, string[]> { { "test", ["test"] } }); });
app.MapGet("typedresults", () => { return TypedResults.ValidationProblem(new Dictionary<string, string[]> { { "test", ["test"] } }); });
app.Run();
internal class ValidationDetailsWriter : IProblemDetailsWriter
{
public bool CanWrite(ProblemDetailsContext context) => true;
public async ValueTask WriteAsync(ProblemDetailsContext context)
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
await context.HttpContext.Response.WriteAsync("My response");
}
} It looks like ProblemHttpResult is somewhere handled with ProblemDetailService but ValidationProblem not. Is there a way how to handle ValidationProblem with same ProblemDetailService? Thank you |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
When the result is of type that implement It's the case with The method public sealed class ProblemHttpResult : IResult, ...
{
...
public async Task ExecuteAsync(HttpContext httpContext)
{
var problemDetailsService = httpContext.RequestServices.GetService<IProblemDetailsService>();
if (problemDetailsService is null || !await problemDetailsService.TryWriteAsync(new() { HttpContext = httpContext, ProblemDetails = ProblemDetails }))
{
await HttpResultsHelper.WriteResultAsJsonAsync(
httpContext,
logger,
value: ProblemDetails,
ContentType);
}
}
} The method public sealed class ValidationProblem : IResult, ...
{
public Task ExecuteAsync(HttpContext httpContext)
{
return HttpResultsHelper.WriteResultAsJsonAsync(
httpContext,
logger,
value: ProblemDetails,
ContentType);
}
} It's similar, just As hack, it's possible to add a operation filter to convert app.MapGet("typedresults", () => { return TypedResults.ValidationProblem(new Dictionary<string, string[]> { { "test", ["test"] } }); })
.AddEndpointFilter(async (efiContext, next) =>
{
var result = await next(efiContext);
if(result is ValidationProblem vp)
{
return Results.Problem(vp.ProblemDetails);
}
return result;
}); Can you specify your need? |
Beta Was this translation helpful? Give feedback.
-
There is an open issue and PR that will fix this: |
Beta Was this translation helpful? Give feedback.
When the result is of type that implement
IResult
, the response is generated byIResult.ExecuteAsync
.It's the case with
ProblemHttpResult
(that is returned byResults.ValidationProblem
) andValidationProblem
(that is returned byTypedResults.ValidationProblem
).The method
ProblemHttpResult.ExecuteAsync
is :