--- title: Basic JSON APIs with Route-to-code in ASP.NET Core author: jamesnk description: Learn how to use Route-to-code and JSON extension methods to create lightweight JSON web APIs. monikerRange: '>= aspnetcore-5.0' ms.author: jamesnk ms.custom: mvc ms.date: 11/30/2020 no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR, "Route-to-code"] uid: web-api/route-to-code --- # Basic JSON APIs with Route-to-code in ASP.NET Core By [James Newton-King](https://github.com/jamesnk) ASP.NET Core supports a number of ways of creating JSON web APIs: * [ASP.NET Core web API](xref:web-api/index) provides a complete framework for creating APIs. A service is created by inheriting from . Some features provided by the framework include model binding, validation, content negotiation, input and output formatting, and OpenAPI. * Route-to-code is a non-framework alternative to ASP.NET Core web API. Route-to-code connects [ASP.NET Core routing](xref:fundamentals/routing) directly to your code. Your code reads from the request and writes the response. Route-to-code doesn't have web API's advanced features, but there's also no configuration required to use it. Route-to-code is a good approach when building small and basic JSON web APIs. ## Create JSON web APIs ASP.NET Core provides helper methods that ease the creation of JSON web APIs: * checks the `Content-Type` header for a JSON content type. * reads JSON from the request and deserializes it to the specified type. * writes the specified value as JSON to the response body and sets the response content type to `application/json`. Lightweight, route-based JSON APIs are specified in *Startup.cs*. The route and the API logic are configured in as part of an app's request pipeline. ### Write JSON response Consider the following code that configures a JSON API for an app: [!code-csharp[](route-to-code/sample/Startup3.cs?name=snippet&highlight=6)] The preceding code: * Adds an HTTP GET API endpoint with `/hello/{name:alpha}` as the route template. * When the route is matched, the API reads the `name` route value from the request. * Writes an anonymous type as a JSON response with `WriteAsJsonAsync`. ### Read JSON request `HasJsonContentType` and `ReadFromJsonAsync` can be used to deserialize a JSON response in a route-based JSON API: [!code-csharp[](route-to-code/sample/Startup2.cs?name=snippet&highlight=5,11)] The preceding code: * Adds an HTTP POST API endpoint with `/weather` as the route template. * When the route is matched, `HasJsonContentType` validates the request content type. A non-JSON content type returns a 415 status code. * If the content type is JSON, the request content is deserialized by `ReadFromJsonAsync`. ### Configure JSON serialization There are two ways to customize JSON serialization: * Default serialization options can be configured with in the `Startup.ConfigureServices` method. * `WriteAsJsonAsync` and `ReadFromJsonAsync` have overloads that accept a object. This options object overrides the default options. [!code-csharp[](route-to-code/sample/Startup6.cs?name=snippet)] ## Authentication and authorization Route-to-code supports authentication and authorization. Attributes, such as `[Authorize]` and `[AllowAnonymous]`, can't be placed on endpoints that map to a request delegate. Instead, authorization metadata is added using the and extension methods. [!code-csharp[](route-to-code/sample/Startup.cs?name=snippet&highlight=30)] ## Dependency injection [Dependency injection (DI)](xref:fundamentals/dependency-injection) using a constructor isn't possible with Route-to-code. Web API creates a controller for you with services injected into the constructor. A type isn't created when an endpoint is executed, so services must be resolved manually. Route-based APIs can use to resolve services: * Transient and scoped lifetime services, such as `DbContext`, must be resolved from [HttpContext.RequestServices](xref:Microsoft.AspNetCore.Http.HttpContext.RequestServices) inside an endpoint's request delegate. * Singleton lifetime services, such as `ILogger`, can be resolved from [IEndpointRouteBuilder.ServiceProvider](xref:Microsoft.AspNetCore.Routing.IEndpointRouteBuilder.ServiceProvider). Services can be resolved outside of request delegates and shared between endpoints. [!code-csharp[](route-to-code/sample/Startup4.cs?name=snippet&highlight=3,7)] APIs that use DI extensively should consider using an ASP.NET Core app type that supports DI. For example, ASP.NET Core web API. Service injection using a controller's constructor is easier than manually resolving services. ## API project structure Route-based APIs don't have to be located in *Startup.cs*. APIs can be placed in other files and mapped at startup with `UseEndpoints`. This approach reduces the startup configuration file size. Consider the following static `UserApi` class that defines a `Map` method. The method maps route-based APIs. [!code-csharp[](route-to-code/sample/UserApi.cs?name=snippet)] In the `Startup.Configure` method, the `Map` method and other class's static methods are called in `UseEndpoints`: [!code-csharp[](route-to-code/sample/Startup5.cs?name=snippet)] ## Notable missing features compared to Web API Route-to-code is designed for basic JSON APIs. It doesn't have support for many of the advanced features provided by ASP.NET Core Web API. Features not provided by Route-to-code include: * Model binding * Model validation * OpenAPI/Swagger * Content negotiation * Constructor dependency injection * `ProblemDetails` ([RFC 7807](https://tools.ietf.org/html/rfc7807)) Consider using [ASP.NET Core web API](xref:web-api/index) to create an API if it requires some of the features in the preceding list. ## Additional resources * * *