These days users expect a fluid, app-like experience on the internet. Thus, the new web is being built with APIs and single-page frontends. This means it’s more important that ever to build APIs that are easy to use, reliable, and scalable. ASP.NET Core makes it easy to build great APIs, but there are a few tips we’ve picked up that can help make your APIs even stronger and more scalable.
1. Set the Default Route for ASP.NET Core MVC
A lot of programmers who start using ASP.NET Core just use the default app.UseMvc(); line in the Configure method of Startup.cs. There are options that you can pass to the UseMvc function, like setting the default routes, which is one of the most overlooked:
app.UseMvc(routes => { routes.MapRoute(name: "default", template: "api/{controller=Default}/{action=Get}/{id?}"); });
This will set the root route of your API to: http://www.mycompany.com/api to call the DefaultController’s Get method.
What this does for you (aside from the obvious) is it sets the tone for a decent RESTful API. It also makes changes to URL strategy easier, including versioning the API in the URL easy to do if you set the URL strategy in one place
2. Return IActionResult from .NET Core Controller Methods
Returning IActionResult from your controller methods affords the ability to take advantage of some of the helper methods and classes to ease returning proper HTTP results. The Ok method on the ControllerBase class will return an OkObjectResult that implements IActionResult and returns a 200 OK HTTP message to the caller. The NotFound method returns an object that sends a 404 NOT FOUND HTTP message.
There are quite a few others, but another extremely helpful one is the CreatedAtAction class that returns not only a 201 CREATED HTTP result but adds a header Location with the URL to access the newly created resource.
3. Use the .NET Async Pattern
Network calls by their very nature are asynchronous. It makes the most sense to create asynccontroller methods that extend that asynchronicity when the controllers need to make database and external API calls.
The fact is, asynchronous support in .NET Core and the supporting libraries is very good these days. Using and creating asynchronous code is easy using async/await and libraries that support the Task pattern. The benefit is more simultaneous requests handled with the same hardware requirements.
Asynchronous code just performs better, and since it is so easy to create, why not do it?
4. Use .NET Attributes
Using attributes to decorate routes helps you to take advantage of some of the power of MVC. This may seem counterintuitive since I just told you to use the default routes. Decorating your methods and controller classes with just enough decoration for that class or method can help you take advantage of things like the CreatedAtAction.
You can also use attributes to help the JSON serializer do its job. You can use the NullValueHandling attribute to tell the serializer that when the value of a property is null, not to even serialize the property. You can change the property name that gets serialized so that you can stick with an internal coding standard and still return standard JSON names (like changing ‘MaxTitleLength’ to ‘maxLength’ when serialized). You can even set the order that properties are serialized so that more important properties are serialized first in the JSON documents.
5. Use Async Result Filters
Using Async Result Filters, you can shape the data in the last moments before it goes back to the caller. Usually, you’d add the properties you want (the way you want them) via an anonymous object. There are two problems with that approach, the first is that you need to do a lot of copying of properties and it violates the single responsibility principle. You could use AutoMapper to combat this property copying, but it doesn’t solve the second problem, which is adding new properties (like hypermedia).
Solution: An Async Result Filter will solve both problems and give you a cleaner, more maintainable code base
BONUS: Try This Workaround to Improve Serialization of Self-Referencing Object Graphs
One of the problems with traditional .NET Web API serialization, is that it doesn’t handle self-referencing object graphs very well. The fact is, in good object-oriented objects there may actually be some reference loops, so it’s important to handle them gracefully.
In your ConfigureServices method of Startup.cs, change your MVC line from:
services.AddMvc(); to services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; });
In .NET 4.x a reference loop would cause an error. Once the serializer realized that serializing the object graph would cause a reference loop, it would fail and just send a 500 error. However, in .NET Core without the above JSON options added, the serializer serializes the object until it hits a reference loop and simply sends what has been serialized so far, ignoring the rest of the object, even if it could serialize the rest of the object graph easily.
What this line adds is, it tells the JSON serializer to ignore reference loops and continue serializing the rest of the graph. So far, this is just a workaround for the issue. It’s not perfect, but it’s better than just a failure.
The best way to handle this problem is to simply not have the problem. Normally, we would put these objects into DTOs that are not self-referencing and remove the problem altogether.