I have defined Carter
modules in my app, but none of them trigger breakpoints during startup and no routes are registered. What is the issue?
using Carter;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OneOf;
using MyApp.API.Data;
using MyApp.API.Data.Models;
using MyApp.API.Models;
namespace MyApp.API.Features.Sheets;
public static class GetSheet
{
public record Command(string SheetId) : IRequest<OneOf<Sheet, NotFound>>;
public class Handler : IRequestHandler<Command, OneOf<Sheet, NotFound>>
{
private readonly ApplicationDbContext context;
public Handler(ApplicationDbContext context)
{
this.context = context;
}
public async Task<OneOf<Sheet, NotFound>> Handle(Command request, CancellationToken cancellationToken)
{
var sheetCells = await context.SheetCells
.Where(x => x.SheetId == request.SheetId)
.ToListAsync(cancellationToken: cancellationToken);
if (sheetCells == null)
{
return new NotFound();
}
var sheet = new Sheet(sheetCells);
return sheet;
}
}
public class Endpoint : ICarterModule
{
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("/api/v1/{sheetId:string}",
async ([FromBody]Command command, IMediator mediator) =>
{
var result = await mediator.Send(command);
return result.Match(
cell => Results.Ok(cell),
_ => Results.NotFound());
});
}
}
}
Program.cs
using Microsoft.EntityFrameworkCore;
using MyApp.API.Data;
using Carter;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ApplicationDbContext>(x =>
x.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
builder.Services.AddMediatR(c => c.RegisterServicesFromAssemblyContaining(typeof(Program)));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCarter();
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.MapCarter();
app.Run();
Nested classes have IsPublic
property set to false and IsNestedPublic
set to true. Carter`s package sources don't take this into account and register modules improperly.
User needs either make classes not nested, or register each module individually
var catalog = new DependencyContextAssemblyCatalog();
var types = catalog.GetAssemblies().SelectMany(x => x.GetTypes());
var modules = types
.Where(t =>
!t.IsAbstract &&
typeof(ICarterModule).IsAssignableFrom(t)
&& (t.IsPublic || t.IsNestedPublic)
).ToList();
builder.Services.AddCarter(configurator: c =>
{
c.WithModules(modules.ToArray());
});