Spike WebAPI

ASP.Net makes creating Web APIs as painless as possible. In this article I’ll walk you thru basics of ASP.Net Web API. You’ll learn how to setup EF Core with Web API and Swagger. Additionally I’ll go thru Student Controller which contains CRUD methods. Finally I’ll show you new features that were provided in .Net Core 2.1.

Setup application

Startup.cs is file, where we can configure our API. We can setup there whole DI Container, every library we’re going to use etc. Currently our Startup is very small, we need to setup only EF Core and Swagger, but it can get bigger. I’ll show you later how to deal with too bug startup file.

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    . . .   
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

In ConfigureServices we can setup services that we’ll use in Web API, like Entity Framework, Swagger, Fluent Validation, AutoMapper, Authentication and your own services. Finally we can setup MVC. It’s worth to mention that some libraries have to be called after MVC, because they change options that MVC sets. It’s just to let you know, that here, order of the calls matters. If you reorder method you can break your API. It’s not that fragile, but keep it in mind.

Setup Entity Framework

services.AddDbContext<BlogPostContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

Team responsible for Entity Framework wanted to help us using their library. They’ve created method which will add everything that is needed by EF to Service Collection. Thanks to that we don’t need to know what’s inside. They provided us with Black Box.

What we need to do is provide EF with ConnectionString. ConnectionString is text with every information that is needed to connect to database, like host, database name and credentials. When you’ll setup SQL Server and create database you’ll be able to retrieve Connection String. In my example ConnectionString is in appsettings.json we can retrieve ConnectionString from appsettings.json using  Configuration.GetConnectionString(string text)

MVC Compatibilit

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Last thing that was implemented in .Net Core 2.1, Compatibility Version. Team tried to think about solution that would let them make necessary breaking changes without forcing developers to make changes immediately. Thanks to that we can set which version we want to use. Keep in mind that MS will not support old versions eternally. You will have to update sooner or later.

Controllers

Controllers are our interface that face client. We can implement there every action that client can do. As you can see controller class is decorated with [Route("api/[controller]")] attribute. It tells how url root looks like. In this case it is api/students name is taken from controller class name. You can also specify your own name if you want.

The same way as classes, every method is decorated as well. For every verb there is attribute, `[HttpGet]`, `[HttpPost]`, `[HttpPut]`, `[HttpDelete]`. Additionally every attribute can pass parameter if we want to alter route. Consider example below, you can see how would look url for both actions.

[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
    // GET: api/students
    [HttpGet]
    public ActionResult<IEnumerable<Student>> GetStudents()
    {
        . . .
    }
    // GET: api/students/5
    [HttpGet("{id}")]
    public async Task<ActionResult<Student>> GetStudent([FromRoute] int id)
    {
        . . .
    }
}
[HttpGet("{id}")]
public async Task<ActionResult<Student>> GetStudent([FromRoute] int id)
{
    . . .
}

MVC will bind data passed in url to parameters in method. It will try to bind model from route when you specify [FromRoute] attribute, if you add [FromQuery] it’ll use query params and [FromBody] will use body, it is straight forward. I’ll create post about model binding in future, then we’ll take a closer look, for now that’s enough.

Status codes

As you know, every response from Web API always need status code. In .Net Core we have methods to return response with desired status code. For example return Ok(response) will create response with status 200 OK, return NoContent() will create response with status 204 NoContent, and so on. You need to check by yourself what methods are available, from my experience there is enough, but once for a while I had to create response on my own.

.Net Core 2.0 vs 2.1

.Net Core 2.1 added a lot of great features to WebAPI. I was lucky to be user of .Net Core 2.0 and then transit to 2.1, so I was able to see flaws of version 2.0 and try fixes immediately.

T vs IActionResult vs ActionResult<T>

In verions 2.0 there was only T and IActionResult, so we could’ve let other developers know what type we want to return (T) or return status code (IActionResult). In that case it was empty choice, because we had to choose IActionResult when we wanted to create proper Rest API with status codes for every occasion.

In 2.1 version we were granted ActionResult<T>, in this case we have combination of T and IActionResult. We can let know others what type should they expect, and at the same time, we can return status codes.

[ApiController]

In version 2.1 team added attribute [ApiController] which works as aspect for validation and alters behavior of actions. Before 2.1 we had to add validation ourselves if we wanted to validate user request on the server.

if(!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

Code above will check if model that user passed to action is valid, and if not returns information to client. When we add [ApiController] we don’t need to do that. Every action will check if model was valid and return BadRequest on its own.

Outro

As you can see, Asp.Net Core make building Web API as easy as possible. We have powerful tools to develop clean code faster. Basic example isn’t perfect thou, well it isn’t even good. There’s a lot of minor problems that we’ll get rid of in Advanced Example and Final Example. For now I wanted to keep it simple.

Come by next time. Finally, as always if you have questions or feedback, feel free to contact me.

Leave a Reply