官术网_书友最值得收藏!

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;
})
Since ASP.NET Core 2.0, WebListener is called HTTP.sys.

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" } } } }
Where I have "Web", you should have the name of your application.

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.

We read about server features in this chapter. Application events are discussed in Chapter 18, gRPC and Other Topics.

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.

主站蜘蛛池模板: 东光县| 积石山| SHOW| 铜陵市| 通化市| 龙里县| 张家界市| 云安县| 兴化市| 贺兰县| 嘉兴市| 库车县| 唐河县| 敖汉旗| 应城市| 额敏县| 衡南县| 大宁县| 古丈县| 双城市| 贵州省| 特克斯县| 榆社县| 常宁市| 图片| 胶南市| 黄山市| 宣恩县| 益阳市| 聂荣县| 蚌埠市| 始兴县| 荣昌县| 民勤县| 深水埗区| 福海县| 临夏县| 攀枝花市| 云南省| 孟州市| 卢氏县|