Posts Tagged ‘Startup’

In the last post we found that the Startup class in ASP.NET Core works based on convention. The runtime inspects the class through reflection and invokes the appropriate methods i.e. Configure and ConfigureServices (optional). If class is not properly implemented e.g. say Configure method is not present then there should be a runtime exception. When I removed the Configure method from the Startup class I got the following error:

Unhandled Exception: System.InvalidOperationException: A public method named ‘ConfigureProduction’ or ‘Configure’ could not be found in the ‘startuptest.Startup’ type.

The above message is quite as expected but it was not clear to me why runtime was looking for a method named ConfigureProduction?

There seems to be something missing in the documentation and something else going on inside. So the best way to clear this confusion is to have a look into the ASP.NET Core codebase in github. The core logic for loading the Startup class is implemented in StartupLoader class as shown below.

image

Note, the last parameter environmentName. Does this ring a bell ? “ConfigureProduction”… Production…Environment.

Let’s drill down further. Let’s concentrate on the FindConfigureDelegate method which is used to identify the Configure method of the Startup class. This method in turn invokes “FindMethod” and we need to get into the logic of “FindMethod” to understand this better.

image

The code snippet of FindMethod is shown below.

image

The steps in selecting the right method are:

a) Look for method with name Configure{EnvironmentName}. If found, then check for overloads.In case there are overloads then throw InvalidOperationException.

b) If there are no method with name Configure{EnvironmentName} , then look for method with name Configure.If found, then check for overloads.In case there are overloads then throw InvalidOperationException.

c) If there are no methods found with name Configure{EnvironmentName} or Configure then throw InvalidOperationException.

Step c) above explains the exception message we started with “Unhandled Exception: System.InvalidOperationException: A public method named ‘ConfigureProduction’ or ‘Configure’ could not be found in the ‘startuptest.Startup’ type.

The only missing piece in the puzzle is now the environment name. ASP.NET Core environment name is stored in the environment variable “ASPNETCORE_ENVIRONMENT”. The runtime reads from this variable and sets the IHostingEnvironment.EnvironmentName property. The framework supported values for this variable are “Development” , “Staging” and “Production” , however it can accept other values as well.

We can set this variable from the command line as

set ASPNETCORE_ENVIRONMENT=Development2

Now running the code without any Configure method in the Startup class will lead to the following exception message.

Unhandled Exception: System.InvalidOperationException: A public method named ‘ConfigureDevelopment2‘ or ‘Configure’ could not be found in the ‘startuptest.Startup’ type.

Advertisements

In the last post we have discussed on how the ASP.NET Core request processing pipeline works. As a next step, let’s take a closer look into how the ASP.NET Core application gets started and initialized.When we create a new ASP.NET Core application e.g. say a MVC application, we can see two files which gets added by default, Program.cs and Startup.cs as shown in the figure below:

image

The Program and the Startup class control startup and the configuration of the application runtime. The ASP.NET core application is just a console application and like any other.NET console application and needs a Main method as the entry point of the application.

The Program class contains the implementation of this static void Main method which is used to create an instance of IWebHost and run the same. IWebHost is one of the key components of the application which contains the application configuration and the ASP.NET Core Web server.

The Main method performs the initialization of the IWebHost instance and starts it as shown in the figure below:

image

The IWebHostBuilder is used to configure the ASP.NET Core Development Server (default is Kestrel) , Logging , IIS Integration (if required) , Content Root etc.We will take a deeper look into the IWebHost / IWebHostBuilder later.

Now let’s take a look into the Startup class which gets wired into the IWebHost instance as highlighted below:

image

UseStartup is a generic extension method on IWebHostBuilder as shown below. But the interesting point to be noted here is the generic type parameter has no constraints TStartup can be any class.

image

This is quite interesting as I am more used to having an interface driven strongly typed parameters in this kind of situations. It’s quite obvious that this Startup class needs to work in tandem with the IWebHost based on certain conventions. Now let’s take a look at the code that is in the Startup class by default.

image

a) The Configure method is a must have for the Startup class. This is invoked by the runtime host, which creates an instance of IApplicationBuilder and passes it as an agrument.This IApplicationBuilder is used to configure the middleware pipeline by adding suitable components. The other parameter IHostingEnvironment can be omitted if not required. We will get into further details of the IApplicationBuilder interface while exploring the ASP.NET Core middleware pipeline.

b) The ConfigureServices method is optional.This can be implemented to add additional services to the IServiceCollection.We will get into further details of the IServiceCollection interface while exploring the ASP.NET Core Dependency Injection.

Now comes the question, is it a good design, making the startup class work by convention rather than having any strongly typed interface. I think it’s fine. It helps to keep things simple. This is the startup code so we can take up the additional overhead of reflection in inspecting the method definitions and then invoking it. Also, the chances of type mismatch or method mismatch is not there because its the startup code used to configure and initialize the application and should not have a widely varying behavior at runtime. This is also more flexible as we can different other parameters in the methods to suit our needs.

Next comes the question why we have two classes for the application initialization, Program and Startup? The segregation of responsibilities is very clear, the Program class contains initialization code that is used to set up the infrastructure that will rarely change over the lifetime of the project (like ASP.NET Core Web Server, Logging etc.) whereas Startup contains the initialization of features that are required to customize the application’s behavior.