Monolith, microservice or something in-between

In a recent project we had an interesting challenge as to how we structured and architected our dotnetcore web api’s. We wanted development and deployment agility, but to maintain the flexibility that comes from micro(macro*)services.

* Arguably the term you use here depends on how you choose to cut your system and services

What to expect

Well, maybe lets start with the opposite – what not to expect?

  • This isn’t aimed to be a starter kit, it’s goal is to provide examples
  • How you choose to cut up your apis, well that’s one for you too – sorry
  • And finally, how you choose to name things (models vs data, services vs domain, core vs base, shared vs common) – yep, that’s also up to you

Now the good bits, what to expect?

The goal of the example project (https://github.com/boro2g/MonolithToMicroserviceApi) is to show working examples of the following scenarios:

  • Each WebApi project can run in isolation, without knowledge of others
    • The same mindset applies to deployments – each WebApi can be deployed in isolation
  • All the WebApi’s can be run and deployed as a single application

Why add this extra complexity?

Good question. The key thing for me is flexibility. If it’s done right you give yourself options – you want to deploy as a monolith, no problem. You want to deploy each bit in isolation, well that’s fine too.

How does it look?

Some key highlights of the image above:

  1. MonolithToMicroserviceApi.WebApi
    1. This is the shared singular WebApi project that brings everything together
    2. You can run this via IISExpress, or IIS etc and all the Api’s from the other projects will work within it
  2. MonolithToMicroserviceApi.Search.WebApi
    1. This is the search micro(macro) service
    2. You can run this in isolation, much like you can the common one
  3. MonolithToMicroserviceApi.Weather.WebApi
    1. The same concept as Search, but with other example controllers and code
  4. MonolithToMicroserviceApi.Shared.*
    1. These libraries contain common functionality that’s shared between each WebApi

Adding a new WebApi

The search project has a good example of this. If you look in MonolithToMicroserviceApi.Search.WebApi.Startup

You need to add the ApiConfiguration class itself (see the project for examples), the ApiConfigurations code above and then register them all.

Similarly in the common project startup (MonolithToMicroserviceApi.WebApi.Startup). Simply add each ApiConfiguration and register them.

The Api glue

So how does it all glue together? The key underlying code that allows you to pool controllers from one project into another is:

What issues you might run into?

  • Routing
    • There is a commented out example of this – in the core project and weather project we have a ‘WeatherForecastController’ – if both of these have the same [Route] attribute you will get an exception.
    • A simple fix is to ensure each controller has isolated routes. I’m sure a more clever approach could be used if you have LOTS of WebApi projects, but I’ll leave that for you to work out
  • Dependency bleeding
    • I don’t feel like this approach introduces any more risk of either cyclic dependencies or ‘balls of mud‘ – IMO that comes down the discipline of the team building your solutions.

Summary

What I like about this approach is flexibility. On day 1 you can deploy your common project to a single box and all your api’s are working in one place. Over time, as complexity grows, or your dev teams evolve, different parts can be cut apart but without any fundamental changes needed.

You need to scale your search api, well no problem – deploy it as a single api and scale as you need.

You need to push the weather api to multiple data centres for geo reasons, cut it out and deploy as you want.

Another team needs to own search, again thats fine – you could even pull out to another solution, remove the ApiConfiguration and everyone is happy!? 🙂

I hope it provides some good inspiration. It really doesn’t take much code, or configuration to build what I’d consider to be a very flexible approach to structuring your dotnetcore WebApi projects.

Documenting webapi with Swagger

If you’ve ever worked with webservices, chances are you’ve run into WSDL (http://www.w3.org/TR/wsdl). In the webapi world you don’t get so much out the box – this is where swagger can help expose test methods, documentation and a lot more.

For asp.net projects you can make use of a library: https://github.com/domaindrivendev/Swashbuckle. Install via nuget and you get a UI allowing a configurable interaction with all the webapi methods in your solution:

The swagger UI:
swagger ui

The test controller and methods:
webapi methods

All pretty simple stuff – how about if you want to secure things?
An example scenario might be you only want swagger accessible if you are visiting via http://localhost (or a loopback url).

It’s straight forwards if you implement a custom webapi DelegatingHandler.

This then needs wiring into the webapi request pipelines. In your WebApiConfig file (OTB in your solution in the folder: App_Start) add:

In the TestController example above we had several httpPost methods available – to enable this functionality you need to allow the routes to include the {action} url chunk.

Azure webapi’s are now compatible with swagger – see https://azure.microsoft.com/en-gb/documentation/articles/app-service-dotnet-create-api-app/ for more info.