.NET Core – The ASP.NET Core Architecture

.NeT Core

Because, Great API’s depend on great architecture.

This chapter will introduce you to ASP.NET Core and its features.
We will also take a look at the traditional layered architecture as a solution to potential problems. And finally we will go beyond that …

 

We will introduce you some concepts and get you prepared for the big stuff.

This chapter is part of the .NET Core series.

Part 1

.NET Core RESTful API's

Introduction to API and REST

Part 2

You are here

A dive into the built-in functionalities.

Part 3

The Clean Architecture

Learn and implement the concept of the Clean Architecture

Part 4

Implementing REST

Making the API RESTful

ASP.NET Core

An Introduction to ASP.NET Core.

ASP.NET Core is an open source, cross-platform, modular web platform for developing cloud-based server applications. It can run on both the .NET framework and the (natively cross-platform) .NET Core framework. .NET Core is its default development framework.

 

It includes a unified use case for building web-based user interfaces and web APIs.

ASP.NET Core The Origin

The new ASP.NET Core combines the MVC and Web API into one framework. (i.e You can now return a View or an object using the same controller)

ASP.NET Then and Now

Its Razor syntax allows you to inline C# directly inside your views :

Its Typescript (a superset of JavaScript) support, enables you to create more scalable code :

Typescript

Features

Important Features of ASP.NET Core.

These are some of the important ASP.NET Core features that can be related while implementing a RESTful architecture :

  • Environment Configurable

    The framework contains an environment-based configuration system that supports application settings provided in many different formats ( files, command-line, in-memory, environment variables, encrypted secret stores, custom providers etc) at runtime.

Environment Configurable
  • Dependency Injection

    You can resolve code dependencies by 'injecting' them only when needed. (i.e loosely coupled components ⇒ maintainability and extensibility)

Dependency Injection
  • Logging

    It provides an extensive logging infrastructure that works with many providers to send entries to many destinations.

.Net Core Logging
  • Hosting

    Application can be hosted everywhere (because it is built on top of .NET Core).
    examples: Internet information services (IIS), self-hosted in its own process, or even hosted inside Docker. . REST perspective - Hosts and servers satisfy the Client-Server constraint.

  • Middlewares

    The frameworks request/response architecture is primarily driven by middlewares (components that can intercept requests and perform specific logic before invoking the next component in the pipeline). . REST perspective - Satisfies the Layered System constraint.

Middlewares

Ways to Create Apps

There are two general approaches and a hybrid approach to building web applications using ASP.NET Core.

  • Traditional Web Applications

    Performs most of the application logic on the server.

    Suitable when client-side requirements are simple and no JavaScript is required.

  • Single page applications (SPAs)

    Performs most of the user interface logic in a web browser, communicating with the web server primarily using web APIs.

    Suitable when you are dealing with a rich user interface with large number of features.

  • A Hybrid Approach

    A more rich SPA-like sub-application within a larger traditional web application.

Initiating A New Project

How to create a new ASP.NET Core project.

If you have not already setup your environment to create an ASP.NET Core app, Please do that first.

A cool feature of an ASP.NET project is project template. Project template is a special pre-built architectural framework that sets up a new project along with an organized file and code structure using one of the design patterns (MVC, SPA etc) that we can choose from.

 

Even though it is not a new thing in ASP.NET, the new CLI integration in .NET Core makes the job done in less time.

 

Here is how you can initiate a new Web API project:

New WebApi project

A new ASP.NET Core project starts out as a simple ‘all-in-one’ monolithic application ( whether created in Visual Studio or from the command line ). All of the application behavior, including presentation, business and data access logic is contained within the same project.

Here is a quick overview of a common monolith app :

Common Web Application architectures
Single project monolithic application - ( Image from book - Architecting Modern Web Applications with ASP.NET Core and Azure )

Maintainability ⇐ Our Concern

Maintainability – A key aspect of a good software architecture.

One of the most important aspect of a good software architecture is maintainability. It should always be one of the key concerns of any application.

 

Designing a good application with maintainability in mind, requires making certain architectural decisions that are based on a common set of design principles.

Single Responsibility

States that each system capability (e.g. service | module | api etc) should have only one responsibility and as such one reason to change.

Separation Of Concerns

A design principle for separating a computer program into distinct sections, so that each section addresses a separate concern.

Encapsulation

The idea of bundling data and methods that work on that data within one unit.

Don't Repeat Yourself

States that duplication in logic should be eliminated via abstraction and duplication in process should be eliminated via automation.

Dependency Inversion

Introduces an interface abstraction between higher-level and lower-level software components or layers to remove the dependencies between them.

Persistence Ignorance

States that classes modeling the business domain in a software application should not be impacted by how they might be persisted.

Explicit Dependencies

States that Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.

Bounded Contexts

A central pattern in Domain Driven Design that presents an idea of breaking complex problems into conceptual modules that represents a context (separate from other contexts) with the ability to evolve independently.

A design principle for separating a computer program into distinct sections, so that each section addresses a separate concern.

The idea of bundling data and methods that work on that data within one unit.

Introduces an interface abstraction between higher-level and lower-level software components or layers to remove the dependencies between them.

States that Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.

States that each system capability (e.g. service | module | api etc) should have only one responsibility and as such one reason to change.

States that duplication in logic should be eliminated via abstraction and duplication in process should be eliminated via automation.

States that classes modeling the business domain in a software application should not be impacted by how they might be persisted.

A central pattern in Domain Driven Design that presents an idea of breaking complex problems into conceptual modules that represents a context (separate from other contexts) with the ability to evolve independently.

These key principles not only helps with maintainability but also helps minimize cost and promotes usability and extensibility. We will be focusing on these design principles and learn more about them as we build our RESTful WebAPI.

Using A Single Project ⇐ Drawbacks

Disadvantages of a single project monolithic application.

When working with a single project monolithic application like shown in the above image, separation of concern is achieved through the use of folders.

 

However, as the project evolves overtime, its size increases with new features and more complexities. This will eventually result in a large number of files and folders. In addition to that, the business logic will be scattered through out the project.

 

A developer who works with such a project will eventually have a hard time managing the code and finding files every once in a while.

 

A single project monolithic application will also suffer in terms of horizontal scalibility unless that is what the requirement is. If such a project needs to be scaled, typically the entire application needs to be duplicated across multiple servers or virtual machines.

The Use Of Layers

The Layered Architectural Patterns.

One common approach to organize the project and minimize complexities is through the use of Layers. In layering, the application is broken down (logically separated) into smaller parts according to specific responsibilities and concerns.

 

In general, A Software system is made up of a collection of components that work together in collaboration to accomplish a specific function or a set of functions. These components can be grouped together based on the functionalities that they provide, commonly known as ‘area of concerns‘.

A layered architecture can implement many communication models. A common and popular one is the Top-Down approach. In such communication models, one layer receives the request, processes and makes some changes to the request and finally passes it on to the next layer. Hence, the term – Top-Down.

Common application architecture
Common application architecture

Some popular implementations of the Layered architecture pattern :

  • The OSI Networking model
  • Web architecture model

Some of its benefits are :

  • Code organization
  • Code reuse (following the DRY - Don't Repeat Yourself principle) - it is a good architectural decision as mentioned above.
  • Ability to enforce restrictions A.K.A encapsulation (i.e which layer can communicate with which layer) .
  • Maintainability (If encapsulation is properly implemented, specific layers can be easily replaced using a new one implementing the same interface).
  • Easy Testing

Traditional Layering Drawbacks

The traditional layered architecture is monolithic by nature.

 

In this architecture, the compile time dependency runs from top-to bottom and also, the application is what-so-ever deployed as a singe unit.

 

In a way, Every layer depends on the next layer. The UI layer depends on the business logic which in turn depends on Data access. And finally all these layers depend on a common infrastructure or some utilities. This unnecessary dependencies creates unnecessary coupling.

 

Coupling is what affects maintainability and preventing parts of a system from being upgraded.

 

Jeffrey Palermo – The guy who purposed the Onion Architecture says that this is one of the reasons why legacy systems become stale, and eventually are rewritten.

Traditional Layering
The Three Layered Architecture

The Solution

The solution to this problem has existed for quite some time now. Applications that follow the Domain-Driven Design (DDD) and the Dependency Inversion Principle bring forth a common solution.

 

This solution has has gone by many names in these years, starting from the Hexagonal Architecture to Ports-and-Adapters and most recently the Onion Architecture or the Clean Architecture.

 

Lets take a look at this solution and design our API accordingly in the next chapter.

References & Credits

Share with friends