- Modern Web Development with ASP.NET Core 3
- Ricardo Peres
- 1789字
- 2021-06-18 18:35:53
Hosting ASP.NET Core
You probably noticed, when we talked about OWIN, that I mentioned that the sample app was hosted in Kestrel. Kestrel is the name of a platform-independent web server fully written in .NET Core (of course, using the native libraries of your operating system). You need to host your web application somewhere, and .NET Core offers the following options:
- Kestrel: Platform independent, your host of choice if you want to have your code run on any platform.
- WebListener: A Windows-only host, offering significant performance advantages over Kestrel, but also has the disadvantage of needing Windows; starting with ASP.NET Core 2, it is now called HTTP.sys.
- IIS: As in the past, you can continue to host your web app in IIS, on Windows, benefiting from the old pipeline and configuration tools.
A server in this context is merely an implementation of IServer, an interface defined in the Microsoft.AspNetCore.Hosting NuGet package. This defines the base contract that a server offers, which can be described as follows:
- A Start method, where all the fun begins. It is responsible for creating the HttpContext, setting up the Request and Response properties, and calling the conventional Configure method.
- A collection of Features that are supported by the implementation. There are dozens of features, but at the very least, a server needs to support IHttpRequestFeature and IHttpResponseFeature.
Each of these server implementations is provided in NuGet packages:

IIS cannot be used on its own. IIS is, of course, a Windows-native application and is therefore not available through NuGet, but the Microsoft.AspNetCore.Server.IISIntegration package includes the IIS ASP.NET Core module, which needs to be installed in IIS so that it can run ASP.NET Core apps with Kestrel (WebListener is not compatible with IIS). There are, of course, other server implementations by third-party providers (take, as an example, Nowin, available at https://github.com/Bobris/Nowin). The ASP.NET Core module acts as a reverse proxy, receiving requests through IIS and then calling ASP.NET Core, in the same process space. Other reverse proxies are Apache and NGINX. Reverse proxies are useful because they provide additional features that are not part of ASP.NET Core; they accept requests, do their magic, and forward the requests to ASP.NET Core so that it too can do its magic.
So, what is there to know about these, and how can we select one of these hosting servers?
Kestrel
Kestrel is the default, multiplatform, web server. It offers acceptable performance, but lacks lots of features that are expected in real life:
- No support for Windows authentication (as time passes, this becomes less of a problem)
- No direct file transmission
- No strong security protection (large requests, and more)
From this, it should be clear that Kestrel is not meant to be used in production unless it is sitting behind a reverse proxy (such as NGINX, Apache, or IIS). It is configured at bootstrap through the UseKestrel extension method, and if you need to configure its options, you will need to supply an additional lambda:
Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder=> { webBuilder
.UseStartup<Startup>()
.UseKestrel(opt => { opt.Limits.MaxConcurrentConnections =
10; })
});
You can read more about it at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel.
WebListener/HTTP.sys
This one is for Windows only, as it is a wrapper around HTTP.sys, the Windows subsystem that handles web requests. It offers by far the best performance, supports HTTP/2, WebSockets, Windows Authentication, direct file transmission, port sharing, response caching, and mostly anything that you can think of. The disadvantage, of course, is that it requires Windows 7 or Windows Server 2008 R2 and later. At bootstrap, use the UseWebListener extension method to add it to the host builder, possibly with a configuration parameter:
.UseWebListener(opt => { opt.ListenerSettings.Authentication.AllowAnonymous = false; })
IIS
We already know about IIS. IIS can be used as a reverse proxy for Kestrel, or to add features that the host does not support, such as Windows Authentication. For that, we should include support for IIS by calling UseIISIntegration. Here, the configuration should be done through the Web.config file, which in this case is a requirement (the Visual Studio template will add this file to the root of your project).
NGINX
NGINX (pronounced EngineX) is a UNIX and Linux reverse proxy that can be used with ASP.NET Core. We will talk a bit more about NGINX in Chapter 19, Application Deployment.
Apache
Apache, the popular UNIX and Linux server (which actually also runs in Windows) can also act as a reverse proxy. You can find more information in Chapter 17, Deployment.
Configuration
As we've seen, usually, the server is chosen using a Host instance. As a minimum, you need to tell it which server to use and what the root directory is:
Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder=> { webBuilder
.UseStartup<Startup>()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory()); });
Actually, the calls to UseKestrel and UseContentRoot(Directory.GetCurrentDirectory()) are already done by ConfigureWebHostDefaults, so you can skip them.
Features
Different servers will offer different features. Essentially, a feature in this context is just a configuration that is available per request and offers properties that can be inspected and changed. Here are some of the features that are included out of the box:

This is by no means the full list, as it may change, depending on your exact configuration (your choice of host, and so on). There is no base interface for features. All of these features can be obtained through the Features property of the Serveror from theHttpContext by requesting its interface:
var con = HttpContext.Features.Get<IHttpConnectionFeature>();
This is one way to obtain access to the functionality that the feature supplies, but for some features, there are workarounds. For example, the ASP.NET Session object can be obtained directly from the HttpContext. Features are essentially how the HttpContext class gets the behavior it exposes; for example, request and response objects, sessions, and more. Middleware classes can provide their own features so that they are available downstream by adding them directly to the Features collection:
HttpContext.Features.Set(new MyFeature());
There can be only one feature per type—for example, one per IMyFeature1, one per IMyFeature2, and so on.
Launch configuration
Visual Studio can have more than one configuration per project, meaning that it can launch your project in several ways, and there's a toolbar button that shows just this fact:
In particular, we can choose whether to launch our web application using IIS (or IIS Express) as the host, or use whatever is specified in the code(Kestrel or HTTP.sys). The launch settings are stored in thePropertieslaunchSettings.jsonfile, which is created by default by Visual Studio. This file has the following (or similar) contents:
{ "iisSettings": { "windowsAuthentication": true, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:24896/",
"sslPort": 0 } }, "profiles": { "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "Web": { "commandName": "Project", "launchBrowser": true, "launchUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
Here, we can see the default ports plus the environment name to be used (to be discussed shortly). This file does not need to be changed by hand (although it can be); you can see it in visual form using the project properties:
Let's now look at a special case in which the port needs to be set dynamically.
Setting the listen port and address
There may be a need for setting the listen port—for example, you already have one or more servers running on the same machine. When this happens, you can either pick one port that you are sure is not being used or you can let ASP.NET Core pick one for you. Setting the listen address is also relevant if you want to restrict where you want to accept requests from. There are many ways to achieve this; let's go through them one by one.
By default, ASP.NET Core accepts requests at the following locations:
- http://localhost:5000
- https://localhost:5001 (when using a local certificate)
Using the command line
When you start your application using dotnet, you can pass the --urls parameter to specify the URLs to which it should listen:
dotnet run --urls "http://localhost:5000;https://localhost:5001"
This, of course, is static. Here you specify that you are binding HTTP to localhost only, on port 5000 and HTTPS to localhost too, on port 5001. If you want to bind to any host, you should use 0.0.0.0 instead of localhost.
This approach is a good one for Docker deployments. Let's nowsee how to do this, using environment variables.
Using environment variables
Another alternative is to use the ASPNETCORE_URLS environment variables. It is basically the same as the previous approach:
//Linux, MacOS
export ASPNETCORE_URLS="http://localhost:5000;https://localhost:5001"
//Windows
set ASPNETCORE_URLS="http://localhost:5000;https://localhost:5001"
This is also OK for Docker.
Next, let's look at how to use the configuration file for Visual Studio.
Using launchSettings.json
The launchSettings.json is where Visual Studio keeps the configuration details for running a web solution. Its structure looks like this:
{"iisSettings":{"windowsAuthentication":false,"anonymousAuthentication":true,"iisExpress":{"applicationUrl":"http://localhost:7788","sslPort":44399}},"profiles":{"IIS Express":{"commandName":"IISExpress","launchBrowser":true,"environmentVariables":{"ASPNETCORE_ENVIRONMENT":"Development"}},"Web":{"commandName":"Project","launchBrowser":true,"environmentVariables":{"ASPNETCORE_ENVIRONMENT":"Development"},"applicationUrl":"https://localhost:5001;http://localhost:5000"}}}
You can see where the URLs, address, and port are specified in bold, and where you can change them. For IIS Express, you need to edit the .vs\config\applicationhost.config, located inside the root solution folder.
This approach is, of course, only for local development.
Using code
We can also specify the listen addresses in code, which is more useful for dynamic cases, where we want to build the address dynamically:
publicstaticIHostBuilderCreateHostBuilder(string[] args) => Host
.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder=> { webBuilder.UseStartup<Startup>() .UseUrls("http://localhost:5000",
"https://localhost.5001"); });
Setting ports dynamically
What if we need to use a dynamically assigned port? This may occur when the port that we'd like to use is already taken. ASP.NET Core fully supports this by setting the port to 0, but this needs to be done at the actual host level. This only works with Kestrel; HTTP.sys does not support this. Let's see how we can do this:
publicstaticIHostBuilderCreateHostBuilder(string[] args) => Host
.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder=> { webBuilder.UseStartup<Startup>() .UseKestrel(options =>
{
options.ListenAnyIP(0);
});
});
If you want to find out which addresses we are using, you must make use of a feature called IServerAddressesFeature. One way to do this is to have a look at it in the Configure method, but only after the application starts:
public void Configure(IApplicationBuilderapp, IWebHostEnvironmentenv, IHostApplicationLifetimeevents)
{
events.ApplicationStarted.Register(() => { varfeature=app.ServerFeatures.Get<IServerAddressesFeature>(); varaddresses=feature.Addresses; });
//rest goes here
}
This example illustrates two concepts: server features and host application events. I register a handler to the ApplicationStarted event, and when it is raised, I ask for a server feature, IServerAddressesFeature, that contains all the addresses, including ports, that my application is currently bound to. From here, I can see the port that was chosen.
Now that we've learned the basics of hosting, let's now focus on another key aspect of ASP.NET Core: the inversion of control and the DI framework pattern.
- Learning RxJava
- Visual FoxPro 程序設計
- 碼上行動:零基礎學會Python編程(ChatGPT版)
- Learning FuelPHP for Effective PHP Development
- SQL Server從入門到精通(第3版)
- Instant PHP Web Scraping
- Backbone.js Testing
- 大數據時代的企業升級之道(全3冊)
- Python 3快速入門與實戰
- C語言程序設計教程
- Android開發權威指南(第二版)
- Natural Language Processing with Python Cookbook
- 大話C語言
- SEO的藝術(原書第2版)
- 片上系統設計思想與源代碼分析