ASP.NET Core 9: Using FastEndpoints in ASP.NET Core Applicaitons
In this article, we will understand the use of the FastEndpoints in ASP.NET Core Applicaitons. FastEndpoints is a lightweight REST API development framework built for ASP.NET 8 onwards. It is designed to be a developer-friendly alternative for Minimal APIs as well as MVC Controllers. This helps offering a clean and maintainable structure with minimal boilerplate code.
Importance of FastEndpoints
FastEndpoints follows the REPR design pattern, Request, Endpoint, Response that helps to organize code in a clear and modular way. It is especially suitable for vertical slice architecture, where each feature is self-contained that cuts through all layers of the application stack. In the vertical slice, instead of organizing code by technical layers like controllers, services, repositories, the code is organized by features or use cases.
Following are important advantages of using FastEndpoints:
- Minimal Boilerplate: We can define endpoints without controller and its action method with attributes on them.
- Improved Performance: It matches Minimal APIs in speed and supressed the MVC Controllers in benchmarks.
- Cleaner Codebase: It encourages separation of concerns based on the user stories that helps to reduce the code complexity.
- Use the built-In Features:
- Support the FluentValidation for model validation.
- Provides the JWT authentication and role-based security.
- Has Auto-discovery and registration of endpoints.
- Provides Easy integration with Swagger, Serilog, etc.
- Flexible Dependency Injection: It supports constructor and property injection.
- Endpoint
- The Endpoint class in FastEndpoints is the core building block for defining API routes and their behavior in a clean, feature-focused manner. It is the part of the FastEndpoints library.
- The Endpoint class encapsulates the following:
- The route
- The request model, that represents the input data
- The response model that is for response data
- The handler logic, that represents the logic for the endpoint
- Advantages of using the Endpoint class
- This provides strong typing because we need to explicitly define the request and response model classes
- There are not controllers
- There is built-in support for data validations
- We define separate endpoints for Read and Write and hence this is CQRS friendly.
- This approach provides code-testability.
- This improves readability and maintainability.
- This is suitable for Microservices architecture.
USE [EComm] GO /****** Object: Table [dbo].[ProductInfo] Script Date: 9/9/2025 4:07:58 AM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[ProductInfo]( [ProductId] [varchar](20) NOT NULL, [ProductName] [varchar](100) NOT NULL, [CategoryName] [varchar](100) NOT NULL, [Description] [varchar](200) NOT NULL, [UnitPrice] [int] NOT NULL, [ProductRecordId] [int] IDENTITY(1,1) NOT NULL, PRIMARY KEY CLUSTERED ( [ProductId] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] GO
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Relational
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.Tools
- FastEndpoints
dotnet ef dbcontext scaffold "Data Source=.;Initial Catalog=EComm;User Id=[USER-NAME];Password=[PASSWORD];
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "AppConn": "Data Source=.;Initial Catalog=EComm;Integrated Security=SSPI;TrustServerCertificate=True" } }
public class Request { public ProductInfo? Product { get; set; } public string? ProductId { get; set; } } public class Response { public List<ProductInfo>? Products { get; set; } public ProductInfo? Product { get; set; } public string? Message { get; set; } }
using API_FastEndpoints.Results; using Com.Dal.Models; using FastEndpoints; namespace API_FastEndpoints.EndPoints { public class GetProductsEndpoint :Endpoint<Request, Response> { EcommContext _ctx; public GetProductsEndpoint(EcommContext ctx) { _ctx = ctx; } public override void Configure() { Get("/api/products/{ProductId?}"); AllowAnonymous(); Description(b => b .Produces<Response>() .Produces(404) .WithTags("Products")); } public override async Task HandleAsync(Request req, CancellationToken ct) { if (string.IsNullOrEmpty(req.ProductId)) { var products = _ctx.ProductInfos.ToList(); await HttpContext.Response.SendOkAsync(products, cancellation: ct); return; } var product = _ctx.ProductInfos.Find(req.ProductId); if (product == null) { await HttpContext.Response.SendNotFoundAsync(cancellation: ct); return; } await HttpContext.Response.SendOkAsync(new Response { Product = product }, cancellation: ct); } } }
using API_FastEndpoints.Results; using Com.Dal.Models; using FastEndpoints; namespace API_FastEndpoints.EndPoints { public class CreateProductEndpoint: Endpoint<Request,Response> { EcommContext _ctx; public CreateProductEndpoint(EcommContext ctx) { _ctx = ctx; } public override void Configure() { Post("/api/products"); AllowAnonymous(); } public override async Task HandleAsync(Request req, CancellationToken ct) { try { await _ctx.ProductInfos.AddAsync(req.Product!, ct); await _ctx.SaveChangesAsync(ct); await HttpContext.Response.SendOkAsync(new Response { Product = req.Product, Message = "Product created successfully" }); } catch (Exception ex) { await HttpContext.Response.SendErrorsAsync( new List<FluentValidation.Results.ValidationFailure> { new("Exception", ex.Message) }, 500 ); } } } }
- We need to use the AddFastEndpoints() method in the Service registration of the ASP.NET Core. This is used to perform the following:
- Registers FastEndpoints services into the dependency injection container.
- Scans application assemblies to automatically discover and register endpoint classes.
- Sets up internal middleware, validation, and other FastEndpoints features.
- We need to use the UseFastEndpoints() middleware to perform following:
- This activates FastEndpoints routing, so the endpoint classes can respond to HTTP requests.
- Used to maps endpoints to their respective routes like /api/products.
- Manage request processing, validation, and response formatting.
using System.Text.Json; using System.Text.Json.Serialization; using Com.Dal.Models; using FastEndpoints; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddDbContext<EcommContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("AppConn"))); builder.Services.AddFastEndpoints(); builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options => { options.SerializerOptions.PropertyNamingPolicy = null; options.SerializerOptions.WriteIndented = true; options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi builder.Services.AddOpenApi(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.UseHttpsRedirection(); app.UseFastEndpoints(); app.Run();