diff --git a/.gitignore b/.gitignore
index 370150d..0320691 100644
--- a/.gitignore
+++ b/.gitignore
@@ -433,4 +433,6 @@ _UpgradeReport_Files/
Thumbs.db
Desktop.ini
-.DS_Store
\ No newline at end of file
+.DS_Store
+**/.idea/
+.idea/
diff --git a/src/F23.Kernel.AspNetCore/MinimalApiResultExtensions.cs b/src/F23.Kernel.AspNetCore/MinimalApiResultExtensions.cs
new file mode 100644
index 0000000..000e300
--- /dev/null
+++ b/src/F23.Kernel.AspNetCore/MinimalApiResultExtensions.cs
@@ -0,0 +1,136 @@
+using System.Net;
+using F23.Hateoas;
+using F23.Kernel.Results;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.HttpResults;
+using UnauthorizedResult = F23.Kernel.Results.UnauthorizedResult;
+using HttpResults = Microsoft.AspNetCore.Http.Results;
+
+namespace F23.Kernel.AspNetCore;
+
+///
+/// Provides extension methods for converting objects to ASP.NET Core Minimal API objects.
+///
+public static class MinimalApiResultExtensions
+{
+ ///
+ /// Converts a into an appropriate to be used in a minimal API context.
+ ///
+ /// The to be converted.
+ /// Whether to use a RFC7807 problem details body for a failure response. The default is true.
+ ///
+ /// An that represents the appropriate response:
+ ///
+ /// for a .
+ /// with RFC7807 for any non-successful result if is true.
+ /// for a with a reason of if is false.
+ /// with status code 412 for a with a reason of if is false.
+ /// for a with a reason of if is false.
+ /// with model state populated for a if is false.
+ /// for an if is false.
+ ///
+ ///
+ ///
+ /// Thrown when the does not match any known result types.
+ ///
+ public static IResult ToMinimalApiResult(this Result result, bool useProblemDetails = true)
+ => result switch
+ {
+ SuccessResult
+ => HttpResults.NoContent(),
+ AggregateResult { IsSuccess: true }
+ => HttpResults.NoContent(),
+ AggregateResult { IsSuccess: false, Results.Count: > 0 } aggregateResult
+ => aggregateResult.Results.First(i => !i.IsSuccess).ToMinimalApiResult(useProblemDetails),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.NotFound),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when !useProblemDetails
+ => HttpResults.NotFound(),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when !useProblemDetails
+ => HttpResults.StatusCode((int) HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.Conflict),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when !useProblemDetails
+ => HttpResults.Conflict(),
+ ValidationFailedResult validationFailed when useProblemDetails
+ => HttpResults.ValidationProblem(errors: validationFailed.Errors.CreateErrorDictionary(), title: result.Message),
+ ValidationFailedResult validationFailed when !useProblemDetails
+ => HttpResults.BadRequest(validationFailed.Errors.ToModelState()),
+ UnauthorizedResult when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.Forbidden),
+ UnauthorizedResult when !useProblemDetails
+ => HttpResults.Forbid(),
+ _ => throw new ArgumentOutOfRangeException(nameof(result))
+ };
+
+ ///
+ /// Converts a into an appropriate to be used in a minimal API context.
+ ///
+ /// The instance to be converted.
+ ///
+ /// An optional function to map the value of a successful result into a user-defined .
+ /// If not provided, successful results will default to an HTTP 200 response with the value serialized as the body.
+ ///
+ /// Whether to use a RFC7807 problem details body for a failure response. The default is true.
+ /// The type of the result's value.
+ ///
+ /// An that represents the appropriate response:
+ ///
+ /// response for a if is not provided.
+ /// The result of if provided and the result is a .
+ /// with RFC7807 for any non-successful result if is true.
+ /// for a with a reason of if is false.
+ /// with status code 412 for a with a reason of if is false.
+ /// for a with a reason of if is false.
+ /// with model state populated for a if is false.
+ /// for an if is false.
+ ///
+ ///
+ ///
+ /// Thrown when the does not match any known result types.
+ ///
+ public static IResult ToMinimalApiResult(this Result result, Func? successMap = null, bool useProblemDetails = true)
+ => result switch
+ {
+ SuccessResult success when successMap != null
+ => successMap(success.Value),
+ SuccessResult success
+ => HttpResults.Ok(new HypermediaResponse(success.Value)),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.NotFound),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when !useProblemDetails
+ => HttpResults.NotFound(),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when !useProblemDetails
+ => HttpResults.StatusCode((int)HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.Conflict),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when !useProblemDetails
+ => HttpResults.Conflict(),
+ ValidationFailedResult validationFailed when useProblemDetails
+ => HttpResults.ValidationProblem(errors: validationFailed.Errors.CreateErrorDictionary(), title: result.Message),
+ ValidationFailedResult validationFailed when !useProblemDetails
+ => HttpResults.BadRequest(validationFailed.Errors.ToModelState()),
+ UnauthorizedResult when useProblemDetails
+ => result.ToProblemHttpResult(HttpStatusCode.Forbidden),
+ UnauthorizedResult when !useProblemDetails
+ => HttpResults.Forbid(),
+ _ => throw new ArgumentOutOfRangeException(nameof(result)),
+ };
+
+ ///
+ /// Converts a into an containing RFC7807 .
+ ///
+ /// The to be converted.
+ /// The HTTP status code to be set in the .
+ /// A containing the .
+ ///
+ /// This is primarily an internal API, intended to be used from or .
+ /// However, it might have some desired use cases where direct usage is appropriate, so it is made public.
+ ///
+ public static IResult ToProblemHttpResult(this Result result, HttpStatusCode statusCode)
+ => HttpResults.Problem(title: result.Message, statusCode: (int)statusCode);
+}
diff --git a/src/F23.Kernel.AspNetCore/MvcResultExtensions.cs b/src/F23.Kernel.AspNetCore/MvcResultExtensions.cs
new file mode 100644
index 0000000..adc8010
--- /dev/null
+++ b/src/F23.Kernel.AspNetCore/MvcResultExtensions.cs
@@ -0,0 +1,157 @@
+using System.Net;
+using F23.Hateoas;
+using F23.Kernel.Results;
+using Microsoft.AspNetCore.Mvc;
+using UnauthorizedResult = F23.Kernel.Results.UnauthorizedResult;
+
+namespace F23.Kernel.AspNetCore;
+
+///
+/// Provides extension methods for converting objects to ASP.NET Core MVC objects.
+///
+public static class MvcResultExtensions
+{
+ ///
+ /// Converts a into an appropriate
+ /// that represents the result to be sent in an HTTP response.
+ ///
+ /// The to be converted.
+ /// Whether to use a RFC7807 problem details body for a failure response. The default is true.
+ ///
+ /// An representing the HTTP response:
+ ///
+ /// for .
+ /// with for any non-successful result if is true.
+ /// for a indicating if is false.
+ /// with HTTP status code 412 for a indicating if is false.
+ /// for a indicating if is false.
+ /// with model state populated for a if is false.
+ /// in case of an if is false.
+ ///
+ ///
+ ///
+ /// Thrown when the does not match any known result types.
+ ///
+ public static IActionResult ToActionResult(this Result result, bool useProblemDetails = true)
+ => result switch
+ {
+ SuccessResult
+ => new NoContentResult(),
+ AggregateResult { IsSuccess: true }
+ => new NoContentResult(),
+ AggregateResult { IsSuccess: false, Results.Count: > 0 } aggregateResult
+ => aggregateResult.Results.First(i => !i.IsSuccess).ToActionResult(useProblemDetails),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.NotFound),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when !useProblemDetails
+ => new NotFoundResult(),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when !useProblemDetails
+ => new StatusCodeResult((int) HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.Conflict),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when !useProblemDetails
+ => new ConflictResult(),
+ ValidationFailedResult validationFailed when useProblemDetails
+ => new ObjectResult(new ValidationProblemDetails(validationFailed.Errors.ToModelState())
+ {
+ Title = result.Message,
+ Status = (int) HttpStatusCode.BadRequest,
+ })
+ {
+ StatusCode = (int) HttpStatusCode.BadRequest,
+ },
+ ValidationFailedResult validationFailed when !useProblemDetails
+ => new BadRequestObjectResult(validationFailed.Errors.ToModelState()),
+ UnauthorizedResult when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.Forbidden),
+ UnauthorizedResult when !useProblemDetails
+ => new ForbidResult(),
+ _ => throw new ArgumentOutOfRangeException(nameof(result))
+ };
+
+ ///
+ /// Converts a into an appropriate
+ /// that represents the result to be sent in an HTTP response.
+ ///
+ /// The type of the value contained in the result, if successful.
+ /// The result instance to convert.
+ ///
+ /// An optional function to map a successful result to a custom .
+ /// If not provided, a default mapping is applied.
+ ///
+ /// Whether to use a RFC7807 problem details body for a failure response. The default is true.
+ ///
+ /// An representing the HTTP response:
+ ///
+ /// The result of , if specified, for a .
+ /// for a , when is not specified.
+ /// with for any non-successful result if is true.
+ /// for a indicating if is false.
+ /// with HTTP status code 412 for a indicating if is false.
+ /// for a indicating if is false.
+ /// with model state populated for a if is false.
+ /// in case of an if is false.
+ ///
+ ///
+ ///
+ /// Thrown when the does not match any known result types.
+ ///
+ public static IActionResult ToActionResult(this Result result, Func? successMap = null, bool useProblemDetails = true)
+ => result switch
+ {
+ SuccessResult success when successMap != null
+ => successMap(success.Value),
+ SuccessResult success
+ => new OkObjectResult(new HypermediaResponse(success.Value)),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.NotFound),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } when !useProblemDetails
+ => new NotFoundResult(),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } when !useProblemDetails
+ => new StatusCodeResult((int) HttpStatusCode.PreconditionFailed),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.Conflict),
+ PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } when !useProblemDetails
+ => new ConflictResult(),
+ ValidationFailedResult validationFailed when useProblemDetails
+ => new ObjectResult(new ValidationProblemDetails(validationFailed.Errors.ToModelState())
+ {
+ Title = result.Message,
+ Status = (int) HttpStatusCode.BadRequest,
+ })
+ {
+ StatusCode = (int) HttpStatusCode.BadRequest,
+ },
+ ValidationFailedResult validationFailed when !useProblemDetails
+ => new BadRequestObjectResult(validationFailed.Errors.ToModelState()),
+ UnauthorizedResult when useProblemDetails
+ => result.ToProblemDetailsResult(HttpStatusCode.Forbidden),
+ UnauthorizedResult when !useProblemDetails
+ => new ForbidResult(),
+ _ => throw new ArgumentOutOfRangeException(nameof(result))
+ };
+
+ ///
+ /// Converts a into a containing .
+ ///
+ /// The to be converted.
+ /// The HTTP status code to be set in the .
+ /// A containing the .
+ ///
+ /// This is primarily an internal API, intended to be used from or .
+ /// However, it might have some desired use cases where direct usage is appropriate, so it is made public.
+ ///
+ public static IActionResult ToProblemDetailsResult(this Result result, HttpStatusCode statusCode)
+ => new ObjectResult(new ProblemDetails
+ {
+ Title = result.Message,
+ Status = (int)statusCode,
+ })
+ {
+ StatusCode = (int)statusCode,
+ };
+}
diff --git a/src/F23.Kernel.AspNetCore/ResultExtensions.cs b/src/F23.Kernel.AspNetCore/ResultExtensions.cs
deleted file mode 100644
index a3ae881..0000000
--- a/src/F23.Kernel.AspNetCore/ResultExtensions.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using System.Net;
-using F23.Hateoas;
-using F23.Kernel.Results;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.HttpResults;
-using Microsoft.AspNetCore.Mvc;
-using UnauthorizedResult = Microsoft.AspNetCore.Mvc.UnauthorizedResult;
-
-namespace F23.Kernel.AspNetCore;
-
-///
-/// Provides extension methods for converting objects to objects.
-///
-public static class ResultExtensions
-{
- ///
- /// Converts a into an appropriate
- /// that represents the result to be sent in an HTTP response.
- ///
- /// The to be converted.
- ///
- /// An representing the HTTP response:
- ///
- /// A for successful results.
- /// A for a indicating .
- /// A with HTTP status code 412 for a indicating .
- /// A for a indicating .
- /// A with model state populated for a .
- /// An in case of an .
- ///
- ///
- ///
- /// Thrown when the does not match any known result types.
- ///
- public static IActionResult ToActionResult(this Result result)
- => result switch
- {
- SuccessResult => new NoContentResult(),
- AggregateResult { IsSuccess: true } => new NoContentResult(),
- AggregateResult { IsSuccess: false, Results.Count: > 0 } aggregateResult => aggregateResult.Results.First(i => !i.IsSuccess).ToActionResult(),
- PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } => new NotFoundResult(),
- PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } => new StatusCodeResult((int) HttpStatusCode.PreconditionFailed),
- PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } => new ConflictResult(),
- ValidationFailedResult validationFailed => new BadRequestObjectResult(validationFailed.Errors.ToModelState()),
- F23.Kernel.Results.UnauthorizedResult => new UnauthorizedResult(),
- _ => throw new ArgumentOutOfRangeException(nameof(result))
- };
-
- ///
- /// Converts a into an appropriate to be used in a minimal API context.
- ///
- /// The to be converted.
- ///
- /// An that represents the appropriate response:
- /// - An for a .
- /// - A for a with a reason of .
- /// - A with status code 412 for a with a reason of .
- /// - A for a with a reason of .
- /// - A with model state populated for a .
- /// - An for an .
- ///
- ///
- /// Thrown when the does not match any known result types.
- ///
- public static IResult ToMinimalApiResult(this Result result)
- => result switch
- {
- SuccessResult => Microsoft.AspNetCore.Http.Results.NoContent(),
- AggregateResult { IsSuccess: true } => Microsoft.AspNetCore.Http.Results.NoContent(),
- AggregateResult { IsSuccess: false, Results.Count: > 0 } aggregateResult =>
- aggregateResult.Results.First(i => !i.IsSuccess).ToMinimalApiResult(),
- PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } =>
- Microsoft.AspNetCore.Http.Results.NotFound(),
- PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } =>
- Microsoft.AspNetCore.Http.Results.StatusCode((int) HttpStatusCode.PreconditionFailed),
- PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } =>
- Microsoft.AspNetCore.Http.Results.Conflict(),
- ValidationFailedResult validationFailed =>
- Microsoft.AspNetCore.Http.Results.BadRequest(validationFailed.Errors.ToModelState()),
- F23.Kernel.Results.UnauthorizedResult => Microsoft.AspNetCore.Http.Results.Unauthorized(),
- _ => throw new ArgumentOutOfRangeException(nameof(result))
- };
-
- ///
- /// Converts a into an appropriate
- /// that represents the result to be sent in an HTTP response.
- ///
- /// The type of the value contained in the result, if successful.
- /// The result instance to convert.
- ///
- /// An optional function to map a successful result to a custom .
- /// If not provided, a default mapping is applied.
- ///
- ///
- /// An representing the HTTP response:
- ///
- /// The result of , if specified, for a .
- /// An for a , when is not specified.
- /// A for a indicating .
- /// A with HTTP status code 412 for a indicating .
- /// A for a indicating .
- /// A with model state populated for a .
- /// An in case of an .
- ///
- ///
- ///
- /// Thrown when the does not match any known result types.
- ///
- public static IActionResult ToActionResult(this Result result, Func? successMap = null)
- => result switch
- {
- SuccessResult success when successMap != null => successMap(success.Value),
- SuccessResult success => new OkObjectResult(new HypermediaResponse(success.Value)),
- PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } => new NotFoundResult(),
- PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } => new StatusCodeResult((int) HttpStatusCode.PreconditionFailed),
- PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } => new ConflictResult(),
- ValidationFailedResult validationFailed => new BadRequestObjectResult(validationFailed.Errors.ToModelState()),
- UnauthorizedResult => new UnauthorizedResult(),
- _ => throw new ArgumentOutOfRangeException(nameof(result))
- };
-
- ///
- /// Converts a into an appropriate to be used in a minimal API context.
- ///
- /// The instance to be converted.
- ///
- /// An optional function to map the value of a successful result into a user-defined .
- /// If not provided, successful results will default to an HTTP 200 response with the value serialized as the body.
- ///
- /// The type of the result's value.
- ///
- /// An that represents the appropriate response:
- /// - An HTTP 200 (OK) response for a if is not provided.
- /// - The result of if provided and the result is a .
- /// - An HTTP 404 (NotFound) response for a with a reason of .
- /// - An HTTP 412 (PreconditionFailed) response for a with a reason of .
- /// - An HTTP 409 (Conflict) response for a with a reason of .
- /// - An HTTP 400 (BadRequest) response with model state populated for a .
- /// - An HTTP 401 (Unauthorized) response for an .
- ///
- ///
- /// Thrown when the does not match any known result types.
- ///
- public static IResult ToMinimalApiResult(this Result result, Func? successMap = null)
- => result switch
- {
- SuccessResult success when successMap != null => successMap(success.Value),
- SuccessResult success => Microsoft.AspNetCore.Http.Results.Ok(new HypermediaResponse(success.Value)),
- PreconditionFailedResult { Reason: PreconditionFailedReason.NotFound } =>
- Microsoft.AspNetCore.Http.Results.NotFound(),
- PreconditionFailedResult { Reason: PreconditionFailedReason.ConcurrencyMismatch } =>
- Microsoft.AspNetCore.Http.Results.StatusCode((int)HttpStatusCode.PreconditionFailed),
- PreconditionFailedResult { Reason: PreconditionFailedReason.Conflict } =>
- Microsoft.AspNetCore.Http.Results.Conflict(),
- ValidationFailedResult validationFailed =>
- Microsoft.AspNetCore.Http.Results.BadRequest(validationFailed.Errors.ToModelState()),
- UnauthorizedResult => Microsoft.AspNetCore.Http.Results.Unauthorized(),
- _ => throw new ArgumentOutOfRangeException(nameof(result)),
- };
-}
diff --git a/src/F23.Kernel.Examples.AspNetCore/Core/ResultsEndpoints.cs b/src/F23.Kernel.Examples.AspNetCore/Core/ResultsEndpoints.cs
new file mode 100644
index 0000000..57d8c44
--- /dev/null
+++ b/src/F23.Kernel.Examples.AspNetCore/Core/ResultsEndpoints.cs
@@ -0,0 +1,117 @@
+using F23.Kernel;
+using F23.Kernel.AspNetCore;
+using F23.Kernel.Results;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Routing;
+
+namespace F23.Kernel.Examples.AspNetCore.Core;
+
+///
+/// Minimal API endpoints demonstrating the different types of results available in F23.Kernel.
+///
+public static class ResultsEndpoints
+{
+ ///
+ /// Maps minimal API endpoints for demonstrating result types.
+ ///
+ /// The web application builder.
+ public static void MapResultsEndpoints(this WebApplication app)
+ {
+ var group = app.MapGroup("/minimal-apis/results")
+ .WithTags("Results - Minimal APIs")
+ .WithOpenApi();
+
+ group.MapGet("/success-no-value", SuccessNoValue)
+ .WithName("MinimalApiSuccessNoValue")
+ .WithSummary("Demonstrates a successful result with no value")
+ .WithDescription("Returns 204 No Content");
+
+ group.MapGet("/success-with-value", SuccessWithValue)
+ .WithName("MinimalApiSuccessWithValue")
+ .WithSummary("Demonstrates a successful result with a value")
+ .WithDescription("Returns 200 OK with the value in the response body");
+
+ group.MapGet("/validation-failed", ValidationFailed)
+ .WithName("MinimalApiValidationFailed")
+ .WithSummary("Demonstrates a validation failed result")
+ .WithDescription("Returns 400 Bad Request with validation errors");
+
+ group.MapGet("/unauthorized", Unauthorized)
+ .WithName("MinimalApiUnauthorized")
+ .WithSummary("Demonstrates an unauthorized result")
+ .WithDescription("Returns 403 Forbidden");
+
+ group.MapGet("/not-found", NotFound)
+ .WithName("MinimalApiNotFound")
+ .WithSummary("Demonstrates a precondition failed result (not found)")
+ .WithDescription("Returns 404 Not Found");
+
+ group.MapGet("/concurrency-mismatch", ConcurrencyMismatch)
+ .WithName("MinimalApiConcurrencyMismatch")
+ .WithSummary("Demonstrates a precondition failed result (concurrency mismatch)")
+ .WithDescription("Returns 412 Precondition Failed");
+
+ group.MapGet("/conflict", Conflict)
+ .WithName("MinimalApiConflict")
+ .WithSummary("Demonstrates a precondition failed result (conflict)")
+ .WithDescription("Returns 409 Conflict");
+ }
+
+ private static IResult SuccessNoValue()
+ {
+ var result = Result.Success();
+ return result.ToMinimalApiResult();
+ }
+
+ private static IResult SuccessWithValue()
+ {
+ var data = new { message = "Operation completed successfully", timestamp = DateTime.UtcNow };
+ var result = Result