Chapter 5: Creating a JSON API with minimal APIs
This chapter introduces building full-featured JSON HTTP APIs with minimal APIs, including endpoint definition, responses, reusable filters, and route groups.
After this chapter you will be able to
- Minimal API endpoint construction. Describe the chapter's endpoint-building topics: routing and automatic URL value extraction, mapping HTTP verbs such as POST and PUT, and defining API handlers in different ways.
- API response and reuse tools. Describe the chapter's tools for producing and organizing API behavior: IResult responses using Results or TypedResults and Problem Details errors, endpoint filters for shared endpoint actions, and route groups for shared prefixes and filters.
- HTTP API data exchange. Explain that an HTTP API exposes multiple URL endpoints over HTTP for clients to retrieve or change server data, typically returning JSON rather than HTML.
- Client-side application flow. Describe how a client-side SPA first loads its application code in the browser and then requests JSON data from the server, parses it, and generates the HTML the user sees. Relate this pattern to mobile applications, which similarly use API data to update their UI.
- API versus server rendering. Justify choosing an HTTP API when client-side or mobile clients need to access the application or when a shared backend can serve multiple clients, and distinguish this from choosing server-rendered Razor Pages when no outside client access is needed and configuring a client-side app is unnecessary. State that APIs can also be added later as needs arise.
- Parameterized route values. Explain how a parameterized minimal API route such as /person/{name} extracts a path value and makes it available as a parameter in the endpoint lambda.
- HTTP verb semantics. Explain that GET is for retrieving data only, while operations that send or change server data should use appropriate verbs such as POST or DELETE. Describe why using the expected HTTP verb semantics makes an API more understandable to its consumers.
- Minimal API verb mapping. Describe how minimal APIs map an HTTP verb to an endpoint by using the corresponding Map* method, such as MapGet() for GET and MapPost() for POST. Distinguish these specific mapping methods from MapMethods() and Map(), which can support arbitrary verbs but are best avoided when they obscure the expected operation semantics.
- Route handler function forms. Describe the different ways to supply a route handler to a minimal API endpoint: a lambda, a Func variable, a static method, an instance method, or a local function. Explain that these forms are functionally identical, so the choice can follow the organization that works best for the application.
- JSON body binding. Explain that a minimal API creates a complex handler parameter, such as a Fruit, by deserializing the request's JSON body before it calls the handler. State that minimal APIs bind only JSON request bodies using System.Text.Json, and that only one object parameter can be bound from the body this way.
- IResult for deliberate responses. Explain why a minimal API endpoint should return an IResult for expected invalid requests or missing resources instead of allowing an exception to produce a 500 response. State that an IResult implementation can customize the HTTP response, including its status code, by executing ExecuteAsync.
- HTTP status code semantics. Explain why an API should return status codes that describe successful outcomes and common request failures, and state the meanings of 200 OK, 201 Created, 204 No Content, 400 Bad Request, and 404 Not Found as presented in this section.
- Results and TypedResults helpers. Describe how Results and TypedResults create IResult responses with common status codes and optional JSON bodies in minimal APIs, and distinguish their return types and practical advantages.
- Problem Details error format. Explain why an HTTP API should use the Problem Details web standard for error responses, especially validation errors. Describe that it supplies a consistent, machine-readable JSON error format instead of requiring clients to parse different custom formats.
- Problem Details result helpers. Distinguish Results.Problem() from Results.ValidationProblem() and state their default HTTP status codes. Describe that both return Problem Details JSON, while ValidationProblem() requires a Dictionary of validation errors.
- Consistent API error responses. Distinguish exceptions from error status-code responses as the two classes of API errors, and explain why both should produce Problem Details JSON for a consistent client-facing API.
- Exception Problem Details configuration. Describe how AddProblemDetails() registers IProblemDetailsService and how UseExceptionHandler() without an error-handling path uses that service to turn caught exceptions into Problem Details responses.
- Status-code Problem Details conversion. Describe how UseStatusCodePages() adds StatusCodePagesMiddleware, which uses IProblemDetailsService to add a Problem Details body to error-status responses that reach it without an existing response body, including automatic unmatched-route 404s.
- Binary data result helpers. Describe how Results.File(), Results.Byte(), and Results.Stream() return a file path, byte array, and Stream respectively to a client. Explain that these helpers can include a content type and a suggested filename.
- Endpoint filter purpose. Explain why endpoint filters are useful in minimal APIs: they extract tangential, cross-cutting work from endpoint handlers so the handlers remain focused on their main task. Give examples from the section, such as validation, logging, authorization, or auditing.
- Endpoint filter pipeline. Describe how AddEndpointFilter() attaches a filter to a MapGet or similar minimal API endpoint and how multiple filters form an endpoint filter pipeline. Explain that each filter receives a context and next parameter, and calling next(context) runs the remaining filters or ultimately the endpoint handler.
- Multiple-filter pipeline execution. Describe how multiple endpoint filters execute around an endpoint handler, including their ordering before the handler and reverse ordering after it returns.
- Filter-pipeline short-circuiting. Explain that a filter can stop the remaining endpoint filter pipeline by returning a result without calling next, so subsequent filters and the endpoint handler do not execute.
- Middleware and filter selection. Distinguish middleware from endpoint filters by scope and available information, and justify choosing middleware for general functionality with no endpoint-specific needs versus filters for endpoint-specific behavior or access to endpoint concepts such as IResult.
- Endpoint filter factory pattern. Explain how AddEndpointFilterFactory() registers a factory method that returns an endpoint filter function. Describe that ASP.NET Core runs the factory while building the application and adds the returned filter to the endpoint’s filter pipeline.
- Parameter-aware filter generation. Describe how a filter factory can inspect an endpoint handler's MethodInfo and parameters to generate a filter suited to that handler. Explain that the example finds a string parameter named id, returns next without adding a filter when no id exists, and otherwise creates a filter using the id parameter's actual position.
- IEndpointFilter class implementation. Describe how to create an endpoint filter by defining a class that implements IEndpointFilter and supplies an InvokeAsync() method with the same signature as the AddEndpointFilter() lambda.
- Route group creation. Describe how to create a route group by calling MapGroup() on a WebApplication with a route prefix, and explain that it returns a RouteGroupBuilder.
- Shared endpoint configuration. Explain that RouteGroupBuilder supports the same Map* endpoint-mapping methods as WebApplication, but automatically prepends the group's prefix to every endpoint route; also describe that AddEndpointFilter() on the group applies the filter to every endpoint in that group.
What it builds on
- Simple pipeline scenario 3: A minimal API application (chapter 4) · The reader has seen a minimal API application as one scenario in a middleware pipeline.
- Defining how requests are handled with middleware and endpoints (chapter 3) · The reader has encountered defining request handling with middleware and endpoints.
- Combining middleware in a pipeline (chapter 4) · The reader has learned that middleware can be combined into a pipeline.
- Handling errors using middleware (chapter 4) · The reader has seen middleware used to handle errors.
- How does an HTTP web request work? (chapter 1) · The basic HTTP request-response interaction between a client and server.
- Understanding the many paradigms of ASP.NET Core (chapter 2) · ASP.NET Core supports different application paradigms.
- When to choose ASP.NET Core (chapter 2) · Framework choices depend on the kind of application being built.
- Handling exceptions in production: ExceptionHandlerMiddleware (chapter 4) · ExceptionHandlerMiddleware catching exceptions and using an error-handling path
Section by section
Introduction
This chapter introduces building full-featured JSON HTTP APIs with minimal APIs, including endpoint definition, responses, reusable filters, and route groups.
- HTTP API purpose and choice: Explain that minimal APIs can build full-featured HTTP API applications that return JSON to clients, and describe that the chapter considers how HTTP APIs differ from server-rendered applications and when to use them.
Why it matters: Choosing an HTTP API rather than a server-rendered app affects how clients consume your application. - Minimal API endpoint construction: Describe the chapter's endpoint-building topics: routing and automatic URL value extraction, mapping HTTP verbs such as POST and PUT, and defining API handlers in different ways.
Why it matters: Endpoints connect incoming URLs and HTTP methods to the code that implements an API operation. - API response and reuse tools: Describe the chapter's tools for producing and organizing API behavior: IResult responses using Results or TypedResults and Problem Details errors, endpoint filters for shared endpoint actions, and route groups for shared prefixes and filters.
Why it matters: These tools make API responses consistent while reducing duplicated code and boilerplate across endpoints.
Key terms: HTTP API, minimal API, JSON, server-rendered application, minimal APIs, routing, URL, POST, PUT, route handlers
5.1 What is an HTTP API, and when should you use one?
This section defines HTTP APIs, shows how SPAs, mobile apps, and services consume them, and explains when an API backend is preferable to server-rendered HTML.
- HTTP API data exchange: Explain that an HTTP API exposes multiple URL endpoints over HTTP for clients to retrieve or change server data, typically returning JSON rather than HTML.
Why it matters: This is the basic server-client model used throughout the minimal API chapters. - Client-side application flow: Describe how a client-side SPA first loads its application code in the browser and then requests JSON data from the server, parses it, and generates the HTML the user sees. Relate this pattern to mobile applications, which similarly use API data to update their UI.
Why it matters: It clarifies why an API can supply data while the client application is responsible for rendering its interface. - API consumer scenarios: Describe the main situations in which an HTTP API is useful: powering a client-side SPA, serving a mobile application, or allowing other backend services to consume an application programmatically.
Why it matters: Recognizing the consumers of an application helps you decide whether its backend needs API endpoints. - API versus server rendering: Justify choosing an HTTP API when client-side or mobile clients need to access the application or when a shared backend can serve multiple clients, and distinguish this from choosing server-rendered Razor Pages when no outside client access is needed and configuring a client-side app is unnecessary. State that APIs can also be added later as needs arise.
Why it matters: The rendering and API choices determine where UI work occurs and whether the application can readily support multiple client types.
Key terms: HTTP API, JSON API, REST API, endpoint, JSON, single-page application, SPA, client-side application, Blazor WebAssembly, client-side SPA
5.2 Defining minimal API endpoints
Introduces the upcoming exploration of minimal API endpoints that handle multiple HTTP verbs and use different endpoint-handler styles.
- Minimal API endpoint roadmap: Describe that this section builds on the basic minimal API endpoints introduced in chapters 3 and 4, then previews handling multiple HTTP verbs and writing endpoint handlers in different ways.
Why it matters: This roadmap connects the earlier simple endpoints to the practical endpoint definitions developed next.
Key terms: minimal API endpoints, HTTP verbs, endpoint handlers
5.2.1 Extracting values from the URL with routing
This subsection shows how parameterized minimal API routes extract a value from a request URL path and provide it to an endpoint lambda.
- Parameterized route values: Explain how a parameterized minimal API route such as /person/{name} extracts a path value and makes it available as a parameter in the endpoint lambda.
Why it matters: Route parameters let a single endpoint respond to requests for different resources or inputs. - Dynamic API paths: Describe why parameterized routes are more useful than fixed paths when an API must vary its response based on a value supplied in the URL.
Why it matters: Dynamic paths allow one API definition to handle requests for many values instead of always returning the same result.
Key terms: parameterized routes, route template, name parameter, lambda function endpoint, request URL’s path, fixed paths, dynamic APIs
5.2.2 Mapping verbs to endpoints
This section explains how minimal API Map* methods associate HTTP verbs with endpoints, why verb semantics matter, and how incorrect verbs are handled and tested.
- HTTP verb semantics: Explain that GET is for retrieving data only, while operations that send or change server data should use appropriate verbs such as POST or DELETE. Describe why using the expected HTTP verb semantics makes an API more understandable to its consumers.
Why it matters: Consistent verb choices communicate what an API operation is intended to do before a client even calls it. - Minimal API verb mapping: Describe how minimal APIs map an HTTP verb to an endpoint by using the corresponding Map* method, such as MapGet() for GET and MapPost() for POST. Distinguish these specific mapping methods from MapMethods() and Map(), which can support arbitrary verbs but are best avoided when they obscure the expected operation semantics.
Why it matters: The mapping method determines which requests can reach an endpoint handler. - Verb mismatch responses and testing: State that a request using the wrong HTTP verb for an otherwise matching endpoint does not run its handler and receives a 405 Method Not Allowed response. Describe why requests other than GET generally need an API testing client, such as Postman, Rider's HTTP Client plugin, or later Swagger UI, rather than ordinary browser navigation.
Why it matters: Recognizing a 405 response and using a suitable client speeds up API testing and troubleshooting.
Key terms: HTTP verb, GET, POST, DELETE, RESTful applications, semantics, MapGet(), MapPost(), MapMethods(), Map()
5.2.3 Defining route handlers with functions
This section shows that minimal API endpoints can use several equivalent handler forms, automatically bind one JSON body object, and should be organized modularly in real applications.
- Route handler function forms: Describe the different ways to supply a route handler to a minimal API endpoint: a lambda, a Func variable, a static method, an instance method, or a local function. Explain that these forms are functionally identical, so the choice can follow the organization that works best for the application.
Why it matters: You can keep endpoint code understandable by choosing a handler form that fits the size and structure of your API. - JSON body binding: Explain that a minimal API creates a complex handler parameter, such as a Fruit, by deserializing the request's JSON body before it calls the handler. State that minimal APIs bind only JSON request bodies using System.Text.Json, and that only one object parameter can be bound from the body this way.
Why it matters: Understanding automatic JSON binding lets an endpoint receive structured client data without manually reading and deserializing the request body. - Modular endpoint organization: Explain that minimal APIs do not require endpoints to remain in a single file, even though simple examples often show them there. Describe extracting endpoints into separate files as the intended way to modularize an application and make it easier to understand.
Why it matters: Modular endpoint organization helps a growing API remain maintainable instead of becoming one large, confusing file.
Key terms: route handler, lambda expression, Func<T, TResult>, static method, instance method, local function, complex types, JSON body, deserializing, System.Text.Json
5.3 Generating responses with IResult
This section introduces IResult as the minimal API return type for producing deliberate HTTP responses, especially error status codes, and contrasts it with other handler return types.
- IResult for deliberate responses: Explain why a minimal API endpoint should return an IResult for expected invalid requests or missing resources instead of allowing an exception to produce a 500 response. State that an IResult implementation can customize the HTTP response, including its status code, by executing ExecuteAsync.
Why it matters: Using IResult lets an API communicate expected client-facing problems such as missing data with an appropriate HTTP response. - Endpoint return type behavior: Describe how minimal API endpoint middleware handles void, string, IResult, and other return types. Include the default 200 responses and distinguish text/plain string output from JSON serialization of other objects.
Why it matters: Knowing the default handling of handler return values makes it clear when an endpoint needs IResult instead of a plain value.
Key terms: IResult, ExecuteAsync, 500 Internal Server Error, 404 Not Found, 400 Bad Request, void, Task, Task<IResult>, POCO, text/plain
5.3.1 Returning status codes with Results and TypedResults
This section shows how minimal API endpoints return meaningful HTTP status-code responses using Results, TypedResults, or, less commonly, HttpResponse directly.
- HTTP status code semantics: Explain why an API should return status codes that describe successful outcomes and common request failures, and state the meanings of 200 OK, 201 Created, 204 No Content, 400 Bad Request, and 404 Not Found as presented in this section.
Why it matters: Meaningful status codes let API clients tell success, invalid requests, and missing entities apart without guessing from a response body. - Results and TypedResults helpers: Describe how Results and TypedResults create IResult responses with common status codes and optional JSON bodies in minimal APIs, and distinguish their return types and practical advantages.
Why it matters: These helpers provide a concise standard way for endpoint handlers to produce HTTP responses that clients, tests, and API documentation can understand. - Manual HttpResponse construction: Describe the alternative of injecting HttpResponse into a minimal API handler and manually setting its status code, content type, and response body, including why this approach is usually unnecessary.
Why it matters: Manual response construction is available for exceptional cases when the standard result helpers do not fit the response you need.
Key terms: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 404 Not Found, Location header, Results, TypedResults, IResult, Ok<T>
5.3.2 Returning useful errors with Problem Details
This section introduces Problem Details as the standard JSON format for consistent API errors and shows how minimal APIs generate it.
- Problem Details error format: Explain why an HTTP API should use the Problem Details web standard for error responses, especially validation errors. Describe that it supplies a consistent, machine-readable JSON error format instead of requiring clients to parse different custom formats.
Why it matters: A consistent standard error format makes an API easier and less confusing for mobile apps and single-page applications to consume. - Problem Details result helpers: Distinguish Results.Problem() from Results.ValidationProblem() and state their default HTTP status codes. Describe that both return Problem Details JSON, while ValidationProblem() requires a Dictionary of validation errors.
Why it matters: Choosing the appropriate helper produces a standard error response with the appropriate status and validation information. - Problem response customization: Describe how ProblemHttpResult supplies status-based default titles and descriptions for Problem Details responses, and explain that additional arguments to Problem() or ValidationProblem() can override them.
Why it matters: Defaults provide useful standardized error information while still allowing an API to give a more specific title or description.
Key terms: Problem Details, machine-readable errors, HTTP APIs, validation errors, Results.Problem(), Results.ValidationProblem(), TypedResults, ProblemHttpResult, Dictionary of validation errors, Problem Details JSON
5.3.3 Converting all your responses to Problem Details
This section shows how to make minimal API error responses consistently use Problem Details JSON for both exceptions and error status codes.
- Consistent API error responses: Distinguish exceptions from error status-code responses as the two classes of API errors, and explain why both should produce Problem Details JSON for a consistent client-facing API.
Why it matters: Clients can handle failures reliably when all error paths use the same response format. - Exception Problem Details configuration: Describe how AddProblemDetails() registers IProblemDetailsService and how UseExceptionHandler() without an error-handling path uses that service to turn caught exceptions into Problem Details responses.
Why it matters: This configuration removes the need for a dedicated error endpoint while standardizing exception responses. - Development exception response selection: Explain that DeveloperExceptionPageMiddleware can return Problem Details in development when IProblemDetailsService is registered and the request does not indicate HTML support; otherwise, an HTML-capable client receives the developer exception page.
Why it matters: The response format in development depends on what the client accepts, so browser-friendly diagnostics do not replace API-friendly JSON automatically. - Status-code Problem Details conversion: Describe how UseStatusCodePages() adds StatusCodePagesMiddleware, which uses IProblemDetailsService to add a Problem Details body to error-status responses that reach it without an existing response body, including automatic unmatched-route 404s.
Why it matters: This catches nonexception failures from endpoints and middleware that application code may not directly control.
Key terms: Problem Details, exceptions, error status code responses, AddProblemDetails(), IProblemDetailsService, UseExceptionHandler(), ExceptionHandlerMiddleware, DeveloperExceptionPageMiddleware, error-handling path, HTML developer exception page
5.3.4 Returning other data types
This section shows how minimal API endpoints return files, binary data, and streams, and when to create responses manually or with a custom IResult.
- Binary data result helpers: Describe how Results.File(), Results.Byte(), and Results.Stream() return a file path, byte array, and Stream respectively to a client. Explain that these helpers can include a content type and a suggested filename.
Why it matters: These helpers let an API deliver downloadable files and other non-JSON data without manually writing the HTTP response. - Range request support: Explain that a client can use the Range header to request only a specified byte range rather than an entire file. State that Results.File() and Results.Byte() can handle these requests automatically when enableRangeProcessing is set to true.
Why it matters: Range processing can reduce bandwidth when clients need only part of a binary file. - Custom response fallback: Describe the fallback when built-in Results helpers do not provide the needed behavior: create the HTTP response manually. Explain that repeated manual response logic can be encapsulated in a custom IResult type.
Why it matters: A custom IResult prevents repeated low-level response-writing code when an application needs a response format or behavior not supplied by built-in helpers.
Key terms: Results.File(), Results.Byte(), Results.Stream(), content type, filename, range requests, Range header, enableRangeProcessing, IResult, custom IResult
5.4 Running common code with endpoint filters
This section introduces endpoint filters as a way to move cross-cutting code such as validation out of minimal API handlers and run it before or after an endpoint.
- Endpoint filter purpose: Explain why endpoint filters are useful in minimal APIs: they extract tangential, cross-cutting work from endpoint handlers so the handlers remain focused on their main task. Give examples from the section, such as validation, logging, authorization, or auditing.
Why it matters: Endpoint filters keep repeated supporting logic from obscuring what each endpoint actually does. - Endpoint filter pipeline: Describe how AddEndpointFilter() attaches a filter to a MapGet or similar minimal API endpoint and how multiple filters form an endpoint filter pipeline. Explain that each filter receives a context and next parameter, and calling next(context) runs the remaining filters or ultimately the endpoint handler.
Why it matters: Understanding the pipeline lets you control whether common code runs around an endpoint or stops its execution early. - Filter validation short-circuiting: Trace how an endpoint filter can validate an endpoint argument by reading it with context.GetArgument<T>() using its zero-based argument position. Explain that the filter returns an IResult when the argument is invalid, but awaits next(context) when it is valid so that the endpoint handler executes.
Why it matters: This pattern allows a filter to reject invalid requests before the endpoint handler performs its normal work.
Key terms: endpoint filters, cross-cutting activities, endpoint handler, validation, logging, authorization, AddEndpointFilter(), endpoint filter pipeline, EndpointFilterInvocationContext, next
5.4.1 Adding multiple filters to an endpoint
This subsection explains how multiple endpoint filters form an ordered, nestable pipeline, can short-circuit later work, and should be used sparingly for genuinely repeated endpoint-specific concerns.
- Multiple-filter pipeline execution: Describe how multiple endpoint filters execute around an endpoint handler, including their ordering before the handler and reverse ordering after it returns.
Why it matters: Understanding the order lets you predict which filter code runs before and after an endpoint handler. - Filter-pipeline short-circuiting: Explain that a filter can stop the remaining endpoint filter pipeline by returning a result without calling next, so subsequent filters and the endpoint handler do not execute.
Why it matters: Short-circuiting enables an endpoint-specific filter to reject a request before unnecessary filters or handler code run. - Selective filter use: Justify using endpoint filters only for duplicated endpoint-specific operations that significantly simplify endpoint code, while keeping application-wide cross-cutting concerns such as logging, authentication, and authorization in middleware.
Why it matters: This guidance prevents a filter-heavy design whose request flow is difficult to follow.
Key terms: endpoint filter pipeline, endpoint handler, AddEndpointFilter, next, short-circuit, next(context), Problem Details, result, cross-cutting concerns, middleware
5.4.2 Filters or middleware: Which should you choose?
This section compares endpoint filters with middleware and gives a specificity-based rule for choosing between them.
- Pipeline behavior parallels: Describe the shared pipeline behavior of middleware and endpoint filters: both can run work before and after later processing, can short-circuit by returning a response, and can address cross-cutting concerns.
Why it matters: Recognizing the shared pipeline shape helps you see why either technique can implement some of the same kinds of behavior. - Middleware and filter selection: Distinguish middleware from endpoint filters by scope and available information, and justify choosing middleware for general functionality with no endpoint-specific needs versus filters for endpoint-specific behavior or access to endpoint concepts such as IResult.
Why it matters: Choosing the right extension point keeps broad application concerns broad and lets endpoint-specific logic target only the requests that need it.
Key terms: middleware pipeline, endpoint filter pipeline, short-circuit, cross-cutting concerns, HttpContext, EndpointMiddleware, IResult, middleware, endpoint filters, exception-handling middleware
5.4.3 Generalizing your endpoint filters
This section shows how endpoint filter factories create endpoint-specific filters that avoid assumptions about a handler’s parameter order.
- Endpoint filter factory pattern: Explain how AddEndpointFilterFactory() registers a factory method that returns an endpoint filter function. Describe that ASP.NET Core runs the factory while building the application and adds the returned filter to the endpoint’s filter pipeline.
Why it matters: A filter factory lets one reusable definition produce filters tailored to individual endpoint handlers. - Parameter-aware filter generation: Describe how a filter factory can inspect an endpoint handler's MethodInfo and parameters to generate a filter suited to that handler. Explain that the example finds a string parameter named id, returns next without adding a filter when no id exists, and otherwise creates a filter using the id parameter's actual position.
Why it matters: Inspecting the handler signature removes brittle assumptions such as requiring id to be the first handler parameter.
Key terms: AddEndpointFilterFactory(), filter factory, filter function, filter pipeline, EndpointFilterFactoryContext, MethodInfo, EndpointMetadata, EndpointFilterInvocationContext, id parameter, next
5.4.4 Implementing the IEndpointFilter interface
This section shows how to implement a minimal API endpoint filter as an IEndpointFilter class and when that approach is preferable to lambda-based filters.
- IEndpointFilter class implementation: Describe how to create an endpoint filter by defining a class that implements IEndpointFilter and supplies an InvokeAsync() method with the same signature as the AddEndpointFilter() lambda.
Why it matters: An interface-based filter avoids the difficulty of writing a compiler-valid lambda signature and provides IDE assistance. - IDE support for filter signatures: Explain that implementing IEndpointFilter provides IntelliSense and autocompletion for the filter method signature, avoiding the potential frustration of constructing a valid AddEndpointFilter() lambda.
Why it matters: IDE guidance makes class-based filters easier to write correctly, especially when a lambda signature is hard to infer. - Filter factory limitation: Distinguish a class-based IEndpointFilter from the filter-factory pattern: no equivalent interface exists for filter factories, so generalized filters using a factory must use the lambda or helper-method approach.
Why it matters: This limitation determines whether a reusable filter design can use an interface class or must retain a lambda-based factory.
Key terms: IEndpointFilter, InvokeAsync(), AddEndpointFilter(), IntelliSense, autocompletion, filter-factory pattern, lambda, helper method
5.5 Organizing your APIs with route groups
This section shows how route groups reduce duplicated route prefixes and endpoint filters when organizing minimal API endpoints.
- Route group creation: Describe how to create a route group by calling MapGroup() on a WebApplication with a route prefix, and explain that it returns a RouteGroupBuilder.
Why it matters: A route group gives related minimal API endpoints one shared place for their common route setup. - Shared endpoint configuration: Explain that RouteGroupBuilder supports the same Map* endpoint-mapping methods as WebApplication, but automatically prepends the group's prefix to every endpoint route; also describe that AddEndpointFilter() on the group applies the filter to every endpoint in that group.
Why it matters: Applying common routing and filters at the group level prevents repeated endpoint configuration and missed filters. - Nested group organization: Describe how route groups can be nested by calling MapGroup() on an existing group, with prefixes applied in order, and explain how this lets only a subgroup of endpoints receive a shared filter.
Why it matters: Nested groups let an API share a broad route prefix while applying extra behavior only where it is needed.
Key terms: MapGroup(), WebApplication, RouteGroupBuilder, route prefix, Map* extension methods, AddEndpointFilter(), endpoint filter, nested groups, prefix
5.6 Summary
This summary recaps how to design minimal HTTP API endpoints, generate appropriate responses, and organize shared endpoint behavior.
Where this is used later
- (chapter intro) (chapter 13) · The minimal API applications that Razor Pages are compared against.
- Extracting values from a request with model binding (chapter 7) · Model binding extracts request values sent by API clients.
- (chapter intro) (chapter 11) · The idea of an HTTP API and its endpoints.
- Generating strongly typed clients with NSwag (chapter 11) · Strongly typed clients are generated for applications that consume an API.
- Authentication for APIs and distributed applications (chapter 25) · API authentication is considered in the context of distributed applications and multiple apps.
- Calling HTTP APIs: The problem with HttpClient (chapter 33) · Remote applications call HTTP APIs using HTTP clients.
- Your first Razor Pages application (chapter 13) · Razor Pages provide the contrasting server-rendered application approach.
- Choosing between web API controllers and minimal APIs (chapter 20) · The reader later chooses between web API controllers and minimal APIs.
Concepts explained in this chapter
- endpoint filterAn endpoint filter is an ASP.NET Core component that runs processing around the execution of an associated endpoint and can alter or short-circuit its result.
- IResultIResult is an ASP.NET Core interface representing the result produced by an HTTP endpoint for an HTTP response.
- Problem DetailsProblem Details is a standardized structured format for representing HTTP error information in a response body, commonly serialized as JSON.
- ResultsResults is an ASP.NET Core static helper type that creates HTTP responses with common status codes and optional JSON bodies.
- TypedResultsTypedResults is an ASP.NET Core static helper type that creates typed HTTP responses with common status codes and optional JSON bodies.
- minimal APIA minimal API endpoint is an addressable operation in a minimal API application that handles a request with minimal surrounding framework structure.
- AddEndpointFilterAddEndpointFilter is an ASP.NET Core endpoint-mapping method that attaches an endpoint filter to an endpoint or route group.
- route groupA route group is a minimal API organization construct that applies a common route prefix and shared endpoint configuration to multiple endpoints.
- pipelineA handler pipeline is an ordered chain of HTTP message handlers that can modify requests and inspect responses around a final transport handler.
- deletionRemove is an Entity Framework Core method that marks an entity for deletion when changes are saved.
- HTTP response codeAn HTTP status code is a three-digit code in an HTTP response that indicates the result of processing the corresponding request.
- 400 bad requestA 400 status code is an HTTP response status indicating that the server could not process the request because of invalid client input.
- HTTP responseHttpResponse is the ASP.NET Core object representing the HTTP response sent to a client, including its status code, headers, content type, and body.
- endpointAn endpoint is an addressable application operation associated with a URL pattern that receives a dispatched request and returns a response.
- MapGroupMapGroup is an ASP.NET Core endpoint-mapping method that creates a route group with a specified route prefix.
- RouteGroupBuilderRouteGroupBuilder is the ASP.NET Core builder type returned for configuring a route group and its shared endpoint conventions.
- single-page applicationA single-page application is a web application that updates its user interface dynamically without full-page navigation for most interactions.
- web serviceAn HTTP API application exposes application functionality through endpoints that communicate using the HTTP protocol.
- EndpointFilterFactoryContextEndpointFilterFactoryContext is the ASP.NET Core context object that provides endpoint details to an endpoint filter factory while the application is being built.
- servlet filterIActionFilter is an ASP.NET Core interface for synchronous MVC filters that run before and after action-method execution.
- AddProblemDetailsAddProblemDetails is an ASP.NET Core service-registration extension method that registers IProblemDetailsService and configures Problem Details generation.
- IProblemDetailsServiceIProblemDetailsService is an ASP.NET Core service interface that generates Problem Details responses for errors.
- StatusCodePagesMiddlewareStatusCodePagesMiddleware is ASP.NET Core middleware that generates or modifies responses for HTTP status codes, including adding a body to error responses that lack one.
- UseStatusCodePagesUseStatusCodePages is an ASP.NET Core application-builder extension method that adds StatusCodePagesMiddleware to the request pipeline.
- error responseAn error status code response is an HTTP response whose status code indicates that the requested operation failed or could not be completed.
- HTTP methodAn HTTP verb is the method token in an HTTP request that indicates the intended operation.
- 405 Method Not AllowedA 405 status code is an HTTP response status indicating that the request method is not supported for the targeted resource.
- HTTP GETGET is an HTTP method for retrieving a resource from a server.
- MapGetMapGet is an ASP.NET Core endpoint-mapping method for associating a URL pattern and handler with HTTP GET requests.
- request messagePOST is an HTTP method used to send data to a server for processing or resource creation.
- HTTP 404 errorThe HTTP 404 status code indicates that the server cannot find the resource or endpoint identified by the request path.
- handlerA handler is an application component that receives a framework-dispatched request or event and performs the corresponding processing.
- factoryA factory function is a function that creates and returns a configured object.
- CRUDA CRUD operation is an operation that creates, reads, updates, or deletes persistent data.
- System.Text.JsonSystem.Text.Json is the .NET library for reading and writing JSON data.
- lambdaA lambda expression is an anonymous function expression that can be passed or assigned as a value.
- payloadA JWT payload is the token section that contains its claims and other encoded data.
- middlewareMiddleware is a request-processing component that can inspect, modify, or handle HTTP requests and responses within an ASP.NET Core pipeline.
- short-circuit evaluationA short circuit is the termination of request-processing pipeline execution by returning a result without invoking the remaining components.
- route parameterA route parameter is a named variable embedded in a URL pattern whose value is extracted from a matching request path.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
