diff --git a/src/Http/Http.Results/src/PublicAPI.Unshipped.txt b/src/Http/Http.Results/src/PublicAPI.Unshipped.txt index 96ce109da59d..7eff16008f12 100644 --- a/src/Http/Http.Results/src/PublicAPI.Unshipped.txt +++ b/src/Http/Http.Results/src/PublicAPI.Unshipped.txt @@ -20,7 +20,8 @@ static Microsoft.AspNetCore.Http.Results.LocalRedirect(string! localUrl, bool pe static Microsoft.AspNetCore.Http.Results.NoContent() -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.NotFound(object? value = null) -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.Ok(object? value = null) -> Microsoft.AspNetCore.Http.IResult! -static Microsoft.AspNetCore.Http.Results.Problem(string? detail = null, string? instance = null, int? statusCode = null, string? title = null, string? type = null) -> Microsoft.AspNetCore.Http.IResult! +static Microsoft.AspNetCore.Http.Results.Problem(string? detail = null, string? instance = null, int? statusCode = null, string? title = null, string? type = null, System.Collections.Generic.IDictionary? extensions = null) -> Microsoft.AspNetCore.Http.IResult! +static Microsoft.AspNetCore.Http.Results.Problem(Microsoft.AspNetCore.Mvc.ProblemDetails! problemDetails) -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.Redirect(string! url, bool permanent = false, bool preserveMethod = false) -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.RedirectToRoute(string? routeName = null, object? routeValues = null, bool permanent = false, bool preserveMethod = false, string? fragment = null) -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.SignIn(System.Security.Claims.ClaimsPrincipal! principal, Microsoft.AspNetCore.Authentication.AuthenticationProperties? properties = null, string? authenticationScheme = null) -> Microsoft.AspNetCore.Http.IResult! @@ -30,6 +31,6 @@ static Microsoft.AspNetCore.Http.Results.Stream(System.IO.Stream! stream, string static Microsoft.AspNetCore.Http.Results.Text(string! content, string? contentType = null, System.Text.Encoding? contentEncoding = null) -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.Unauthorized() -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.UnprocessableEntity(object? error = null) -> Microsoft.AspNetCore.Http.IResult! -static Microsoft.AspNetCore.Http.Results.ValidationProblem(System.Collections.Generic.IDictionary! errors, string? detail = null, string? instance = null, int? statusCode = null, string? title = null, string? type = null) -> Microsoft.AspNetCore.Http.IResult! +static Microsoft.AspNetCore.Http.Results.ValidationProblem(System.Collections.Generic.IDictionary! errors, string? detail = null, string? instance = null, int? statusCode = null, string? title = null, string? type = null, System.Collections.Generic.IDictionary? extensions = null) -> Microsoft.AspNetCore.Http.IResult! static Microsoft.AspNetCore.Http.Results.Extensions.get -> Microsoft.AspNetCore.Http.IResultExtensions! -Microsoft.AspNetCore.Http.IResultExtensions \ No newline at end of file +Microsoft.AspNetCore.Http.IResultExtensions diff --git a/src/Http/Http.Results/src/Results.cs b/src/Http/Http.Results/src/Results.cs index 15d4937e3a24..aa69b20ea4d9 100644 --- a/src/Http/Http.Results/src/Results.cs +++ b/src/Http/Http.Results/src/Results.cs @@ -471,13 +471,15 @@ public static IResult UnprocessableEntity(object? error = null) /// The value for . /// The value for . /// The value for . + /// The value for . /// The created for the response. public static IResult Problem( string? detail = null, string? instance = null, int? statusCode = null, string? title = null, - string? type = null) + string? type = null, + IDictionary? extensions = null) { var problemDetails = new ProblemDetails { @@ -485,9 +487,30 @@ public static IResult Problem( Instance = instance, Status = statusCode, Title = title, - Type = type + Type = type, }; + if (extensions is not null) + { + foreach (var extension in extensions) + { + problemDetails.Extensions.Add(extension); + } + } + + return new ObjectResult(problemDetails) + { + ContentType = "application/problem+json", + }; + } + + /// + /// Produces a response. + /// + /// The object to produce a response from. + /// The created for the response. + public static IResult Problem(ProblemDetails problemDetails) + { return new ObjectResult(problemDetails) { ContentType = "application/problem+json", @@ -502,8 +525,9 @@ public static IResult Problem( /// The value for . /// The value for . /// The status code. - /// The value for . + /// The value for . Defaults to "One or more validation errors occurred." /// The value for . + /// The value for . /// The created for the response. public static IResult ValidationProblem( IDictionary errors, @@ -511,16 +535,26 @@ public static IResult ValidationProblem( string? instance = null, int? statusCode = null, string? title = null, - string? type = null) + string? type = null, + IDictionary? extensions = null) { var problemDetails = new HttpValidationProblemDetails(errors) { Detail = detail, Instance = instance, - Title = title, Type = type, Status = statusCode, }; + + problemDetails.Title = title ?? problemDetails.Title; + + if (extensions is not null) + { + foreach (var extension in extensions) + { + problemDetails.Extensions.Add(extension); + } + } return new ObjectResult(problemDetails) { diff --git a/src/Http/samples/MinimalSample/MinimalSample.csproj b/src/Http/samples/MinimalSample/MinimalSample.csproj index 6b59d1446b9b..eea90b96520b 100644 --- a/src/Http/samples/MinimalSample/MinimalSample.csproj +++ b/src/Http/samples/MinimalSample/MinimalSample.csproj @@ -8,6 +8,8 @@ + + diff --git a/src/Http/samples/MinimalSample/Program.cs b/src/Http/samples/MinimalSample/Program.cs index 5441e671a8f9..12b78a782467 100644 --- a/src/Http/samples/MinimalSample/Program.cs +++ b/src/Http/samples/MinimalSample/Program.cs @@ -1,9 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Mvc; var app = WebApplication.Create(args); @@ -13,12 +11,29 @@ } string Plaintext() => "Hello, World!"; -app.MapGet("/plaintext", (Func)Plaintext); +app.MapGet("/plaintext", Plaintext); + object Json() => new { message = "Hello, World!" }; -app.MapGet("/json", (Func)Json); +app.MapGet("/json", Json); string SayHello(string name) => $"Hello, {name}!"; -app.MapGet("/hello/{name}", (Func)SayHello); +app.MapGet("/hello/{name}", SayHello); + +var extensions = new Dictionary() { { "traceId", "traceId123" } }; + +app.MapGet("/problem", () => + Results.Problem(statusCode: 500, extensions: extensions)); + +app.MapGet("/problem-object", () => + Results.Problem(new ProblemDetails() { Status = 500, Extensions = { { "traceId", "traceId123"} } })); + +var errors = new Dictionary(); + +app.MapGet("/validation-problem", () => + Results.ValidationProblem(errors, statusCode: 400, extensions: extensions)); + +app.MapGet("/validation-problem-object", () => + Results.Problem(new HttpValidationProblemDetails(errors) { Status = 400, Extensions = { { "traceId", "traceId123"}}})); app.Run();