本系列代码全部采用.NET 6.0

ASP.NET Core应用

注册服务器与中间件

  • 从应用承载或寄宿(Hosting)方面看,.NET Core具有一个以IHost/IHostBuilder为核心的服务承载系统。任何需要长时间运行的操作都可以定义成IHostedService服务并通过该系统来承载。
  • IHost对象可以视为所有承载服务的宿主(Host),IHostBuilder对象则是它的构造者(Builder)。
  • 一个ASP.NET Core应用本质上就是一个用来监听、接收和处理HTTP请求的后台服务,所以它被定义为一个GenericWebHostService(实现了IHostedService接口),并将它注册到承载系统中,进而实现了针对ASP.NET Core应用的承载。

    1. 服务类型

  • ASP.NET Core提供了几种原生的服务类型:

    • KestrelServer
      • 一种采用libuv创建的跨平台的Web服务器,可以在Windows、macOS和Linux平台上使用
      • 不仅可以作为独立的Web服务器直接对外提供服务,还可以结合传统的Web服务器(IIS、Apache、Nginx)将它们作为反向代理来使用
    • HTTP.sys
      • 一种只能在Windows平台上使用的Web服务器
      • 本质上是一个在操作系统内核模式运行的驱动,所以能够提供非常好的性能

        2. 将控制台应用程序转为ASP.NET Core应用

        (1)项目文件

        ```xml Exe net6.0 enable enable
  • ```

    (2)主程序文件

    ```csharp using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting;

Host.CreateDefaultBuilder() .ConfigureWebHost(builder => //构建管道->针对管道的配置 { builder.UseKestrel(); //将KestrelServer注册为服务器 //注册用来处理请求的中间件 builder.Configure(app => { app.Run(context => context.Response.WriteAsync(“Hello World”)); }); }).Build().Run();

  1. - 调用静态类型`Host``CreateDefaultBuilder`方法创建了一个`IHostBuilder`对象,并最终调用该对象的`Build`方法构建作为服务宿主的`IHost`对象。当调用`IHost`对象的`Run`扩展方法时,ASP.NET Core应用程序将会被启动。
  2. - `Build`方法调用之前,可以先调用`IHostBuilder`接口的`ConfigureWebHost`扩展方法,并利用指定的`Action<IWebHostBuilder>`委托对象**构建**ASP.NET Core应用的**请求处理管道**。
  3. - 在管道配置中,调用`IWebHostBuilder`接口的`UseKestrel`扩展方法将`KestrelServer`注册为服务器。
  4. - 在管道配置中,调用`Configure`扩展方法注册用来处理请求的中间件。扩展方法的输入参数时一`Action<IApplicationBuilder>`对象,所需的中间件注册在`IApplicationBuilder`对象上。
  5. - 在中间件配置中,调用`IApplicationBuilder`接口的`Run`扩展方法注册了一个中间件。该中间件利用指定的`Func<HttpContext, Task>`对象将响应的主题内容设置为"Hello World"
  6. <a name="GyMcn"></a>
  7. ### 3. LaunchSettings.json
  8. <a name="QC3Km"></a>
  9. #### (1)修改SDK
  10. - 每个.NET Core应用都针对一种具体的SDK类型。在项目文件中的`<Project Sdk="">`根节点设置了当前项目采用的SDK类型。
  11. - 控制台应用默认采用的SDK类型为"Microsoft.NET.Sdk",而ASP.NET Core应用通常采用另一种名为"Microsoft.NET.Sdk.Web"SDK类型。在这种类型下,可以将"Microsoft.AspNetCore.App"的框架引用从项目文件中删除。
  12. ```xml
  13. <Project Sdk="Microsoft.NET.Sdk.Web">
  14. <PropertyGroup>
  15. <TargetFramework>net6.0</TargetFramework>
  16. <ImplicitUsings>enable</ImplicitUsings>
  17. <Nullable>enable</Nullable>
  18. </PropertyGroup>
  19. </Project>
  • 重新编译后,会生成/Properties/launchSettings.json文件。

    (2)lunchSettings.json文件说明

    {
    "iisSettings": {
      "windowsAuthentication": false,
      "anonymousAuthentication": true,
      "iisExpress": {
        "applicationUrl": "http://localhost:60646/",
        "sslPort": 44332
      }
    },
    "profiles": {
      "IIS Express": {
        "commandName": "IISExpress",
        "launchBrowser": true,
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
        }
      },
      "helloworld": {
        "commandName": "Project",
        "launchBrowser": true,
        "environmentVariables": {
          "ASPNETCORE_ENVIRONMENT": "Development"
        },
        "applicationUrl": "https://localhost:5001;http://localhost:5000"
      }
    }
    }
    
  • 其中,iisSettings节点用于设置IIS相关的选项,而profiles节点定义了一系列用于描述应用启动场景的Profile。

  • 初始的文件会创建两个Profile,一个被命名为”IIS Express”,另一个则使用应用名称命名。每个Profile相当于定义了应用的启动场景,相关的设置包括应用启动的方式、环境变量和URL等,具体包含:
    • commandName
      • 启动当前应用程序的命令类型,有效的选项包括IIS、IISExpress、Executable和Project
    • executablePath
      • 如果commandName被设置为Executable,就需要利用该属性设置启动可执行文件的路径(绝对路径或相对路径)
    • environmentVariables
      • 该属性用来设置环境变量。由于lanuchSettings.json文件仅仅在开发环境中使用,所以默认会添加一个名为”ASPNETCORE_ENVIRONMENT”的环境变量,并将它的值设置为”Development”用以表示当前部署环境
    • commandLineArgs
      • 命令行参数,即传入Main方法的参数列表
    • workingDirectory
      • 工作目录的绝对路径
    • applicationUrl
      • 应用程序采用的URL列表,多个URL直接用分号( ; )进行分隔
    • launchBrowser
      • 布尔类型的开关,表示应用程序启动时是否自动启动浏览器
    • launchUrl
      • 如果launchBrowser被设置为True,浏览器采用的初始化路径就通过该属性进行设置
    • nativeDebugging
      • 是否启动本地代码调试,默认值为False
    • externalUrlConfiguration
      • 如果该属性设置为True,意味着禁用本地的配置,默认值为False
    • use64Bit
      • 如果commandName属性被设置为IIS Express,该属性将决定采用X64版本还是X86版本,默认值为False,意味着ASP.NET Core应用默认采用X86版本的IIS Express
        • lunchSettings.json文件中的所有设置仅仅针对开发环境,在产品环境下不需要这个文件。应用发布后生成的文件列表也不包含该文件。
        • 通过项目属性-Debug选项可用图形界面来设置该文件的相关内容。

4. 显式指定URL

  • 如果既不使用launchSettings.json文件中定义的URL,也不是有KestrelServer默认采用的监听地址,可以在应用程序中显式指定应用的URL。只需在管道配置中添加如下代码: ```csharp Host.CreateDefaultBuilder() .ConfigureWebHost(builder => //构建管道-》针对管道的配置 {
       builder.UseKestrel();    //将KestrelServer注册为服务器
    
  • builder.UseUrls(“http://localhost:5010;https://localhost:5011“); //注册用来处理请求的中间件 builder.Configure(app => {
    app.Run(context => context.Response.WriteAsync("Hello World"));
    
    }); }).Build().Run(); ```

    5. ConfigureWebHostDefault

  • 对于上面的.ConfigureWebHost管道配置方法,可以使用ConfigureWebHostDefault方法替代,它会做一些默认设置,如:KestrelServer无需显式注册。具体详见13章。
  • 使用.ConfigureWebHost时无法用IIS Express访问。

ASP.NET Core MVC应用

  • 由于ASP.NET Core框架在本质上就是由服务器和中间件构建的消息处理管道,所以在它上面构建的应用开发框架都建立在某种类型的中间件上。
  • 整个ASP.NET Core MVC开发框架就是建立在用来实现路由的EndpointRoutingMiddleware中间件和EndpointMiddleware中间件上的。
  • ASP.NET Core MVC利用路由系统为它分发请求,并在此基础上实现针对目标Controller的激活、Action方法的选择和执行,以及最终对于执行结果的响应。

    注册服务与中间件

  • 整个框架建立在EndpointRoutingMiddleware和EndpointMiddleware中间件构建的路由系统上。这两个中间件采用”终结点(Endpoint)映射”的方式实现针对HTTP请求的路由。

  • 这里所谓的终结点可以视为应用程序提供的针对HTTP请求的处理器。这两个中间件通过预先设置的规则将具有某些特征的请求(如路径、HTTP方法等)映射到对应的终结点,进而实现路由的功能。
  • 对于一个MVC应用程序来说,定义在Controller类型中的Action方法可以视为一个终结点,路由映射最终体现在HTTP请求与目标Action方法的映射上。

    Host.CreateDefaultBuilder()
      .ConfigureWebHostDefaults(builder =>    //构建管道-》针对管道的配置
      {
          builder.ConfigureServices(services =>
          {
              services.AddRouting();
              services.AddControllersWithViews();
          });
          //注册用来处理请求的中间件
          builder.Configure(app =>
          {
              app.UseRouting();
              app.UseEndpoints(endpoints => endpoints.MapControllers());
          });
      }).Build().Run();
    
  • 在中间件配置中,先后调用IApplicationBuilder接口的UseRouting方法与UseEndpoints方法注册了EndpointRoutingMiddleware和EndpointMiddleware中间件。

  • 在调用UseEndpoints方法时,利用指定的Action委托对象调用了IEndpointRouteBuilder接口的MapControllers扩展方法,该方法完成了针对定义在Controller类型中所有Action方法的映射。

    在.NET 6.0中的顶级语句中,可以直接使用app.MapControllers()来注册路由中间件,而不必使用app.UseRouting和app.UseEndpoints。

  • 由于注册的中间件具有对相关服务的依赖,故需预先将这些服务注册到依赖注入框架中。
  • 依赖服务的注册是通过调用IWebHostBuilder接口的ConfigureServices方法完成的。该方法参数类型为Action,添加的服务注册就保存在IServiceCollection接口的集合中。

    注册Startup类型

  • 任何一个ASP.NET Core应用在初始化时都会根据请求处理的需求注册对应的中间件。在大部分真实的开发场景中,一般将中间件及以来服务的注册定义在一个单独的类中。按照约定,通常命名为Startup:

    public class Startup
    {
      public void ConfigureServices(IServiceCollection services)
      {
          services.AddRouting();
          services.AddControllersWithViews();
      }
    
      public void Configure(IApplicationBuilder app)
      {
          app.UseRouting();
          app.UseEndpoints(endpoints => endpoints.MapControllers());
      }
    }
    
  • 由于已经将两种核心操作转移到Startup类中,故此时需要注册该类型。

  • 通过调用IWebHostBuilder接口的UseStartup扩展方法进行注册:
    Host.CreateDefaultBuilder()
      .ConfigureWebHostDefaults(builder =>    //构建管道-》针对管道的配置
      {
          builder.UseStartup<Startup>();
      }).Build().Run();