'Custom Result in Net 6 Minimal API

In ASP.NET Core 5 I had a custom Action Result as follows:

public class ErrorResult : ActionResult {

  private readonly IList<Error> _errors;

  public ErrorResult(IList<Error> errors) {
    _errors = errors;
  }

  public override async Task ExecuteResultAsync(ActionContext context) {

    // Code that creates Response

    await result.ExecuteResultAsync(context);

  }

}

Then on a Controller action I would have:

return new ErrorResult(errors);

How to do something similar in NET 6 Minimal APIs?

I have been looking at it and I think I should implement IResult.

But I am not sure if that is the solution or how to do it.



Solution 1:[1]

If you still want to use MVC (Model-View-Controller), you still can use Custom ActionResult.

If you just want to use Minimal APIs to do the response, then you have to implement IResult, Task<IResult> or ValueTask<IResult>.

app.MapGet("/hello", () => Results.Ok(new { Message = "Hello World" }));

The following example uses the built-in result types to customize the response:

app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
         await db.Todos.FindAsync(id) 
         is Todo todo
         ? Results.Ok(todo) 
         : Results.NotFound())
   .Produces<Todo>(200)
   .Produces(404);

You can find more IResult implementation samples here: https://github.com/dotnet/aspnetcore/tree/main/src/Http/Http.Results/src

Link: Minimal APIs overview | Microsoft Docs

Solution 2:[2]

I have recently been playing around with minimal APIs and and working on global exception handling. Here is what I have come up with so far.

  1. Create a class implementation of IResult
  • Create a constructor which will take an argument of the details you want going into your IResult response. APIErrorDetails is a custom implementation of mine similar to what you'd see in ProblemDetails in MVC. Method implementation is open to whatever your requirements are.
public class ExceptionAllResult : IResult
{
    private readonly ApiErrorDetails _details;

    public ExceptionAllResult(ApiErrorDetails details)
    {
        _details = details;
    }
    public async Task ExecuteAsync(HttpContext httpContext)
    {
        var jsonDetails = JsonSerializer.Serialize(_details);
        httpContext.Response.ContentType = MediaTypeNames.Application.Json;
        httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(jsonDetails);
        httpContext.Response.StatusCode = _details.StatusCode;
        await httpContext.Response.WriteAsync(jsonDetails);
    }
}

  1. Return result in your exception handling middleware in your Program.cs file.

app.UseExceptionHandler(
            x =>
            {
                
                x.Run(
                    async context =>
                    {
                        // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-6.0
                        var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>();

                        // Whatever you want for null handling
                        if (exceptionFeature is null) throw new Exception(); 

                        // My result service for creating my API details from the HTTP context and exception. This returns the Result class seen in the code snippet above
                        var result = resultService.GetErrorResponse(exceptionFeature.Error, context);
                        await result.ExecuteAsync(context); // returns the custom result
                    });
            }
        );

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 DharmanBot