FastSharp.Modules
1.0.0-beta.12
See the version list below for details.
dotnet add package FastSharp.Modules --version 1.0.0-beta.12
NuGet\Install-Package FastSharp.Modules -Version 1.0.0-beta.12
<PackageReference Include="FastSharp.Modules" Version="1.0.0-beta.12" />
<PackageVersion Include="FastSharp.Modules" Version="1.0.0-beta.12" />
<PackageReference Include="FastSharp.Modules" />
paket add FastSharp.Modules --version 1.0.0-beta.12
#r "nuget: FastSharp.Modules, 1.0.0-beta.12"
#:package FastSharp.Modules@1.0.0-beta.12
#addin nuget:?package=FastSharp.Modules&version=1.0.0-beta.12&prerelease
#tool nuget:?package=FastSharp.Modules&version=1.0.0-beta.12&prerelease
FastSharp
FastSharp is a lightweight library for building APIs in C# and ASP.NET Core (Minimal APIs).
It organizes your application using Modules (contracts) and Endpoints (implementations), so you can structure your API by domain instead of technical layers.
You can also generate full CRUD endpoints in one line — but that's optional.
Why FastSharp?
Minimal APIs are flexible, but as your project grows they often become:
- Repetitive
- Unstructured
- Hard to scale
FastSharp solves this with a simple model:
- Modules → define the route group and API contract
- Endpoints (
IEndpoint) → implement behavior as independent classes AddCRUD→ optional shortcut for standard REST operations
// Inside a module constructor, one call maps 5 REST endpoints backed by EF Core
AddCRUD<Product, int>("/products");
No controllers. No repetition. Just modules organized by domain.
Installation
dotnet add package FastSharp.Modules
dotnet add package FastSharp.Models
FastSharp.Modulesis the core.FastSharp.Modelscontains only the model interfaces — add it to projects that don't need the full core.
⚠️ FastSharp is currently in beta. APIs may change between versions.
Quick Start
The minimum setup is four code files (steps 2–5 below) plus package restore. This example uses an in-memory database so you can run it immediately.
🧠 Need help choosing a project structure? See How to FastSharp for the recommended ways to organize a FastSharp application as it grows.
1. Install the dependencies
dotnet add package FastSharp.Modules
dotnet add package FastSharp.Models
dotnet add package Microsoft.EntityFrameworkCore.InMemory
2. Your model
// Models/Product.cs
using FastSharp.Models;
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}
3. Your DbContext
// Data/ApiDbContext.cs
using Microsoft.EntityFrameworkCore;
public class ApiDbContext : DbContext
{
public ApiDbContext(DbContextOptions<ApiDbContext> options) : base(options) { }
public DbSet<Product> Products => Set<Product>();
}
4. Your module
// Modules/Products/ProductsModule.cs
using yourproject.Context;
using yourproject.Context.Models;
using yourproject.Modules.Products.Dtos;
using yourproject.Modules.Products.Endpoints;
using FastSharp.Modules.Core;
using FastSharp.Modules.Configuration;
namespace yourproject.Modules.Products;
public class ProductsModule : Module<ApiDbContext>
{
public ProductsModule()
{
ConfigureModule("/api", opt => opt
.WithTags("Products")
.WithDescription("Endpoints of products module")
);
// Use a manual Id selector for entities that do not implement IModel<int>.
AddCRUD<Product, int>("/products/alternative", p => p.Id, crud =>
{
crud.DisableEndpoint(GenericEndpoint.GetList);
crud.GetList<ProductDto>((endpoint) => endpoint
.WithDescription("Retrieves a list of products (use ?page and ?pageSize for pagination)")
.WithTags("GetList")
);
crud.Create<ProductRequest, ProductDto>((endpoint) => endpoint
.WithDescription("Creates a new product")
.WithTags("Create")
);
});
// Declare custom endpoints for this module (implemented via IEndpoint)
//Include<CheckProductStock>();
}
}
5. Custom Endpoint
public class CheckProductStock : IEndpoint
{
public void Map(RouteGroupBuilder app)
{
app.MapGet("/{id}/stock", async ([FromRoute] int id) =>
{
return Results.Ok($"Checking stock for product {id}");
})
.WithTags("Stock");
}
}
6. Program.cs
using FastSharp.Modules;
using FastSharp.Modules.Core;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ApiDbContext>(opt =>
opt.UseInMemoryDatabase("fastsharp-demo"));
builder.Services.AddFastSharpEndpoints();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapFastSharpEndpoints();
app.MapOpenApi();
app.Run();
Run the project and open /openapi/v1.json — you'll see the generated CRUD endpoints for /api/products/alternative plus any custom endpoints you include in the module.
What does AddCRUD generate?
| Method | Route | Description |
|---|---|---|
GET |
/api/products/alternative |
List, capped at the default max page size (add ?page=1&pageSize=10 for paginated results) |
GET |
/api/products/alternative/{id} |
Get by ID |
POST |
/api/products/alternative |
Create |
PUT |
/api/products/alternative/{id} |
Update |
DELETE |
/api/products/alternative/{id} |
Delete |
Paths use the module prefix from ConfigureModule (these examples use /api) plus the AddCRUD route prefix (here, /products/alternative). Convention: pass a leading slash on every path you own (ConfigureModule, AddCRUD, and custom MapGet / MapPost templates) so routes stay consistent across modules and the library.
🧠 Usage Modes
FastSharp can be used in different ways depending on your needs:
- CRUD-only (fastest)
AddCRUD<Product, int>("/products");
- CRUD + custom endpoints
AddCRUD<Product, int>("/products");
Include<CheckProductStock>();
- Custom endpoints only (no persistence required) You can create modules without relying on EF Core and define only IEndpoint implementations.
🆚 How FastSharp differs from FastEndpoints
FastEndpoints focuses on building endpoints with a structured, opinionated approach.
FastSharp focuses on organizing APIs by domain:
- Modules (domains) as first-class units
- Endpoints (
IEndpoint) as implementations inside a module - Optional CRUD generation for common cases
- Closer to Minimal APIs, with less framework overhead
When to choose each:
- Choose FastEndpoints if you want a more opinionated endpoint-centric framework with built-in pipeline features.
- Choose FastSharp if you prefer explicit modular architecture with lightweight abstractions and domain-oriented organization.
Configuration
Disable specific endpoints
AddCRUD<Product, int>("/products", crud =>
{
crud.DisableEndpoint(GenericEndpoint.GetList);
});
Use DTOs
AddCRUD<Product, int>("/products", crud =>
{
crud.Update<ProductDto>();
// Or apply DTOs to all endpoints:
// crud.ConfigureAll<ProductDto>();
});
Add metadata for OpenAPI
AddCRUD<Product, int>("/products", crud =>
{
crud.Get(endpoint =>
endpoint.WithDescription("Get a product by its unique identifier"));
});
Validate custom endpoint requests with FluentValidation
Define your validator and apply WithValidation<T>() to the route handler.
using FastSharp.Modules.Core;
using FluentValidation;
public record UpdateProductStock(int Id, int Quantity);
public sealed class UpdateProductStockValidator : AbstractValidator<UpdateProductStock>
{
public UpdateProductStockValidator()
{
RuleFor(x => x.Id).GreaterThan(0);
RuleFor(x => x.Quantity).NotEqual(0);
}
}
public sealed class UpdateProductsStock : IEndpoint
{
public void Map(RouteGroupBuilder app)
{
app.MapPost("/products/update-stock", (UpdateProductStock request) => Results.NoContent())
.WithValidation<UpdateProductStock>();
}
}
If no IValidator<T> is registered for the request type, the validation filter does nothing and the endpoint continues normally. Validators in assemblies passed to AddFastSharpEndpoints(...) are registered automatically through FluentValidation assembly scanning. See Validation with FluentValidation.
Add custom endpoints to the same module
public ProductsModule()
{
ConfigureModule("/api", module => module.WithTags("Products"));
AddCRUD<Product, int>("/products");
Include<CheckProductStock>();
}
public class CheckProductStock : IEndpoint
{
public void Map(RouteGroupBuilder app)
{
app.MapGet("/{id}/stock", async ([FromRoute] int id) =>
{
return Results.Ok($"Checking stock for product {id}");
})
.WithTags("Stock");
}
}
Custom IEndpoint types are mapped on the module route group (the ConfigureModule prefix), not nested under each AddCRUD prefix. With /api as the module prefix, MapGet("/{id}/stock", ...) becomes GET /api/{id}/stock, alongside GET /api/products, GET /api/products/{id}, etc. They still share group-level OpenAPI metadata from ConfigureModule.
Module discovery: With no arguments,
AddFastSharpEndpoints()andMapFastSharpEndpoints()scan the calling assembly (typically the project that containsProgram.cs). If your modules live in another class library, pass that assembly explicitly. See Assembly scanning.
OpenAPI UI: The snippet above exposes the OpenAPI document only. For Swagger UI in Development (like the repo sample), add
Swashbuckleor your preferred UI and callMapOpenApi/ UI middleware where appropriate.
Architecture
FastSharp is built on Modular Slices — group your logic by domain, not by technical layers.
YourProject/
└── Modules/
├── Products/
│ ├── ProductsModule.cs
│ ├── CheckProductStock.cs
│ └── ProductDto.cs
└── Orders/
├── OrdersModule.cs
└── OrderDto.cs
Each module is a self-contained unit: its routes, its DTOs, its custom endpoints. At startup, FastSharp registers every concrete IFastModule and IEndpoint type found in the assemblies you pass to AddFastSharpEndpoints / MapFastSharpEndpoints (default: the calling assembly only). There is no manual “register this module” list beyond that scan.
Requirements
- .NET 10 or higher
- Entity Framework Core
- A registered
DbContextin the dependency container - Entities used with the parameterless
AddCRUD<TEntity, TKey>(...)overload must implementIModel<TId>(or use the overload that takes an id selector expression for plain POCOs) - Modules inheriting from
Module<TDbContext>
Docs
- Contributing
- Modular architecture
- Customization
- Validation with FluentValidation
- Assembly scanning
- Roadmap
- How to FastSharp
Minimal APIs, EF Core, and Mapster
FastSharp registers routes using the same building blocks as ASP.NET Core Minimal APIs (MapGet, MapGroup, route handlers, OpenAPI metadata, etc.). You do not need to be an expert to use the built-in CRUD conventions, but anything beyond that (custom IEndpoint handlers, policies, filters, or fine-grained OpenAPI) is easier if you already know how Minimal APIs work.
The generic CRUD endpoints run on Entity Framework Core: they use your DbContext, DbSet<T>, LINQ queries, and SaveChangesAsync under the hood. Understanding EF Core basics (configuring the context, change tracking, relationships, and migrations in real apps) helps when your entities are more than simple tables.
When you use DTOs (ConfigureAll, per-endpoint generic types, etc.), FastSharp uses Mapster to map between entities and DTOs (for example Adapt<T>()). Customizing those mappings (flattening, ignoring members, global settings) follows Mapster’s configuration model.
- Minimal APIs overview — Microsoft Learn
- Entity Framework Core documentation — Microsoft Learn
- Mapster wiki — GitHub
License
Licensed under the Apache License, Version 2.0.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- FastSharp.Models (>= 1.0.0-beta.12)
- FluentValidation (>= 12.0.0 && < 13.0.0)
- FluentValidation.DependencyInjectionExtensions (>= 12.0.0 && < 13.0.0)
- Mapster (>= 10.0.7)
- Microsoft.EntityFrameworkCore (>= 9.0.0 && < 11.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-beta.16 | 79 | 7/28/2026 |
| 1.0.0-beta.12 | 125 | 6/11/2026 |
| 1.0.0-beta.11 | 72 | 5/29/2026 |
| 1.0.0-beta.8 | 73 | 4/14/2026 |
| 1.0.0-beta.7 | 74 | 4/1/2026 |
| 1.0.0-beta.6 | 69 | 3/31/2026 |
| 1.0.0-beta.5 | 66 | 3/31/2026 |
| 1.0.0-beta.4 | 68 | 3/23/2026 |
| 1.0.0-beta.3 | 69 | 3/21/2026 |
| 1.0.0-beta.2 | 79 | 2/21/2026 |
| 1.0.0-alpha.4 | 82 | 2/12/2026 |
| 1.0.0-alpha.1 | 81 | 2/11/2026 |