Back to the roots: Creating thin Web APIs using the Core of ASP.NET Core 1.0

Back to the roots: Creating thin Web APIs using the Core of ASP.NET Core 1.0

I'm currently fiddling about ASP.NET Core 1.0 using VS Code on my Mac. I have a simple scenario: Building a Web API which has CRUD operations for a CustomerModel. So purely HTTP things. :-) My controller looks like:

using Microsoft.AspNet.Mvc;
using System;
using System.Collections.Generic;

namespace CustomerWebApi
{
    [Route("api/[controller]")]
    public class Customer : Controller
    {
        private ICustomerService _customerService { get; set; }

        public Customer(ICustomerService customerService) {
            _customerService = customerService;
        }

        [HttpGet("list")]
        public IActionResult List()
        {
            return Ok(_customerService.List());
        }
        
        [HttpPost("")]
        public IActionResult Create([FromBody] CustomerModel model) {
            _customerService.Create(model);
            return Ok();
        }
    }
}

The ICustomerService represents a service to access a database which holds my model:

namespace CustomerWebApi
{
    public class CustomerModel
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

If you use the Yeoman generator to generate a Web API template, you end up with a Startup.cs which uses services.AddMvc():

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

Curious as I am, I added a new line after services.AddMvc(), typed services. and let IntelliSense show me, what else can be done on an IServiceCollection. I didn't take long that services.AddMvcCore() got my attention.

Neither the documentation for AddMvc nor for AddMvcCore is that verbose yet to get a difference between those two statements, I ended up clicking the View on GitHub link.

Oh my open source! Did you just realize, that the ASP.NET Core 1.0 documentation contains links to the source code on GitHub? Everything you want to know about how things are done in ASP.NET Core 1.0 can easily be looked up at GitHub. Well, I stop drooling... Let's look at the differences of the two mentioned statements.

As you can see in the source code (I'm still drooling) AddMvc() uses AddMvcCore() and adds some middlewares like razor view engine or api explorer. Additionally it adds support for data annotations (which allows you to use annotation for validations on your model) as well as JSON formatters. So far so good, but since I'm building Web APIs I just want to use middlewares I really need. Performance matters. ;-)

If you just switch from AddMvc() to AddMvcCore() you're gonna have a bad time. Requesting data will end up in getting a HTTP 406 Not acceptable and a warning:

warn: Microsoft.AspNet.Mvc.Infrastructure.ObjectResultExecutor[0]
      No output formatter was found to write the response.

When posting data, you get an empty model, since the post body will not be transformed in any way. If you instantly access the model without a null check, you'll get an exception which will be turned into a HTTP 500 Internal Server Error. Not really what you want, eh? ;-)

To fix this, you need to add the JSON formatters again:

public void ConfigureServices(IServiceCollection services)
{
    var mvcCore = services.AddMvcCore();
    
    mvcCore.AddJsonFormatters(options => options.ContractResolver = new CamelCasePropertyNamesContractResolver());
}

With this, you can get and post data from and to your controllers in JSON format. As a bonus I'm using CamelCasePropertyNameContractResolver() to automatically convert from and to camel-cased property names. This is useful for JavaScript, since it allows you to access the properties in a response.myProperty way instead of response.MyProperty which looks really weird in JavaScript.

Be aware! AddMvcCore does exactly what its name stands for: It only adds core components. You need to add everything else yourself like support for CORS or data annotations.

What do you think about using AddMvcCore() instead of AddMvc()? Share your thoughts by leaving a comment! :)