Promoting SoC Through Application Layering

Creating a layered design in an application is a fundamental element of modern software architecture. The goal is to promote the Separation of Concerns (SoC) design principle. Separation of Concerns The ideas behind SoC date back to Dijkstra's 1974 paper "On the role of scientific thought" . In computer science, separation of concerns (sometimes abbreviated as SoC) is a design principle for separating a computer program into distinct sections. Each section addresses a separate concern, a set of information that affects the code of a computer program. A concern can be as general as "the details of the hardware for an application", or as specific as "the name of which class to instantiate". A program that embodies SoC well is called a modular program. Modularity, and hence separation of concerns, is achieved by encapsulating information inside a section of code that has a well-defined interface. - Wikipedia SoC is a broad design principal th...

Organizing ASP.NET Application Initialization Code

In modern ASP.NET applications, the code to initialize the application can become large and cluttered. Below are two easy techniques that can be helpful in organizing and simplifying the application startup code.

IServiceCollection Extension

One option to help organize the application's startup code is to create IServiceCollection extension methods. This is currently one of the more popular solutions for organizing an application's startup code. Below is an example of a class that contains methods that extend IServiceCollection.

/// <summary>
/// Sample ServiceCollectionExtensions class
/// </summary>
public static class ServiceCollectionExtensions
{
	/// <summary>
	/// Configure custom service registrations for the application
	/// </summary>
	/// <param name="services">IServiceCollection</param>
	public static void AddCustomServices(this IServiceCollection services)
	{
		// just do something here as an example
		services.AddScoped<ApplicationLogic>();
		services.AddSingleton<CachedData>();
	}

	/// <summary>
	/// Configure customer security settings for the application
	/// </summary>
	/// <param name="services">IServiceCollection</param>
	public static void AddCustomSecurity(this IServiceCollection services)
	{
		// just do some stuff here as an example
		services.AddAntiforgery(options =>
		{
			options.HeaderName = "AppInitDemo";
			options.Cookie.Name = "AppInitDemo";
			options.Cookie.SameSite = SameSiteMode.Strict;
			options.Cookie.HttpOnly = false;
			options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
		});

		services.AddDataProtection()
			.SetApplicationName("AppInitDemo");
	}
}

To use the class above, add the following lines to Program.cs.

// call an extension method in Intializers/ServiceCollectionExtensions
builder.Services.AddCustomServices();

// call an extension method in Intializers/ServiceCollectionExtensions
builder.Services.AddCustomSecurity();

Initialization Classes

Another technique that is not as common, but can be useful, is to isolate complex initialization code into static classes.

public static class ResourceInitializer
{
	/// <summary>
	/// Initialize application Resource settings
	/// </summary>
	/// <param name="builder">WebApplicationBuilder</param>
	public static void Init(WebApplicationBuilder builder)
	{
		// perform some Resource configuration as an example
		builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

		var supportedCultures = new List<CultureInfo> { new CultureInfo("en-US") };

		builder.Services.Configure<RequestLocalizationOptions>(options =>
		{ 
			options.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en-US");
			options.SupportedCultures = supportedCultures;
			options.SupportedUICultures = supportedCultures;
		});
	}
}

To use the class above, add the following line to Program.cs.

// call ResourceInitializer.Init()
ResourceInitializer.Init(builder);

This example was created using Visual Studio 2022 running an ASP.NET Core Web App project using IIS Express.

Source code: https://github.com/jharrell-bits/AppInitDemo