0

The following method defines my endpoints and worked fine in .Net 6. I am upgrading this app now to .Net 8 before I get to far along since that will be standard in a few months.

public static void DefineEndpoints(IEndpointRouteBuilder app)
{
        
    app.MapPost(BaseRoute, CreateNoteAsync)
        .WithName("CreateNote")
        .Accepts<Note>(ContentType)
        .Produces<Note>(201).Produces<IEnumerable<ValidationFailure>>(400)
        .WithTags(Tag);

    app.MapGet(BaseRoute, GetAllNotesAsync)
        .WithName("GetNotes")
        .Produces<IEnumerable<Note>>(200)
        .WithTags(Tag);

    app.MapGet($"{BaseRoute}/{{symbol}}", GetNotesByTickerAsync)
        .WithName("GetNotesForSymbol")
        .Produces<IEnumerable<Note>>(200)
        .WithTags(Tag);
    app.MapGet($"{BaseRoute}/{{symbol}}/{{date}}", GetNotesForSymbolOnDateAsync)
        .WithName("GetNotesForSymbolByDate")
        .Produces<IEnumerable<Note>>(200)
        .WithTags(Tag);

    app.MapPut($"{BaseRoute}/{{symbol}}/{{date}}", UpdateNoteAsync)
        .WithName("UpdateNote")
        .Accepts<Note>(ContentType)
        .Produces<Note>(200).Produces<IEnumerable<ValidationFailure>>(400)
        .WithTags(Tag);

    app.MapDelete($"{BaseRoute}/{{symbol}}/{{date}}", DeleteNoteAsync)
        .WithName("DeleteNote")
        .Produces(204).Produces(404)
        .WithTags(Tag);
    // rest removed for brevity
}

The error produced is

Severity Code Description Project File Line Suppression State Error CS1929 'IEndpointConventionBuilder' does not contain a definition for 'Accepts' and the best extension method overload 'OpenApiRouteHandlerBuilderExtensions.Accepts(RouteHandlerBuilder, string, params string[])' requires a receiver of type 'Microsoft.AspNetCore.Builder.RouteHandlerBuilder' BATLWebApp.Net8.Api C:\Users\Trader\source\repos\BATLWebApp.Net8\BATLWebApp.Net8.Api\Endpoints\NoteEndpoints.cs 19 Active

I get the same error for the .Produces method as well.

I can see it is telling me that I need to be using the RouteHandlerBuilder but from what I see in the .Net 8 docs, the RouteHandlerBuilder takes an IEnumerable

RouteHandlerBuilder(IEnumerable)

and the OpenApiRouteHandlerBuilderExtensions class needs that builder.

I'm not that versed in using minimal api's and am having trouble refactoring this to work in .Net 8 and am equally unsure the error is pushing me in the right direction. Any api routing experts familiar with .Net 8 methods please help.

UPDATE: Here is a sample of the methods called. They all are async Task.

private static async Task<IResult> CreateNoteAsync(Note note, TableServiceManager tableServiceManager, IValidator<Note> validator)
{
    var validationResult = await validator.ValidateAsync(note);
    if (!validationResult.IsValid)
    {
        return Results.BadRequest(validationResult.Errors);
    }
    var equityNote = MapNoteToEquityNoteEntity(note);

    try
    {
        var created = await tableServiceManager.AddEquityNoteAsync(equityNote);
        Results.Created($"/{BaseRoute}/{note.Ticker}", note);
    }
    catch (Exception ex)
    {
        var errorMessage = $"Error creating note for {note.Ticker} on {note.NoteDate} due to {ex.Message}";
        Log.Error(ex, errorMessage);
        return Results.BadRequest(errorMessage);
    }
    return Results.BadRequest();
}
dinotom
  • 4,990
  • 16
  • 71
  • 139

1 Answers1

1

The class EndpointRouteBuilderExtensions has two methods MapGet :

public static class EndpointRouteBuilderExtensions
{
    public static RouteHandlerBuilder MapGet(
        this IEndpointRouteBuilder endpoints,
        [StringSyntax("Route")] string pattern,
        Delegate handler)
    { ... }

    public static IEndpointConventionBuilder MapGet(
        this IEndpointRouteBuilder endpoints,
        [StringSyntax("Route")] string pattern,
        RequestDelegate requestDelegate)
    { ... }
}

I suspect the method than handle the request (CreateNoteAsync, GetAllNotesAsync, ... ) is of type RequestDelegate, then the compiler choose the MapGet method that return IEndpointConventionBuilder that hasn't Accept method.

You can add explicit cast to force the compiler to choose the correct method MapGet:

app.MapPost(BaseRoute, (Delegate)CreateNoteAsync)
    .WithName("CreateNote")
    .Accepts<Note>(ContentType)
    .Produces<Note>(201).Produces<IEnumerable<ValidationFailure>>(400)
    .WithTags(Tag);
vernou
  • 6,818
  • 5
  • 30
  • 58