[ASP.NET Core MVC 入门教程笔记] P2 MVC02

文件的伺服

传统 ASP.NET

  • 根目录的文件都被伺服
  • 某些重要文件不会被伺服
  • 黑名单策略

ASP.NET Core

  • 只有 wwwroot 被伺服
  • 白名单策略

项目配置文件(.csproj)

<PackageReference Include="Microsoft.AspNetCore.App" /> 引用的库是一个整合库称为 Meta PackageASP.NET Core Meta Package。它没有具体版本号,默认引用电脑上最新的版本。它包括:

  • 仅有的几个第三方库:Json.NET,Remotion.Linq 和 IX-Async
  • 它们是保证框架功能所必需的
  • 所有 ASP.NET Core 团队支持的库,包含第三方依赖项(除上面三个外)的库除外
  • 所有 Entity Framework Core 团队支持的库,包含第三方依赖项(除上面三个外)的库除外

启动和配置

  • Program类:Main方法 也可以进行配置 其中有默认配置

 public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();

CreateDefaultBuilder 方法是对 WebHost进行配置

源码地址:https://github.com/aspnet/MetaPackages/blob/master/src/Microsoft.AspNetCore/WebHost.cs

其中对HTTP请求的处理部分:

builder.UseKestrel((builderContext, options) =>
{
    options.Configure(builderContext.Configuration.GetSection("Kestrel"));
})
.ConfigureServices((hostingContext, services) =>
{
    // Fallback
    services.PostConfigure<HostFilteringOptions>(options =>
    {
        if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
        {
            // "AllowedHosts": "localhost;127.0.0.1;[::1]"
            var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            // Fall back to "*" to disable.
            options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
        }
    });
    // Change notification
    services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
                new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));

    services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
})
.UseIIS()
.UseIISIntegration();

所以可以看到:

  • UseKestel 使用了项目内嵌的 Kestrel 服务器
  • UseIIS 使用了外部的 IIS 服务器
  • 所以一个 HTTP 请求会先到 IIS,再被中继到 Kestrel,处理后再先 Kestrel 后 IIS 返回

 对配置文件读取的配置;

config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

也就是说:

  • 默认配置加载 appsettings.json
  • 也可以根据环境加载不同配置文件

 配置 logging 时,默认输出到 Console、Debug 和 EventSourceLogger 三个地方。

.ConfigureLogging((hostingContext, logging) =>
{
    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
    logging.AddConsole();
    logging.AddDebug();
    logging.AddEventSourceLogger();
}).

使用自带的依赖注入容器。

.ConfigureServices((hostingContext, services) =>
{
    // Fallback
    services.PostConfigure<HostFilteringOptions>(options =>
    {
        if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
        {
            // "AllowedHosts": "localhost;127.0.0.1;[::1]"
            var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            // Fall back to "*" to disable.
            options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
        }
    });
    // Change notification
    services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
                new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));

    services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
})

 

ConfigureServices 主要用来添加一些类型到依赖注入容器中。

WebHost 进行了很多的默认配置,如果你需要修改配置,它的代码很有参考意义,参考它对Program.cs进行修改。

  • Startup类:主要用于进行配置

两个方法: Configure和ConfigureServices(配置依赖注入)

将一个类看作一个服务,在ConfigureServices中注册之后的类就可以被别的类调用。

依赖注入,IoC 容器

依赖注入的生命周期

  • Transient:每次被请求都会创建新的实例
  • Scoped:每次 Web 请求会创建一个实例
  • Singleton:一旦被创建实例,就会一直使用这个实例,直到应用停止

Startup 类的 ConfigureServices 方法里面进行依赖注入配置。

public void ConfigureServices(IServiceCollection services)
{
    // 每当有其他类请求 ICinemaService 时,容器都会返回 CinemaMemoryService 的实例
    services.AddSingleton<ICinemaService, CinemaMemoryService>();
    services.AddSingleton<IMovieService, MovieMemoryService>();
}

依赖注入的好处

  • 不用去管生命周期
  • 类型之间没有依赖,有利于单元测试

如何实现依赖注入

[ASP.NET Core MVC 入门教程笔记] P2 MVC02

.Models中是模型类,在项目名点右键新建Library即可,需要被CoreDemo引用。

在项目中建立一个新文件夹Services,其中有四个类/接口,类名以I开头的是接口,对应的memory类是其实现的类。在Startup.cs中,通过接口将服务注入。

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<ICinemaService, CinemaMemoryService>();
            services.AddSingleton<IMovieService, MovieMemoryService>();
        }

Configure方法中是配置管道和中间件(MVC...)

管道示意图:

[ASP.NET Core MVC 入门教程笔记] P2 MVC02

 

完整 Web 请求的流程:请求的过程和返回的过程顺序相反。
[ASP.NET Core MVC 入门教程笔记] P2 MVC02

 Kestrel是轻量级的代理服务器,IIS是反向代理服务器。一般的部署在Kerestrel也可以,但是最好用IIS,因为负载均衡之类都是在这里实现的。

中间件测试

Use就是可以转向下一个中间件,Run的话结束就返回了。

这里要用控制台看日志。

// 配置 HTTP 请求管道
// 管道:配置我们的 Web 应用如何响应 HTTP 请求
// 管道里面放的东西就是中间件,MVC 就是一个中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILogger<Startup> logger)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.Use(async (context, next) =>
    {
        logger.LogInformation("M1 Start");
        await context.Response.WriteAsync("Hello World!");
        await next();
        logger.LogInformation("M1 End");
    });

    app.Run(async (context) =>
    {
        logger.LogInformation("M2 Start");
        await context.Response.WriteAsync("Another Hello!");
        logger.LogInformation("M2 End");
    });
}

[ASP.NET Core MVC 入门教程笔记] P2 MVC02

切换启动配置

 

可以通过选择项目名,使用 Kestrel 服务器进行调试,而不是默认的 IIS Express。

[ASP.NET Core MVC 入门教程笔记] P2 MVC02

 

可以通过项目 Properties 下的 launchSettings.json 修改启动配置。

{
  "iisSettings": {
    "windowsAuthentication": false, 
    "anonymousAuthentication": true, 
    "iisExpress": {
      "applicationUrl": "http://localhost:53994",
      "sslPort": 44374
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "CoreDemo": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:5001;http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}