Configure ASP.NET Core site

I started this project because I was often stuck doing the same job several times, mainly configuring new and existing projects.
I have a self-developed framework called Assets that I am constantly adding new features to, so I needed an easy way to add or remove features from Assets.
Configure ASP.NET Core site

Content

  1 Setup the project
  2 Create the feature's type
  3 Configure the site
  4 Review
    Links

Setup the project

For this article I created a standard ASP.NET Core MVC project.

Select project in Visual Studio

First thing is to define two enum's that defines avaiable feature's and scope when using the Service feature.
The enum's are defined in BlogStatics which is located in the root directory.
1
public enum Feature
2
{
3
    SSL,
4
    DefaultRoute,
5
    Service
6
}
7
8
public enum ServiceScope
9
{
10
    Scoped,
11
    Singleton,
12
    Transient
13
}
                            
public enum Feature
{
    SSL,
    DefaultRoute,
    Service
}

public enum ServiceScope
{
    Scoped,
    Singleton,
    Transient
}
                            
                        

Create the feature's type

Now it's time to add some feature that's avaiable for your project's.
We'll implement three features:
  • DefaultRoute Let's you define a default route on configuring
  • SSL Add's security features like Https Redirection and HSTS
  • Service Let's you add any type as service that you can use in dependency injection


The enum Feature defines which features is available.
Here you can add whatever you need and implement it in a new feature class that inherits FeatureBase.
The enum ServiceScope defines the scope when adding services to the WebApplicationBuilder.

Let's start with the base class FeatureBase that all feature's inherit from.
The class only defines what kind of feature that implements it.

1
public abstract class FeatureBase(Feature feat)
2
{
3
    public Feature Feature => feat;
4
}
                            
public abstract class FeatureBase(Feature feat)
{
    public Feature Feature => feat;
}
                            
                        
1
public sealed class DefaultRoute : FeatureBase
2
{
3
    private readonly string _controller;
4
    private readonly string _action;
5
6
    public DefaultRoute(string controller, string action) : base(Feature.DefaultRoute)
7
    {
8
        _controller = controller;
9
        _action = action;
10
    }
11
12
    public string Path => $"{{controller={_controller}}}/{{action={_action}}}/{{id?}}";
13
}
                            
public sealed class DefaultRoute : FeatureBase
{
    private readonly string _controller;
    private readonly string _action;

    public DefaultRoute(string controller, string action) : base(Feature.DefaultRoute)
    {
        _controller = controller;
        _action = action;
    }

    public string Path => $"{{controller={_controller}}}/{{action={_action}}}/{{id?}}";
}
                            
                        
1
public sealed class SSL : FeatureBase
2
{
3
    private readonly int _port = 443;
4
5
    public SSL() : base(Feature.SSL) 
6
    { }
7
8
    public SSL(int port) : base(Feature.SSL)
9
    {
10
        _port = port;
11
    }
12
13
    public int Port => _port;
14
}
                            
public sealed class SSL : FeatureBase
{
    private readonly int _port = 443;

    public SSL() : base(Feature.SSL) 
    { }

    public SSL(int port) : base(Feature.SSL)
    {
        _port = port;
    }

    public int Port => _port;
}
                            
                        
1
public sealed class Service : FeatureBase
2
{
3
    private readonly Type _interface;
4
    private readonly Type _implementation;
5
    private readonly ServiceScope _scope = ServiceScope.Transient;
6
7
    public Service(Type implementation, ServiceScope scope = ServiceScope.Transient) : base(Feature.Service)
8
    {
9
        _interface = null;
10
        _implementation = implementation;
11
        _scope = scope;
12
    }
13
14
    public Service(Type interface_, Type implementation, ServiceScope scope = ServiceScope.Transient) : base(Feature.Service) 
15
    {
16
        _interface = interface_;
17
        _implementation = implementation;
18
        _scope = scope;
19
    }
20
21
    public Type Interface => _interface;
22
    public Type Implementation => _implementation;
23
    public ServiceScope Scope => _scope;
24
}
                            
public sealed class Service : FeatureBase
{
    private readonly Type _interface;
    private readonly Type _implementation;
    private readonly ServiceScope _scope = ServiceScope.Transient;

    public Service(Type implementation, ServiceScope scope = ServiceScope.Transient) : base(Feature.Service)
    {
        _interface = null;
        _implementation = implementation;
        _scope = scope;
    }

    public Service(Type interface_, Type implementation, ServiceScope scope = ServiceScope.Transient) : base(Feature.Service) 
    {
        _interface = interface_;
        _implementation = implementation;
        _scope = scope;
    }

    public Type Interface => _interface;
    public Type Implementation => _implementation;
    public ServiceScope Scope => _scope;
}
                            
                        

Configure the site

Ok now it's time to actually configure the site.
1
using Blog.ConfigureAspNetCore;
2
using Blog.ConfigureAspNetCore.Components;
3
using Blog.ConfigureAspNetCore.Components.Features;
4
using Blog.ConfigureAspNetCore.Components.Repo;
5
6
new Config(args,
7
    new SSL(),
8
    new Service(typeof(ITheRepo), typeof(TheRepo), ServiceScope.Transient),
9
    new DefaultRoute("Demo", "Index"));
10
                            
using Blog.ConfigureAspNetCore;
using Blog.ConfigureAspNetCore.Components;
using Blog.ConfigureAspNetCore.Components.Features;
using Blog.ConfigureAspNetCore.Components.Repo;

new Config(args,
    new SSL(),
    new Service(typeof(ITheRepo), typeof(TheRepo), ServiceScope.Transient),
    new DefaultRoute("Demo", "Index"));

                            
                        
As you can see, the code is much cleaner and easier to read.

Review

As you can see, it's very easy to add new features and control when the different services are added to the site.
Some features need to be added in a specific order. With this system you can figure it out once and never worry about it again.

I hope you had a good time coding!

-Stein Lundbeck

Comments

Name