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.
Ready to dive right in? For a full walkthrough of how to build a REST API in ASP.NET Core, check out Stormpath Evangelist Nate’s recent talk!
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:
This will set the root route of your API to:
http://www.mycompany.com/api to call the
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.
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.
Network calls by their very nature are asynchronous. It makes the most sense to create
async controller 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
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?
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
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.
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.
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.
ConfigureServices method of
Startup.cs, change your MVC line from:
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.
Questions? Comments? Leave ’em in the comments below, or hit me up on Twitter @LeeBrandt.
And, if you’re building a webapp in .NET, here’s one last tip: don’t build auth in-house! Stormpath is a complete user management solution that can be added to any project with just a few lines of code. We know that secure user management is tough and time-consuming, and it’s also not the core of your business. But it is the core of ours! Learn more about how Stormpath makes auth easy in these resources: