内容来自书籍:
Pro ASP.NET Core 6
Develop Cloud-Ready Web Applications Using MVC, Blazor, and Razor Pages (Ninth Edition)Author: Adam Freeman
需要该电子书的小伙伴,可以留下邮箱,有空看到就会发送的
配置数据的主要来源是 appsetings.json 文件
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
配置服务不理解 appsetings.JSON 文件中配置部分或设置的含义,只负责处理 JSON 数据文件,并将配置设置与从其他来源获得的值(如环境变量或命令行参数)合并。结果是一组分层的配置属性
大多数项目包含多个 JSON 配置文件,允许为开发周期的不同部分定义不同的设置。有三个预定义的环境,分别命名为Development、Staging和Production,每个环境都对应于开发的一个常用阶段。在启动过程中,配置服务查找名称包含当前环境的 JSON 文件。默认的环境是 Development,这意味着配置服务将加载 appsettings.Development.json 文件并使用其内容来补充主 appsetings.json 文件的内容。
通过服务访问配置数据。如果您只需要配置数据来配置中间件,那么可以使用一个参数来声明对配置服务的依赖
app.MapGet("config", async (HttpContext context, IConfiguration config) => { string defaultDebug = config["Logging:LogLevel:Default"]; await context.Response .WriteAsync($"The config setting is: {defaultDebug}"); });
var servicesConfig = builder.Configuration;
var pipelineConfig = app.Configuration;
builder.Services.Configure<MessageOptions>(servicesConfig.GetSection("Location"));
使用 GetSection 方法获取配置数据,并在创建选项时将配置数据传递给 Configure 方法。检查选定部分中的配置值,并使用它们将选项类中的默认值替换为相同的名称。
{ "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:5000", "sslPort": 0 } }, "profiles": { "Platform": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
Properties 文件夹中的 launchSettings.JSON 文件包含启动 ASP.NET Core 平台的配置设置,包括用于侦听 HTTP 和 HTTPS 请求的 TCP 端口以及用于选择附加 JSON 配置文件的环境。
iisSettings 部分用于配置 ASP.NET Core 平台通过 IIS Express 启动时使用的 HTTP 和 HTTPS 端口,这是部署 ASP.NET Core 旧版本的方式。
配置文件部分描述了一系列启动配置文件,这些配置文件为运行应用程序的不同方式定义了配置设置。Platform 部分定义了 dotnet run 命令使用的配置。IISExpress 部分定义与 IISExpress 一起使用应用程序时所使用的配置。
这两个概要文件都包含一个 Environmental Variables 部分,该部分用于定义添加到应用程序的配置数据中的环境变量。默认情况下只有一个环境变量: ASPNETCORE _ ENVIRONMENT
ASP.NET Core 平台提供了用于确定当前环境的 IWebHostEnvironment 服务,从而避免了手动获取配置设置的需要
var servicesEnv = builder.Environment;
var pipelineEnv = app.Environment;
app.MapGet("config", async (HttpContext context, IConfiguration config, IWebHostEnvironment env) => { string defaultDebug = config["Logging:LogLevel:Default"]; await context.Response .WriteAsync($"The config setting is: {defaultDebug}"); await context.Response .WriteAsync($"\nThe env setting is: {env.EnvironmentName}"); });
在开发过程中,通常需要使用敏感数据来处理应用程序所依赖的服务。这些数据可以包括 API 密钥、数据库连接密码或默认的管理帐户,它既用于访问服务,也用于重新初始化服务,以使用新的数据库或用户配置测试应用程序更改。
如果敏感数据包含在 C # 类或 JSON 配置文件中,它将被check-in源代码版本控制存储库,并对所有开发人员和任何其他能够看到代码的人可见ーー这可能意味着对那些拥有开放存储库或安全性差的存储库的项目可见。
用户保密服务允许敏感数据存储在一个文件中,这个文件不属于项目的一部分,也不会被check-in版本控制,允许每个开发人员拥有敏感数据,这些数据不会通过版本控制check-in意外暴露
安装工具
dotnet tool uninstall --global dotnet-user-secrets dotnet tool install --global dotnet-user-secrets
此命令将一个元素添加到 Platform 项目文件中,该文件包含与每台开发人员机器上的机密相关联的项目的唯一 ID
dotnet user-secrets init
dotnet user-secrets set "WebService:Id" "MyAccount" dotnet user-secrets set "WebService:Key" "MySecret123$"
每个 secret 都有一个键和一个值,相关的 secret 可以通过使用一个公共前缀、后跟冒号(: 字符)、后跟机密名称来组合在一起
dotnet user-secrets list
查看文件内容
然后在上面这些命令都成功后,会自动生成一个文件在~/.microsoft/usersecrets中
User secrets与常规配置设置合并,并以相同的方式访问
string wsID = config["WebService:Id"]; string wsKey = config["WebService:Key"];
只有在将应用程序设置为 Development 环境时才加载User secrets。
日志消息被发送到日志提供程序,后者负责将消息转发到可以看到、存储和处理它们的位置。有用于基本日志记录的内置提供程序,还有一系列可用于将消息提供到日志框架中的第三方提供程序,这些日志框架允许对消息进行整理和分析
public static async Task Endpoint(HttpContext context, ILogger<Population> logger) { logger.LogDebug($"Started processing for {context.Request.Path}"); }
日志记录服务根据分配给消息的类别将消息记录在一起。日志消息使用 ILogger < T > 接口编写,其中通用参数 T 用于指定类别。约定是使用生成消息的类的类型作为类别类型
app.Logger.LogDebug("Pipeline configuration starting");
如果希望指定日志的类型
var logger = app.Services .GetRequiredService<ILoggerFactory>().CreateLogger("Pipeline");
{ "Logging": { "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information", "Microsoft.AspNetCore": "Debug" } } }
ASP.NET Core 包括用于生成日志消息的内置中间件,这些日志消息描述应用程序接收到的 HTTP 请求及其产生的响应
app.UseHttpLogging();
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
可以使用 AddHttpLogging 方法配置 HTTP 请求和响应日志记录消息的详细信息
builder.Services.AddHttpLogging(opts => { opts.LoggingFields = HttpLoggingFields.RequestMethod | HttpLoggingFields.RequestPath | HttpLoggingFields.ResponseStatusCode; });
静态内容不会改变,它用于提供图像、 CSS 样式表、 JavaScript 文件,以及应用程序所依赖但不必为每个请求生成的任何其他内容。ASP.NET Core 项目中静态内容的常规位置是 wwwroot 文件夹
app.UseStaticFiles();
UseStaticFiles 扩展方法将静态文件中间件添加到请求管道。该中间件响应对应于磁盘文件名的请求,并将所有其他请求传递给管道中的下一个组件。这个中间件通常添加在接近请求管道开始的位置,以便其他组件不处理静态文件的请求
当 UseStaticFiles 方法没有参数的时候,默认是wwwroot文件夹下定位文件,如果想要更改默认行为,可以使用StaticFileOptions在方法上
var env = app.Environment; app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider($"{env.ContentRootPath}/staticfiles"), RequestPath = "/files" });
cookies的几种使用
context.Request.Cookies["counter1"]
context.Response.Cookies.Append("counter1", counter1.ToString(), new CookieOptions { MaxAge = TimeSpan.FromMinutes(30) });
context.Response.Cookies.Delete("counter1");
CookieOptions的配置
欧盟通用数据保护条例(GDPR)要求在使用不必要的 cookie 之前必须得到用户的同意。ASP.NET Core 支持获得同意,并防止在未授予同意的情况下将不必要的 cookie 发送到浏览器
builder.Services.Configure<CookiePolicyOptions>(opts => { opts.CheckConsentNeeded = context => true; }); var app = builder.Build(); app.UseCookiePolicy();
为了启用同意检查,我将一个新函数分配给 CheckConsent Needed 属性,该属性始终返回 true。ASP.NET Core 接收到的每个请求都会调用该函数,这意味着可以定义复杂的规则来选择需要同意的请求。对于这个申请,我采取了最谨慎的方法,并要求所有请求的同意
使用 UseCookiePolicy 方法将实施 Cookie 策略的中间件添加到请求管道中。其结果是,只有 IsEssential 属性为 true 的 cookie 才会被添加到响应中
特性处理很少需要更改的请求处理方面,例如响应的结构。唯一的例外是 cookie 同意的管理,它是通过 ITrackingConsenFeature 接口处理的
Cookie 存储应用程序的状态数据,为中间件组件提供所需的数据。这种方法的问题在于 Cookie 的内容存储在客户机上
更好的方法是使用 ASP.NET Core session 特性。session中间件将 cookie 添加到响应中,这允许识别相关的请求,并且该请求还与存储在服务器上的数据相关联
当接收到包含会话 cookie 的请求时,会话中间件组件检索与会话相关联的服务器端数据,并通过 HttpContext 对象使其可用于其他中间件组件。使用会话意味着应用程序的数据保留在服务器上,只有会话的标识符被发送到浏览器
设置会话需要配置服务并向请求管道添加中间件组件
builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(opts => { opts.IdleTimeout = TimeSpan.FromMinutes(30); opts.Cookie.IsEssential = true; }); var app = builder.Build(); app.UseSession();
Session 的存储方法
Session中间件的配置参数
Session Cookies 的配置参数
会话中间件通过 HttpContext 对象的 Session 属性提供对与请求相关的会话详细信息的访问。Session 属性返回一个实现 ISsession 接口的对象
if (context.HostingEnvironment.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
UseDeveloperExceptionPage 方法添加了拦截异常的中间件组件,并提供了更有用的响应。为了演示处理异常的方法
当开发人员异常中间件被禁用时,就像应用程序在生产环境中一样,ASP.NET Core 通过发送只包含错误代码的响应来处理未处理的异常
作为仅返回状态代码的替代方案,ASP.NET Core 提供了拦截未处理异常的中间件,并向浏览器发送一个重定向,这可以用来显示比原始状态代码更友好的响应。异常重定向中间件是用 UseExceptionHandler 方法添加的
app.UseExceptionHandler("/error.html"); app.UseStaticFiles();
当抛出异常时,异常处理程序中间件将截获响应,并将浏览器重定向到作为 UseExceptionHandler 方法的参数提供的 URL。重定向是指向将由静态文件处理的 URL,因此 UseStaticFiles 中间件也已添加到管道中
有一些版本的 UseExceptionHandler 方法允许组合更复杂的响应,但我的建议是尽可能保持错误处理的简单性,因为您无法预测应用程序可能遇到的所有问题,并且当您试图处理触发处理程序的异常时,您可能会遇到另一个异常,从而导致混乱的响应或根本没有响应。
并非所有的错误响应都是未捕获异常的结果。有些请求由于软件缺陷以外的原因无法处理,例如不支持 URL 请求或需要身份验证的 URL 请求。对于这种类型的问题,将客户端重定向到不同的 URL 可能是有问题的,因为一些客户端依赖于错误代码来检测问题
ASP.NET Core 提供的中间件可以将用户友好的内容添加到错误响应中,而不需要重定向。这保留了错误状态代码,同时提供了一个人类可读的消息,帮助用户理解问题
最简单的方法是定义一个字符串,该字符串将用作响应的主体。这比简单地指向一个文件要笨拙得多,但它是一种更可靠的技术,而且作为一项规则,在处理错误时,简单和可靠的技术更可取