Separation of concerns and n-tiered architecture in ASP.NET 5/ASP.NET Core 1 Separation of concerns and n-tiered architecture in ASP.NET 5/ASP.NET Core 1 asp.net asp.net

Separation of concerns and n-tiered architecture in ASP.NET 5/ASP.NET Core 1


If you ask 10 civil architects to build you a bridge, you’ll end up having 10 different architectures. Not one will be the same and not one will be better than the other.

Regardless of how many best practices and design patterns they apply, each architect will justify their idea. Some will be overzealous while others will keep it simple and get the job done. Amongst other things, budget, delivery dates and craftsmanship will have a direct impact on type of architecture you decide.

The same rule applies with software architects.

I’ve seen my fair share of architects having the best intentions in the world only to realize that the UI layer has a dependency on the DAL. Perhaps the reasoning behind this is that:

  • They haven't thought of it
  • They don't really care about it
  • It facilitates DI since you see every layer which in turn makes iteasy to map Interfaces to their Implementation.

Back in MVC 5, I had the following layers:

-Contoso.Core (Class Library)-Contoso.Data (Class Library)-Contoso.Service (Class Library)-Contoso.Web (asp.net MVC 5)-Contoso.Web.Configuration (Class Library)

The Web.Configuration layer had a dependency on Core, Data and Service. This layer is where I would configure my DI stuff.

The Web layer did not have a dependency on the Data layer and to get stuff started, I was using the Bootstrapper Nuget Package.

Perhaps you could achieve something similar with ASP.NET 5

I’d love for Microsoft (or anyone) to create a working project template that is more geared towards enterprise level samples using a decoupled approach or even something like an Onion Architecture sample.

In the end, whatever I consider like a reasonable decoupled architecture might be too much for some while not enough for others...

Feel free to share your findings as I’m curious to know how you’ve managed to make it work.


Is this really a major problem?

You UI layer will have a dependency on your data layer and there will be some reference somewhere.

The StartUp.cs adds various services and configuration, so most of these references are in one place.


You can probably get around that using a Service Locator.

For example, you have an interface in your root/core/abstractions project:

public interface IServiceConfiguration{    void ConfigureServices(IServiceCollection services, IConfigurationRoot configuration);}

In your StartUp.cs, find all types that implements IServiceConfiguration and use that to register your external services.

public void ConfigureServices(IServiceCollection services){    var currentAssembly = typeof(Startup).Assembly;    // Limit to project assemblies    var @namespace = currentAssembly.FullName.Split(',')[0].Split('.')[0];    var assemblies = currentAssembly.GetReferencedAssemblies()                            .Where(a => a.Name.StartsWith(@namespace, StringComparison.Ordinal))                            .Select(a => Assembly.Load(a));    foreach (var assembly in assemblies)    {        // Assembly.ExportedTypes is not supported in dnxcore50 so you need to take it off your frameworks node in project.json.        foreach (var config in assembly.ExportedTypes.Where(t => typeof(IServiceConfiguration).IsAssignableFrom(t) && !t.IsAbstract))        {            ((IServiceConfiguration)Activator.CreateInstance(config)).ConfigureServices(services, Configuration);        }    }    // More service registrations..}

And in your DAL, you can add a class that will register EF:

public sealed class EntityFrameworkServiceConfiguration : IServiceConfiguration{    public void ConfigureServices(IServiceCollection services)    {        services.AddEntityFramework()                    .AddSqlServer()                    .AddDbContext<BookContext>(options =>                    {                        options.UseSqlServer(Configuration.Get("Data:ConnectionString"));                    });    }} 

Not everyone would need this type of decoupling though. In some ways, it makes more sense to just register everything in StartUp.cs. You would've referenced your DAL in the web project anyway (unless everything is through dynamic discovery) and that means that it already knows something about your DAL.