ASP.NET Core 中的基础知识

整个 ASP.NET Core 框架建立在一个底层的依赖注入框架之上,它使用依赖注入容器提供所需的服务对象。(默认是构造函数注入方式)

对项目文件的理解:

VS打开的解决方案中,双击项目名,查看项目文件,即 xx.csproj 文件

<!--不同的应用类型会采用不同的SDK。
console:Microsoft.NET.Sdk
web(mvc/webapi):Microsoft.NET.Sdk.Web
-->
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
	  <!--<OutputType>Exe</OutputType>--> <!--仅在console里需要-->
    <TargetFramework>net6.0</TargetFramework>
	  <!--Nullable的属性与C#与一个名为“空值(Null)验证”的特性有关-->
    <Nullable>enable</Nullable>
	  <!--ImplicitUsings属性与C# 10提供的一个叫做“全局命名空间”新特性有关-->
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

</Project>

dotnet --info 命令

WIN+R,输入“cmd”回车打开命令行,输入dotnet --info,查看当前安装的.NET Core SDK的基本信息,其中包含SDK的版本、运行时环境和共享框架宿主的版本信息。

launchSettings.json

该文件是一个在应用启动时自动加载的配置文件,该配置文件可以在不同的设置下执行应用程序。注意该文件仅仅在开发环境中出现和起作用。应用发布后生成的文件列表中也不包含该文件。右击项目、选择属性、选择调试,在该面板的设置最终都会体现在该文件上。

中间件

中间件是一种装配到应用管道以处理请求和响应的一段程序(一个逻辑处理单元,通常指一个类或方法)。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在管道中的下一个组件前后执行工作。

Startup.Configure 方法添加中间件组件的顺序定义了针对请求调用这些组件的顺序,以及响应的相反顺序。 此顺序对于安全性、性能和功能至关重要。

一个重要的事实:ASP.NET Core应用针对请求的处理总是在一个HttpContext上下文对象中进行。

一个重要的委托:public delegate Task RequestDelegate(HttpContext context);

中间件最终总是体现为一个Func<RequestDelegate,RequestDelegate>委托,除了用这个委托定义一个中间件,还可以用下面这两个:

  • Func<HttpContext, RequestDelegate, Task>
  • Func<HttpContext, Func<Task>, Task>

这两个委托内容分别使用作为输入参数的RequestDelegateFunc<Task>完成对后续管道的调用。

我们调用WebApplication 的 Use 方法将这两种“变体”注册为中间件。请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件”,因为它阻止中间件进一步处理请求。

当我们试图利用一个自定义中间件来完成某种请求处理功能时,其实很少会将中间件定义成上述的这三种委托形式,基本上都会将其定义成一个具体的类型。中间件类型有两种定义方式,一种是直接实现 IMiddleware 接口,一种是基于约定的。按照ASP.NET Core的约定,中间件类型需要定义成一个公共实例类型(静态类型无效),其构造函数可以注入任意的依赖服务,但必须包含一个 RequestDelegate 类型的参数,该参数表示由后续中间件构建的管道,当前中间件利用它将请求分发给后续管道作进一步处理。针对请求的处理实现在一个命名为 InvokeAsync 或者 Invoke 的方法中,该方法返回类型为 Task , 第一个参数并绑定为当前的 HttpContext 上下文。

image-20210718121739834

选项模式

ASP.NET Core采用了一个非常灵活的配置框架,我们可以存储在任何载体的数据作为配置源。我们还可以将结构化的配置转换成对应的选项(Options)类型,以强类型的方式来使用它们。

读取相关配置值的首选方法是使用选项模式。选项模式使用类来提供对相关设置组的强类型访问。 当配置设置由方案隔离到单独的类时,应用遵循两个重要软件工程原则:

环境

开发环境可以启用不应该在生产中公开的功能。 例如,ASP.NET Core 模板在开发环境中启用了开发人员异常页

本地计算机开发环境可以在项目的 Properties\launchSettings.json 文件中设置。 在 launchSettings.json 中设置的环境值替代在系统环境中设置的值。

launchSettings.json 文件:

  • 仅在本地开发计算机上使用。
  • 未部署。
  • 包含配置文件设置。

筛选器

参考官网:ASP.NET Core 中的筛选器 | Microsoft Learn

通过使用 ASP.NET Core 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码。

可以创建自定义筛选器,用于处理横切关注点。 横切关注点的示例包括错误处理、缓存、配置、授权和日志记录。 筛选器可以避免重复代码。 例如,错误处理异常筛选器可以合并错误处理。

本文档适用于 Razor Pages、API 控制器和具有视图的控制器。

工作原理如下:

请求通过其他中间件、路由中间件、操作选择和操作调用管道进行处理。请求处理会继续通过操作选择、路由中间件和其他各种中间件,然后再成为发送到客户端的响应。

五种筛选器:

每种筛选器类型都在筛选器管道中的不同阶段执行:

  • 授权筛选器:
    • 首先运行。
    • 确定用户是否获得请求授权。
    • 如果请求未获授权,可以让管道短路。
  • 资源筛选器
    • 授权后运行。
    • OnResourceExecuting 在筛选器管道的其余阶段之前运行代码。 例如在模型绑定之前运行代码。
    • OnResourceExecuted 在管道的其余阶段完成之后运行代码。
  • 操作筛选器
    • 在调用操作方法之前和之后立即运行。
    • 可以更改传递到操作中的参数。
    • 可以更改从操作返回的结果。
    • 不可在 Razor Pages 中使用。
  • 异常筛选器在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
  • 结果筛选器
    • 在执行操作结果之前和之后立即运行。
    • 仅当操作方法成功执行时才会运行。
    • 对于必须围绕视图或格式化程序的执行的逻辑,会很有用。

下图展示了筛选器类型在筛选器管道中的交互方式:

请求通过授权筛选器、资源筛选器、模型绑定、操作筛选器、操作执行和操作结果转换、异常筛选器、结果筛选器和结果执行进行处理。在出路时,请求仅由结果筛选器和资源筛选器处理,然后才会成为发送到客户端的响应。

另外,在实现上,筛选器通过不同的接口定义支持同步和异步实现。筛选器接口的同步和异步版本任意实现一个,而不是同时实现 。如果在一个类中同时实现异步和同步接口,则仅调用异步方法。

在使用上,注意,以上这些Filter接口都有默认的实现类,可用于你自定义筛选器的基类。此外如果仅继承Filter接口,那么如果想以特性的形式,应用于控制器和方法,那么还需继承Attribute。这点官方文档没提,自己注意点。


Cookie、Session

Cookie 存储请求之间的数据。 因为 Cookie 是随每个请求发送的,所以它们的大小应该保持在最低限度。 理想情况下,仅标识符应存储在 cookie 中,而数据则由应用存储。 大多数浏览器 cookie 大小限制为 4096 个字节。 每个域仅有有限数量的 cookie 可用。

注意:由于 cookie 易被篡改,因此它们必须由服务器进行验证。另外, 客户端上的 Cookie 可能被用户删除或者过期。

会话状态(Session)是在用户浏览 Web 应用时用来存储用户数据的 ASP.NET Core 方案。 会话状态使用应用维护的存储来保存客户端所有请求的数据。 会话数据由缓存提供支持,并被视为临时数据。 站点应在没有会话数据的情况下继续运行。 关键应用程序数据应存储在用户数据库中,并仅作为性能优化缓存在会话中。

ASP.NET Core 通过向客户端提供包含会话 ID 的 cookie 来维护会话状态。 cookie 会话 ID:

  • 会随每个请求发送到应用。
  • 由应用用于提取会话数据。

会话使用 cookie 跟踪和标识来自单个浏览器的请求。 默认情况下,此 cookie 名为 .AspNetCore.Session,并使用路径 /

会话状态是通过 Razor Pages PageModel 类或包含 HttpContext.Session 的 MVC Controller 类进行访问。 此属性是 ISession 实现。

IOC容器

要想使用IoC ,首先服务类型,必须是实例类,且有Public 的构造函数,而不是静态类。

构造函数的选择策略

容器能够提供服务类的实例,是通过调用其某个合适的构造函数来实现的。这些候选的合适的构造函数是指每个参数类型都能被容器提供的构造函数。在所有合法的候选构造函数列表中,最终被选择的构造函数具有如下特征:所有候选构造函数的参数类型都能在这个构造函数中找到。如果这样的构造函数并不存在,会直接抛出一个InvalidOperationException类型的异常。

不预先注册而获取服务实例

IServiceProvider对象能够提供指定类型服务实例的前提是存在对应的服务注册,但是有的时候我们需要利用容器创建一个对应类型不曾注册的实例。一个最为典型的例子是MVC应用针对目标Controller实例的创建,因为Controller类型并未作为依赖服务进行注册。这种情况我们就会使用到ActivatorUtilities这个静态的工具类型(十分重要)。当我们调用定义在ActivatorUtilities类型中的如下这些静态方法根据指定的IServiceProvider对象创建指定服务实例时,虽然不要求针对目标服务被预先注册,但是要求指定的IServiceProvider对象能够提供构造函数中必要的参数。

public static class ActivatorUtilities
{
    public static object CreateInstance(IServiceProvider provider,  Type instanceType, params object[] parameters);
    public static T CreateInstance<T>(IServiceProvider provider, params object[] parameters);

    public static object GetServiceOrCreateInstance(IServiceProvider provider, Type type);
    public static T GetServiceOrCreateInstance<T>(IServiceProvider provider);
}

注意,这种方式获取的服务,在构造函数的选择上有点另类,默认的构造函数选择策略过于模糊且不严谨,如果希望ActivatorUtilities选择某个构造函数,我们可以通过在目标构造函数上标注ActivatorUtilitiesConstructorAttribute特性的方式来解决这个问题。具体参考:

[ASP.NET Core 6框架揭秘实例演示06]:依赖注入框架设计细节 - Artech - 博客园 (cnblogs.com)

对象池

net6中出现的东西。一种对象复用的手段,用来提升程序性能,减少GC压力。消费者有借有还再借不难。

对象池主要用在对象初始化比较耗时和使用比较频繁的场景,比如初始化时要读取网络资源,有时候这些对象因为有时效性,又不能用单例。

gRPC

gRPC是语言中立的远程调用框架,gRPC服务契约使用到的数据类型都采用标准的定义方式。具体来说,gRPC传输的数据采用Proto Buffers协议进行序列化,Proto Buffers采用高效紧凑的二进制编码。

Dapr

Dapr的全称是“分布式应用运行时Distributed Application Runtime”。

它并不是分布式应用的开发框架,它提供的是更底层的“运行时”。我们可以使用不同的编程语言,采用不同的开发框架在这个由Dapr提供的运行时上面构建分布式应用。

在一个分布式环境下,我们不需要知道目标服务所在的位置,因为这是不确定的,确定的唯有目标服务/应用的标识,所以我们直接将此标识作为请求的目标地址。

Dapr在初始化过程中会默认为我们设置一个针对Redis的状态存储组件,并将其命名为“statestore”。

这个东西好像类似iis,就是程序直接怼到这个东西里,然后以它的方式启动应用程序,即可。


更新于:2022.5.22

posted @ 2023-05-22 09:49  AI大胜  阅读(117)  评论(0编辑  收藏  举报