Monday 10 August 2020

Anatomy of C# Core Rest API

Lets talk about dot net core for a quick second, the short of it is it's awesome and you should switch from dotnet sooner than later. With that out of the way lets take a look at the autonomy of the web api project. 

The dotnet core web api project starts in the main method of the program class.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace pav {
  public class Program {
    public static void Main(string[] args) =>
      CreateHostBuilder(args).Build().Run();

    public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
  }
}

Here the main method calls the Create host builder function which uses the Startup class to instantiate the web service. 

the Startup.cs file is really where all the interesting stuff happens out of the box, later you can do some cool integration with azure key vault in the main.cs class but for now lets take a look at startup.cs since otb (out of the box) it's far more interesting.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace pav {
  public class Startup {
    public IConfiguration Configuration { get; }
    public Startup(IConfiguration configuration) => Configuration = configuration;
    
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services) => services.AddControllers();
    
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder appIWebHostEnvironment env) {
      if (env.IsDevelopment())
        app.UseDeveloperExceptionPage();
      app.UseHttpsRedirection();
      app.UseRouting();
      app.UseAuthorization();
      app.UseEndpoints(endpoints => endpoints.MapControllers());
    }
  }
}


our main.cs class first calls the constructor of the startup class which instantiates an instance of the IConfiguration interface using dependency injection, basically this is just a dictionary which is defined in our appsettings.json file allowing us to have a place to store things like connection strings or tenant ids or even passwords.... though you should never store a production password in your appsettings.json file, but that's another story for a different blog post.

Next the ConfigureServices method executes which registers all of our services as well as any dependencies to be used by the default IOC container within dotnet core.

then finally the configure method is executed where the request pipeline is configured, basically an http request comes in and all of the registered middle-ware components act on the request. 

In short the program.cs class is the entry point and it uses the startup.cs were all of our app services and dependencies are registered as well as our request pipeline is configured.

next lets take a look at the controller

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace pav.Controllers.V1 {

  [ApiController]
  [Route("api/v1/[controller]")]
  public class WeatherForecastController : ControllerBase {
    private static readonly string[] Summaries = new[] {
      "Freezing""Bracing""Chilly""Cool""Mild"
      "Warm""Balmy""Hot""Sweltering""Scorching"
    };

    private readonly ILogger<WeatherForecastController_logger;

    public WeatherForecastController(ILogger<WeatherForecastControllerlogger) {
      _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecastGet() {
      var rng = new Random();

      return Enumerable.Range(15).Select(index => new WeatherForecast {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-2055),
        Summary = Summaries[rng.Next(Summaries.Length)]
      }).ToArray();
    }
  }
}

This is where the magic happens this is our entry point when a user hits an endpoint, each endpoint is contained within a controller, these controllers can have multiple functions that take in request and provide responses. 

the most common requests are:
  • Get: should not have a body makes a request for date
  • Post: sends data usually for creating something
  • Delete: sends a command to delete something
  • Put: sends an update to overwrite an existing something
  • Patch: sends an update to modify and existing something
that's pretty much it for the basics