ASP.Net Core MVC基础系列之中间件
作者:丶亡我之心不死 发布时间:2024-05-09 09:04:47
上一节我们介绍了服务注册和基本的管道执行流程, 并且讲到了中间件, 这一节我们就来详细谈谈中间件这个东西
讲中间件, 其实就是讲Startup类里面的ConfigureServices 和Configure 这两个方法
在程序启动类Program 中, 我们在CreateWebHostBuilder 方法中调用了UseStartup方法, 里面用泛型注入了 Startup 类, 那程序就会自动实例化这个类, 并且去执行它里面的ConfigureServices 和Configure 这两个方法. 我们就可以做很多配置操作
首先调用的第一个方法当然就是构造函数, 这里没有没有, 我们不说, 然后就是ConfigureServices 方法. 这个方法上一节已经使用过了, 在这个方法里面, 我们可以注册一些服务或者我们叫自定义服务. 注册完服务, 我们就可以通过依奈注入的方式在其它地方使用这些服务.
然后再执行的方法就是Configure 这个方法. 我们能看到Configure 方法默认的第一个参数是IApplicationBuilder 接口, 可以理解为整个程序的根, 我们通过这个接口对象, 可以精确的配置获取启用我们的中间件, 使我们的各种中间件组合起来, 形成一个完美的Web应用程序, 去处理我们的HTTP请求并且做出对应的响应等等.
讲之前, 我们先把
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
这几行代码注释掉, 待会再用, 再去解释这个是干嘛用的, 为什么要加个if, 这里先注释掉
我们看这个代码
app.Run(async (context) =>
{
var msg = welcome.GetWelcomMsg();
await context.Response.WriteAsync(msg);
});
这个app.Run方法, 可以理解为我们自己写的一个中间件, 它什么都不干, 就是为响应输出一个字符串. 其实这是新建项目默认生成的.
在真实的项目中, 我们基本上不会使用app.Run这个方法去处理我们的请求, 因为我做的事情远远比输出一个字符串复杂很多.
在实际开发中, 我们通常使用的中间件都是app.Usexxxx开头的, 才能组成一个完成的Web项目, 比如 app.UseMvc / app.UseStaticFiles等等这些方法去启用系统自带的中间件获取别的第三方中间件.
我们这里启用个ASP.Net Core MVC自带的彩蛋中间件吧, 代码为:app.UseWelcomePage(); 启用默认的MVC欢迎页面. 我们F5执行.
我们能够正常看到出现了一个页面, 而不是简单的一个字符串的输出了
然后我们尝试改变一下地址栏, 随便写个什么, 可以发现, 我们随便怎么输入地址, 都是进入到欢迎页, 如图 :
到这里, 我们就可以发现, 这个"彩蛋"中间件的"优先级"还是很高的, 在ASP.Net Core MVC发现你使用了这个中间件的时候, 他就不会执行后面的东西了, 或者说不会执行后面的中间件了.
还有呢, 在我们使用中间件的时候, 或者说是在调用app.Usexxxx方法的时候, 一般来说, 这个方法都会接受一个对象参数, 这个参数可以对这个中间件进行一些配置, 下面我们尝试配置一下"彩蛋"中间件, 告诉大家中间件是怎么配置的. 代码是这样的
app.UseWelcomePage(new WelcomePageOptions
{
Path = "/welcome"
});
都能看到, 这里是为"彩蛋"配置了一个地址(路径), 现在我们F5看看效果
会发现网页输出是个字符串, 那我们在地址后面加上 /welcome 再看看, 可以发现能正常出现"彩蛋"了, 说明这个配置是有效的.
当然我的目的不是讲这个"彩蛋"怎么使用, 而是给大家介绍中间件怎么使用, 怎么去配置中间件, 基本上所有的中间件都是这个使用方式和配置方式.
既然说到了这里, 那我们来说说 app.Use 这个方法. 这个方法怎么说呢, 就是它比较"底层", 因为app.Use里面的参数类型是RequestDelegate , 也就是当前请求对象的委托, 相对比较"底层", 可以说是当前请求管道的"原型". 我们来写一些代码试试吧.
app.Use(next =>
{
return async context =>
{
if (context.Request.Path.StartsWithSegments("/first"))
{
await context.Response.WriteAsync("First");
}
else
{
await next(context);
}
};
});
我们写的代码如上, 它的意思就是: 当前地址是/first 的时候, 输出 First 这个字符串, 否则就不管, 继续往下执行, 去执行别的中间件, 我们运行看看效果. 可以发现, 默认输出的是 你好, .Net Core 2.2, 当我们把地址后面加上/first 的时候, 输出的就是First, 如图:
我们再输入地址 /welcome 的是, 可以看到"彩蛋"正常出现了, 可以看到, 我们的Use方法是正常的
在实际开发过程中, 我们很少直接使用app.Use方法去处理我们的底层请求的, 这里只是简单介绍了这个方法, 以及它能干什么.
知道app.Use是干什么的, 那就把上面的app.Use方法删掉吧, 或者注释掉, 我们下面的教程不会用的.
接下来, 我们干点坏事, 我们在 app.Run 方法里面手动报个异常出来, 代码如下:
app.Run(async (context) =>
{
throw new Exception();
var msg = welcome.GetWelcomMsg();
await context.Response.WriteAsync(msg);
});
我们执行项目, 会看到出现了500错误, Chrome浏览器是这样的, 其它浏览器可能不一样
但是我们不希望这样, 我们希望我们能看到异常的详细信息, 这时候, 我们就需要启用一个异常中间件, 就是我们上面注释掉的那个 iif (env.IsDevelopment()) 的代码, 我们把它启用起来, 那么我们的Configure 方法里面代码就是这样的, 如图:
然后我们再F5运行项目, 就是这样的了, 如图:
我们的异常就很明显了, 很好排查错误
至于为什么加个if (env.IsDevelopment()), 这个代码一看就知道意思了吧, 就是当前环境是开发环境的时候, 才启用这个异常显示中间件
因为我们只希望在开发或者调试的时候, 才显示异常的详细信息, 别的环境不显示, 这样安全一些, 如果不加这个 if , 会在任何环境都会显示详细的错误信息, 这样可能会给我们的Web应用带来安全隐患.
所以, 我们再加个else , 在else里面启用一个别的中间件, 代码如下:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler();
}
这样我们不是在开发环境的时候, 发送异常就是这样的:
不至于暴露一些敏感的信息
我们发现这个启动异常页面中间件的代码写在最上面, 那我们把它移动到Configure 方法的最后面, 会怎么样呢 ? 我们试试, 代码如图:
可以看到, 我把异常页面中间件移动到最后面启用了, 我们F5运行项目, 会发现, 浏览器不出先异常页面了, 而是直接 500 错误.
可以知道, 中间件的启用顺序是有依奈关系和顺序的, 不能随便启用的, 需要在正确的位置启用对应的中间件, 如果顺序错了, 可能会导致中间件失效, 如果你在开发过程中, 启用了某个中间件, 但是它却没效果, 可以使用该思路进行排查.
到这里, 这一节就结束了, 到目前为止, 我们的Web应用功能很简单, 就是输出一个字符串和启用了一个"彩蛋".
我们还讲到了"环境", 比如上面的if (env.IsDevelopment()) 判断是不是开发环境, 那么怎么改变这个环境, 让我们在开发或者试运行和运营环境切换, 加载不同的配置和启用不同的中间件
来源:https://www.cnblogs.com/klwen/p/10303273.html
猜你喜欢
- 前言在部署一些定时运行或者长期运行的任务时,为了留存一些导致程序出现异常或错误的信息,通常会才用日志的方式来进行记录这些信息。python内
- 1.本人第一次学python做出来的,当时满满的成就感,当作纪念!!!!!非常简单,复制即可使用代码块import json#把字符串类型的
- 为什么能实现在线编辑呢? 首先需要ie 的支持,在 ie 5.5以后就有一个编辑状态,就是利用这个编辑状态,然后用javascript 来控
- 环境准备好了!我们怎么使用这些东东?IIS用组件初始化是用这个过程Public Sub OnStartPage给个使用asp组件的例子:数字
- 实例如下所示:from xml.etree.cElementTree import ElementTree,Elementimport xl
- 如何处理DataFrame的inf值在用DataFrame计算变化率时,例如(今天-昨天) / 昨天恰好为(2-0) / 0时,这些结果数据
- 在附加数据库后查看不了数据库关系图,也无法建立数据库关系图 我的解决方法如下: 1、设置兼容级别为90(2005为90)(2000为80)
- 导 读vue3.0中,响应式数据部分弃用了 Object.defineProperty ,使用 Proxy 来代替它。本文将主要通过以下方面
- 众所周知,Python 支持多种编程范式:过程式(使用基础的语句)、面向对象编程和函数式编程。Python 也提供了其他函数式编程语言的工具
- 本文为大家分享了mysql 8.0.12的 安装教程,供大家参考,具体内容如下安装教程环境:系统:Windows8.1安装包:mysql-8
- 1、实例 DELIMITER // DROP PROCEDURE IF EXISTS `test`.`p_getvalue` // CREA
- 基础代码pred_y = test_output.data.numpy()pred_y = pred_y.flatten()print(pr
- 本文实例讲述了php函数连续调用的方法。分享给大家供大家参考。具体如下:<?php //返回$this,实现连续调用 class xi
- 当两个数包含小数进行运算的时候结果并不是正确的结果,而是出现了精度丢失的情况(小数点后面出现很多位)。问题所在:res.orderColor
- 一、问题描述在用python开发时经常用到logging这个包,根据官方示例,如果要指定日志级别可以写成如下的方式。import loggi
- 1 安装nginx下载windows上的nginx最新版本,http://www.nginx.org/en/download.html。解压
- Cookies的处理作用保存客户端的相关状态在爬虫中如果遇到了cookie的反爬如何处理?手动处理 在抓
- <?php $fp = fopen("http://www.***.com/**
- 一般情况下TextArea区输入的文字数量是没有限制的,但是我们可以通过javascript限制表单的文字字数。如下javascript代码
- Pandas函数的核心功能是,既计算了统计值,又保留了明细数据。为了更好地理解transform和agg的不同,下面从实际的应用场景出发进行