CSV Import
Derive your request type from CsvRequest<TRow>. After binding, request.Rows contains the parsed rows as IReadOnlyList<TRow>.
Minimal API requires BindAsync to be declared as a non-generic static method on the concrete type, so it cannot be provided by the base class. Declare it in the derived class and delegate to BindCsvAsync<T>:
public sealed class UserImportRow{ [Name("name")] public string Name { get; init; } = string.Empty; [Name("email")] public string Email { get; init; } = string.Empty; [Name("role")] public string Role { get; init; } = string.Empty;}
public sealed class ImportUsersRequest : CsvRequest<UserImportRow>{ public static ValueTask<ImportUsersRequest> BindAsync(HttpContext context) => BindCsvAsync<ImportUsersRequest>(context);}
public sealed class ImportUsersEndpoint : IEndpoint<ImportUsersRequest, Response<EmptyResponse>>{ public void Configure(IEndpointConfiguration config) { config.Post("/users/import") .AddFilter<CsvBindingExceptionFilter>() .Summary("Import users from CSV"); }
public Task<Response<EmptyResponse>> HandleAsync( ImportUsersRequest request, CancellationToken cancel) { foreach (var row in request.Rows) { /* persist row */ } return Task.FromResult(Response.NoContent); }}Both text/csv direct body and multipart/form-data file uploads are supported automatically.
For per-row validation, see Row Validation. For custom column mapping, see Class Map.