Reusable API mechanisms in ASP.NET Web API 2. Part 1: Introduction
Here, in Twinfield, we are working on complex functionality related to online accounting. While working on API layer we’ve noticed that a lot of different patterns and pieces of code are repeated from controller to controller, and from action to action. Validation, versioning, patching etc. We wanted to avoid duplication, split responsibilities, make code reusable and better testable. As result we came up with generic mechanisms which help to add this kind of functionality with minimal effort.
NOTE: As far as our current stack is ASP.NET Web API, but not ASP.NET Core, all code samples in the articles will be written using this framework. But all the provided ideas and partially code can be easily transformed to fit ASP.NET Core.
What will be covered:
- Output reduction
- Defaults population
You can find whole code in Github repository.
All the mechanisms described in this series are built using Action filters. If you are not familiar with this concept please check Understanding Action Filters (C#) first.
- Validation. Incoming data is validated in most cases related to POST, PUT or PATCH request (“Don’t trust the client”). It’s easy to check input when primitives come to an action, but with more complex data, validation could become a problem. Complex fields could have complicated validation rules, cross fields validations, relations to the app state etc. We wanted to decouple validation part from action in the controller. The solution is the action filter which does validation before data comes into the controller action.
- Output reduction. Sometimes client needs only couple of fields from the requested resource but the whole resource body is huge. To solve this problem we have added the action which reduces output based on query parameter fields.
- Defaults population. When we create new resource we should provide the body which contains all the required data to create the resource. But, as it often happens, most of the data should be taken from some defaults like default accounts, templates, etc. In this case, to prepare the data for the new resource a client should execute several more requests and process its responses. We decided to solve this by automatic defaults population in case if data is not provided in the body.
- Versioning. Versioning is hard! When there are clients who already use your API you should change contracts really carefull. If the business logic requires some changes in the model data it automatically means that you should support current and previous model (and logic behind them). Versioning filter helps to separate versioning logic from main business logic, avoid producing endpoints per each request, switch statements etc.
- Patching. It’s often happening PATCH implementation comes down taking data from the input, apply it on the model and store the whole model. The logic of parsing incoming data from PATCH is hard enough for complex objects and we have to repeat it for every resource. Patched data should be validated somehow. And other specifics… Extracting patching logic to separate filter helps to avoid these problems.
We will apply all this mechanisms on some sample ASP.NET Web API 2 application. You can find whole code in Github repository.
The demo application provides API to work with heroes collection.
First, application has HeroesController with actions for CRUD operations on heroes:
Second, there is a HeroModel and related models to cover cases with different cases like primitives, complex objects(Lair) and arrays(SuperPowers):
Third, we have HeroRepository. It’s a singleton which keeps heroes collection in memory and provides operations with this collection. The initial collection is already filled with some data:
In the next articles we will extend this example with reusable API mechanisms.
We just looked at the overview of the upcoming articles about reusable API mechanisms in ASP.NET Web API 2.
We got the understanding how all the API mechanisms in our application are related to each other and found out the motivation for the implementation of these mechanisms.
Also, we specified initial application setup for future extensions.
See you in the next articles ;)
Twinfield International N.V. is the European market leader in the area of online accounting and part of the Wolters Kluwer Tax & Accounting division, the global leading provider of tax, accounting and audit information, software and services. Today, more than 80,000 financial accounts are being compiled using Twinfield in 22 countries.