The new Startup class in ASP.NET Core was changed and now it is clearer and divided in better sections. This is my opinion. The first thing that we have to understand: what is it for? How is it run? I begin the answer that this class is intended to be the initial point of project, by default the class called Startup is initialized by configuration of host, I am going to explain later. In this class is initialized all configurations needed to the project and now I am going to show so you can understand better.
In ASP.NET Core we have configuring a web host to start listening, because the new ASP.NET is only console apps. Program class does this configuration, in case where you create a web application using the VS. Below following the code:
- using System.IO;
- using Microsoft.AspNetCore.Hosting;
-
- namespace RC2WebApp
- {
- public class Program
- {
- public static void Main(string[] args)
- {
- var host = new WebHostBuilder()
- .UseKestrel()
- .UseContentRoot(Directory.GetCurrentDirectory())
- .UseIISIntegration()
- .UseStartup<Startup>()
- .Build();
-
- host.Run();
- }
- }
- }
As can be seen, the Program class is simple and it has an initial method (main). The web host created has some configurations and there we have a configuration to call the Startup class, through the method UseStartup, and this starts the life of the Startup class.
Three methods are seen in Startup class when created by VS:
- Startup method where is responsible by load the values of configuration.
- ConfigureServices method where is responsible by adding the services in container of dependency injection.
- Configure method where is responsible by adding the middlewares and services in HTTP pipeline.
If you still are not familiar about middlewares, you can read other article where speaks about the subject.
Now comes the code time!
Startup method
- public Startup(IHostingEnvironment env)
- {
- var builder = new ConfigurationBuilder()
- .SetBasePath(env.ContentRootPath)
- .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
- .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
-
- if (env.IsDevelopment())
- {
-
- builder.AddUserSecrets();
-
-
- builder.AddApplicationInsightsSettings(developerMode: true);
- }
-
- builder.AddEnvironmentVariables();
- Configuration = builder.Build();
- }
As we all know, now we do not have anymore the file classic called “web.config” to configure your web site. It was changed for JSON. This is a tendency of others platforms and Microsoft joined. If we do not have the “web.config”, now we have the “appsettings.json” that looks like:
- {
- "ApplicationInsights": {
- "InstrumentationKey": ""
- },
- "ConnectionStrings": {
- "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-RC2WebApp-6e6adec3-1055-40a6-80cd-1a392255c25e;Trusted_Connection=True;MultipleActiveResultSets=true"
- },
- "Logging": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Debug",
- "System": "Information",
- "Microsoft": "Information"
- }
- }
- }
The file shows the configurations that will be loaded in constructor of Startup class. However, to load we need the interface IConfigurationRoot. The code is simple, it initializes a builder that loads the configurations of JSON and the environment variables, because to each environment, you can have different configurations. This new feature came in the ASP.NET Core. In the last line, we have the Configuration being loaded.
Note: The web.config still there is, but only to publish.
ConfigureServices method
- public void ConfigureServices(IServiceCollection services)
- {
-
- services.AddApplicationInsightsTelemetry(Configuration);
-
- services.AddDbContext<ApplicationDbContext>(options =>
- options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
-
- services.AddIdentity<ApplicationUser, IdentityRole>()
- .AddEntityFrameworkStores<ApplicationDbContext>()
- .AddDefaultTokenProviders();
-
- services.AddMvc();
-
-
- services.AddTransient<IEmailSender, AuthMessageSender>();
- services.AddTransient<ISmsSender, AuthMessageSender>();
- }
Other nice changes that came in ASP.NET is the arrived of a native dependency injector (DI), but you are free to add other DI that you like. In this method, I inform the services that will be added to DI to be enabled to use these classes without need of creating an instance, According what can be seen, was added the services: EF, identity, MVC and 2 classes. In relation to EF, observe that was informed using the SQL Server and Data Base Context where is informed a connection string through of Configuration, one that was initialized by Startup method.
In case you have specific class of project that you would like to add to DI, you also will use the IServiceCollection. For this, we must use one of the methods following according to Microsoft documentation:
- Instance: A specific instance is given all the time. You are responsible for its initial creation.
- Transient: A new instance is created every time.
- Singleton: A single instance is created and it acts like a singleton.
- Scoped: A single instance is created inside the current scope. It is equivalent to Singleton in the current scope.
Observe that for the specific interfaces, IEmailSender and ISmsSender, utilized the method AddTransient. From now, you can use these interfaces by inserting in constructor that the DI will load for you.
Configure method
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
- {
- loggerFactory.AddConsole(Configuration.GetSection("Logging"));
- loggerFactory.AddDebug();
-
- app.UseApplicationInsightsRequestTelemetry();
-
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- app.UseDatabaseErrorPage();
- app.UseBrowserLink();
- }
- else
- {
- app.UseExceptionHandler("/Home/Error");
- }
-
- app.UseApplicationInsightsExceptionTelemetry();
-
- app.UseStaticFiles();
-
- app.UseIdentity();
-
-
-
- app.UseMvc(routes =>
- {
- routes.MapRoute(
- name: "default",
- template: "{controller=Home}/{action=Index}/{id?}");
- });
- }
In this method we control the ASP.NET pipeline. I am going to add all middlewares needed to the project. Be alert, do not add a middleware that will not be needed in the project, because how many more middlewares are added, heavier your application gets. The explanation is simple, each middleware stays in HTTP pipeline analyzing the request and response of application. To add a middleware, we must use the IApplicationBuilder parameter and call the middleware needed, case nothing is added in this method, neither the MVC will run, because you do not say what want to use for this application
Below I explain some middlewares and your responsibilities:
- UserBrowserLink: Creates a channel of communication between the development and one or more browsers.
- UseDeveloperExceptionPage: Shows the detail of exception thrown by application.
- UseIISPlatformHander: Enable the use the web server IIS.
- UseStaticFiles: Enable the utilization of static files as CSS, JS and others.
- UseMvc: Enable the use of framework MVC.
Beyond the parameter IApplicationBuilder, we have the parameters IHostingEnvironment and ILoogerFactory, where the first loads the information about the current environment. In the code above we are utilizing this parameter to validate if we are in development environment and in case positive is added middlewares specific to this environment. Already the second parameter enables the system log where this is done in the first line.
Conclusion
It is not difficult to understand the behavior of the Startup class, but is essential to apply this fundamental to a correct working of application and for this to get alerts to which services are added.