MVC 02.mp4 (155.79MB)

文件的伺服

传统 ASP.NET

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

ASP.NET Core

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

ASP.NET Core Meta Package

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

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

WebHost 源码分析

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

  1. builder.UseKestrel((builderContext, options) =>
  2. {
  3. options.Configure(builderContext.Configuration.GetSection("Kestrel"));
  4. })
  5. .ConfigureServices((hostingContext, services) =>
  6. {
  7. // Fallback
  8. services.PostConfigure<HostFilteringOptions>(options =>
  9. {
  10. if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
  11. {
  12. // "AllowedHosts": "localhost;127.0.0.1;[::1]"
  13. var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
  14. // Fall back to "*" to disable.
  15. options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
  16. }
  17. });
  18. // Change notification
  19. services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
  20. new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
  21. services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
  22. })
  23. .UseIIS()
  24. .UseIISIntegration();
  • UseKestel 使用了项目内嵌的 Kestrel 服务器
  • UseIIS 使用了外部的 IIS 服务器
  • 所以一个 HTTP 请求会先到 IIS,再被中继到 Kestrel,处理后再先 Kestrel 后 IIS 返回
  1. config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  2. .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
  • 默认配置加载 appsettings.json
  • 也可以根据环境加载不同配置文件
  1. .ConfigureLogging((hostingContext, logging) =>
  2. {
  3. logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
  4. logging.AddConsole();
  5. logging.AddDebug();
  6. logging.AddEventSourceLogger();
  7. }).

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

  1. UseDefaultServiceProvider((context, options) =>
  2. {
  3. options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
  4. });

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

  1. .ConfigureServices((hostingContext, services) =>
  2. {
  3. // Fallback
  4. services.PostConfigure<HostFilteringOptions>(options =>
  5. {
  6. if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
  7. {
  8. // "AllowedHosts": "localhost;127.0.0.1;[::1]"
  9. var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
  10. // Fall back to "*" to disable.
  11. options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
  12. }
  13. });
  14. // Change notification
  15. services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
  16. new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration));
  17. services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
  18. })

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

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

依赖注入,IoC 容器

依赖注入的生命周期

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

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

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

依赖注入的好处

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

管道与中间件

Startup 类的 Configure 方法里面进行管道和中间件的配置。

管道示意图:
image.png

完整 Web 请求的流程:
image.png

切换启动配置

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

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

  1. {
  2. "iisSettings": {
  3. "windowsAuthentication": false,
  4. "anonymousAuthentication": true,
  5. "iisExpress": {
  6. "applicationUrl": "http://localhost:53994",
  7. "sslPort": 44374
  8. }
  9. },
  10. "profiles": {
  11. "IIS Express": {
  12. "commandName": "IISExpress",
  13. "launchBrowser": true,
  14. "environmentVariables": {
  15. "ASPNETCORE_ENVIRONMENT": "Development"
  16. }
  17. },
  18. "CoreDemo": {
  19. "commandName": "Project",
  20. "launchBrowser": true,
  21. "applicationUrl": "https://localhost:5001;http://localhost:5000",
  22. "environmentVariables": {
  23. "ASPNETCORE_ENVIRONMENT": "Development"
  24. }
  25. }
  26. }
  27. }

中间件测试

  1. // 配置 HTTP 请求管道
  2. // 管道:配置我们的 Web 应用如何响应 HTTP 请求
  3. // 管道里面放的东西就是中间件,MVC 就是一个中间件
  4. public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILogger<Startup> logger)
  5. {
  6. if (env.IsDevelopment())
  7. {
  8. app.UseDeveloperExceptionPage();
  9. }
  10. app.Use(async (context, next) =>
  11. {
  12. logger.LogInformation("M1 Start");
  13. await context.Response.WriteAsync("Hello World!");
  14. await next();
  15. logger.LogInformation("M1 End");
  16. });
  17. app.Run(async (context) =>
  18. {
  19. logger.LogInformation("M2 Start");
  20. await context.Response.WriteAsync("Another Hello!");
  21. logger.LogInformation("M2 End");
  22. });
  23. }

image.png

源码

CoreDemo.zip