ASP.NET Core ushers in a new generation of ASP.NET applications. This new generation of application can run on many platforms such as Windows, Mac, Linux and Docker. Running cross platform means dropping the need for Internet Information Services (IIS) to host the application.
In addition, ASP.NET Core has been engineered with dependency injection and a modular HTTP middleware pipeline to facilitate application services. Together these changes affect the way that ASP.NET Core applications are structured and initialized. Let's look at the startup process and get an understanding where all of the pieces fit and why each is important.
Prior to ASP.NET Core, ASP.NET Framework applications were loaded by IIS. The executable InetMgr.exe creates and calls a managed web application's entry point. The HttpApplication.Application_Start()
event is fired during this initialization process. A developer's first chance to execute code was to handle the Application_Start
event in Global.asax.
In ASP.NET Core, the Global.asax file is no longer available as has been replaced with a new initialization process.
ASP.NET Core applications are a .NET Core Console application that calls into ASP.NET specific libraries. This is a fundamental change in how ASP.NET Core applications are developed. Instead of the application being hosted by IIS, all of the ASP.NET hosting libraries are executed from within Program.cs. This means that a single .NET tool chain can be used for both .NET Core Console applications and ASP.NET Core applications. The benefits of the new architecture allow for more control by the developer over initialization and the hosting environment.
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>() // Invokes Configure & ConfigureServices on Startup
.Build();
host.Run();
}
}
In this excerpt from the Main method of an ASP.NET Core app, Main
is responsible for initializing the web host, invoking startup and running the app. Additional settings and hosting functionality can be configured and added to the WebHostBuilder
. The host will invoke the Configure
and ConfigureServices
methods on the application's Startup
class.
ASP.NET Core provides complete control over the application's life cycle. The Startup
class is called by the Main
method of the application, this is where configuration takes place and services for the application are specified.
When the Startup
class is initialized, the application's settings are fetched from appsettings by the ConfigurationBuilder
. After the settings are read, the ConfigureServices
method is invoked allowing services to be resolved from the dependency injection container and created before configuration takes place.
Next the Configure
method is invoked. Here application settings are applied and middleware components are registered in the application pipeline.
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)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
The ConfigureServices
method is where services are added to the application's service container. ASP.NET Core uses a dependency injection container to resolve dependencies versus hard-coding concrete implementations. Middleware, frameworks, authentication services and more can be added to the services container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
In the example above, the call to AddMvc
will add the necessary services for MVC to the services container. Individual application services are added with the Add[Transient|Scoped|Singleton]
methods. These methods map an abstract type to a concrete service for a specific lifetime. Choosing the right lifetime - Transient, Scoped, Singleton - will depend on how your service is intended to interact with the application.
// method signature services.AddTransient<TService, TImplementation>();
services.AddTransient<TService, TImplementation>();
When adding services, the types are specified where TService
is the Type, typically an interface, and TImplementation
is the concrete class that will be used to satisfy the interface.
In the request pipeline, middleware components are initialized. The Configure
method is used to specify how the ASP.NET application will respond to individual HTTP requests in the form of middleware.
Middleware in ASP.NET Core are built from extension methods on IApplicationBuilder
and give developers direct access to HTTP requests. Typical Use*Action*
middleware will handle requests and responses and pass the request on to the next component in the pipeline for further action. In addition, Run
and Map
middleware delegates are used for less common scenarios - these delegates will terminate or branch the request pipeline. Additional services like IHostingEnvironment
and ILoggerFactory
may also be configured, these services are initialized in the ConfigureServices
method.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Each Use
extension method adds middleware to the request pipeline. If we look at the Configure
method generated by the ASP.NET Core project template, we'll see several pieces of middleware have already been defined for us. Because of the modular design of IApplicationBuilder
, middleware can be added for specific deployment scenarios such as development and production. In the default project template, alternative exception handling is added with UseDeveloperExceptionPage
and UseDatabaseErrorPage
middleware.
Other middleware used by default includes:
UseStaticFiles
allows the application to serve static resources.UseIdentity
enables ASP.NET authentication for the application.UseMvc
adds MVC to the pipeline and allows configuration of routing. This ability to add application features ad-hoc gives developers the flexibility to adapt the application to fit their needs.
Now Compatable with Cross Platform Development on ASP.NET Core
Telerik UI for ASP.NET MVC is a comprehensive collection of over 70 user interface components built with Kendo UI. Just as ASP.NET Core can run on Windows, Mac, Linux, and Docker, so can UI for MVC. In addition to supporting the cross-platform deployment model of .NET Core, UI For MVC is also able to render for any screen size, on any device using responsive and adaptive rendering techniques.
Even though UI for MVC is primarily a user interface library, it still needs access to application configurations and the HTTP pipeline for activities like making calls from JavaScript to the server endpoints.
Plugging Telerik controls into the application is straight forward, just like other ASP.NET Core components. Start by adding the Kendo UI services to the services container.
public void ConfigureServices(IServiceCollection services)
{
...
// Add Kendo UI services to the services container
services.AddKendo();
}
Next, the Kendo UI configuration is set.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
// Configure Kendo UI
app.UseKendo(env);
}
ASP.NET Core is a new generation of ASP.NET applications built to run everywhere. It allows greater flexibility and control over the initialization, configuration and customization. Each part of the application's initialization is designed to be intuitive with a clear separation of responsibility.
For more details on all aspects of ASP.NET Core development, download the free whitepaper "ASP.NET Core MVC Changes Every Developer Should Know".
If you'd like to learn more about using the .NET CLI for cross-platform development with .NET, check out our whitepaper, The Command Line: Reinvented for Modern Developers.
Image by Norlando Pobre https://flic.kr/p/4XTMLu, modified by Ed Charbeneau
Ed