# Auto API Controllers Once you create an [application service](../Application-Services.md), you generally want to create an API controller to expose this service as an HTTP (REST) API endpoint. A typical API controller does nothing but redirects method calls to the application service and configures the REST API using attributes like [HttpGet], [HttpPost], [Route]... etc. ABP can **automagically** configure your application services as API Controllers by convention. Most of time you don't care about its detailed configuration, but it's possible to fully customize it. ## Configuration Basic configuration is simple. Just configure `AbpAspNetCoreMvcOptions` and use `ConventionalControllers.Create` method as shown below: ````csharp [DependsOn(BookStoreApplicationModule)] public class BookStoreWebModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => { options .ConventionalControllers .Create(typeof(BookStoreApplicationModule).Assembly); }); } } ```` This example code configures all the application services in the assembly containing the class `BookStoreApplicationModule`. The figure below shows the resulting API on the [Swagger UI](https://swagger.io/tools/swagger-ui/). ![bookstore-apis](../images/bookstore-apis.png) ### Examples Some example method names and the corresponding routes calculated by convention: | Service Method Name | HTTP Method | Route | | ----------------------------------------------------- | ----------- | -------------------------- | | GetAsync(Guid id) | GET | /api/app/book/{id} | | GetListAsync() | GET | /api/app/book | | CreateAsync(CreateBookDto input) | POST | /api/app/book | | UpdateAsync(Guid id, UpdateBookDto input) | PUT | /api/app/book/{id} | | DeleteAsync(Guid id) | DELETE | /api/app/book/{id} | | GetEditorsAsync(Guid id) | GET | /api/app/book/{id}/editors | | CreateEditorAsync(Guid id, BookEditorCreateDto input) | POST | /api/app/book/{id}/editor | ### HTTP Method ABP uses a naming convention while determining the HTTP method for a service method (action): - **Get**: Used if the method name starts with 'GetList', 'GetAll' or 'Get'. - **Put**: Used if the method name starts with 'Put' or 'Update'. - **Delete**: Used if the method name starts with 'Delete' or 'Remove'. - **Post**: Used if the method name starts with 'Create', 'Add', 'Insert' or 'Post'. - **Patch**: Used if the method name starts with 'Patch'. - Otherwise, **Post** is used **by default**. If you need to customize HTTP method for a particular method, then you can use one of the standard ASP.NET Core attributes ([HttpPost], [HttpGet], [HttpPut]... etc.). This requires to add [Microsoft.AspNetCore.Mvc.Core](https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Core) nuget package to your project that contains the service. ### Route Route is calculated based on some conventions: * It always starts with '**/api**'. * Continues with a **route path**. Default value is '**/app**' and can be configured as like below: ````csharp Configure(options => { options.ConventionalControllers .Create(typeof(BookStoreApplicationModule).Assembly, opts => { opts.RootPath = "volosoft/book-store"; }); }); ```` Then the route for getting a book will be '**/api/volosoft/book-store/book/{id}**'. This sample uses two-level root path, but you generally use a single level depth. * Continues with the **normalized controller/service name**. Normalization removes 'AppService', 'ApplicationService' and 'Service' postfixes and converts it to **kebab-case**. If your application service class name is 'ReadingBookAppService' then it becomes only '/reading-book'. * If you want to customize naming, then set the `UrlControllerNameNormalizer` option. It's a func delegate which allows you to determine the name per controller/service. * If the method has an '**id**' parameter then it adds '**/{id}**' ro the route. * Then it adds the action name if necessary. Action name is obtained from the method name on the service and normalized by; * Removing '**Async**' postfix. If the method name is 'GetPhonesAsync' then it becomes 'GetPhones'. * Removing **HTTP method prefix**. 'GetList', 'GetAll', 'Get', 'Put', 'Update', 'Delete', 'Remove', 'Create', 'Add', 'Insert', 'Post' and 'Patch' prefixes are removed based on the selected HTTP method. So, 'GetPhones' becomes 'Phones' since 'Get' prefix is a duplicate for a GET request. * Converting the result to **kebab-case**. * If the resulting action name is **empty** then it's not added to the route. If it's not empty, it's added to the route (like '/phones'). For 'GetAllAsync' method name it will be empty, for 'GetPhonesAsync' method name it will be 'phones'. * Normalization can be customized by setting the `UrlActionNameNormalizer` option. It's an action delegate that is called for every method. * If there is another parameter with 'Id' postfix, then it's also added to the route as the final route segment (like '/phoneId'). #### Customizing the Route Calculation `IConventionalRouteBuilder` is used to build the route. It is implemented by the `ConventionalRouteBuilder` by default and works as explained above. You can replace/override this service to customize the route calculation strategy. #### Version 3.x Style Route Calculation The route calculation was different before the version 4.0. It was using camelCase conventions, while the ABP Framework version 4.0+ uses kebab-case. If you use the old route calculation strategy, follow one of the approaches; * Set `UseV3UrlStyle` to `true` in the options of the `options.ConventionalControllers.Create(...)` method. Example: ````csharp options.ConventionalControllers .Create(typeof(BookStoreApplicationModule).Assembly, opts => { opts.UseV3UrlStyle = true; }); ```` This approach effects only the controllers for the `BookStoreApplicationModule`. * Set `UseV3UrlStyle` to `true` for the `AbpConventionalControllerOptions` to set it globally. Example: ```csharp Configure(options => { options.UseV3UrlStyle = true; }); ``` Setting it globally effects all the modules in a modular application. ## Service Selection Creating conventional HTTP API controllers are not unique to application services actually. ### IRemoteService Interface If a class implements the `IRemoteService` interface then it's automatically selected to be a conventional API controller. Since application services inherently implement it, they are considered as natural API controllers. ### RemoteService Attribute `RemoteService` attribute can be used to mark a class as a remote service or disable for a particular class that inherently implements the `IRemoteService` interface. Example: ````csharp [RemoteService(IsEnabled = false)] //or simply [RemoteService(false)] public class PersonAppService : ApplicationService { } ```` ### TypePredicate Option You can further filter classes to become an API controller by providing the `TypePredicate` option: ````csharp services.Configure(options => { options.ConventionalControllers .Create(typeof(BookStoreApplicationModule).Assembly, opts => { opts.TypePredicate = type => { return true; }; }); }); ```` Instead of returning `true` for every type, you can check it and return `false` if you don't want to expose this type as an API controller. ## API Explorer API Exploring a service that makes possible to investigate API structure by the clients. Swagger uses it to create a documentation and test UI for an endpoint. API Explorer is automatically enabled for conventional HTTP API controllers by default. Use `RemoteService` attribute to control it per class or method level. Example: ````csharp [RemoteService(IsMetadataEnabled = false)] public class PersonAppService : ApplicationService { } ```` Disabled `IsMetadataEnabled` which hides this service from API explorer and it will not be discoverable. However, it still can be usable for the clients know the exact API path/route.