【aspnetcore】在过滤器(Filter)中使用注入服务(ServiceFilter|TypeFilter)
在MVC中,AOP是很常用的功能,我们经常会使用如 ActionFilter,IAuthorizeFilter 等描述对Controller和Action进行约束和扩展,一般做法如下:
public class TestActionFilterAttribute : Attribute, IActionFilter
{ public void OnActionExecuted(ActionExecutedContext context)
{
if (context.HttpContext.Request.Query.TryGetValue("id", out StringValues value))
{
Console.WriteLine(value.First());
}
else
{
context.HttpContext.Response.Redirect("/Error/404");
}
} public void OnActionExecuting(ActionExecutingContext context)
{ }
}
上面的代码很简单,就是判断请求中是否包含id参数,如果有,则打印id;如果没有,则跳转到错误页面。用法也很简单,在需要约束的Action上添加[TestActionFilter]即可。
[TestActionFilter]
public IActionResult Index()
{
return View();
}
这是Filter最基本的用法,但是,如果我们需要在Filter中使用注入的服务怎么办?比如说修改下 TestActionFilterAttribute:
public class TestActionFilterAttribute : Attribute, IActionFilter
{
private readonly ILogger _logger; public TestActionFilterAttribute(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TestActionFilterAttribute");
} public void OnActionExecuted(ActionExecutedContext context)
{
var path = context.HttpContext.Request.Path;
_logger.LogDebug($"{path} 开始运行了");
} public void OnActionExecuting(ActionExecutingContext context)
{ }
}
我们在Filter的构造函数中注入ILoggerFactory参数,这是系统默认提供的日志工厂服务,用来在控制台打印消息。
回到Controller文件,发现[TestActionFilter]报错:未提供与"TestActionFilterAttribute"的必需形参logger对应的实参。好吧,下面我们尝试构造一个logger对象
public class HomeController : Controller
{
private readonly ILoggerFactory _loggerFactory; public HomeController(ILoggerFactory factory)
{
_loggerFactory = factory;
} [TestActionFilter(_loggerFactory)]
public IActionResult Index()
{
return View();
}
}
修改过后,继续报错:特性构造函数参数"logger"具有类型ILoggerFactory,这不是有效特性参数类型。由此可见,如果在Filter中需要注入服务,常规的方式是无法实现的。
如果一定需要调用注入服务该怎么实现呢?其实框架已经为我们提供了两种途径:TypeFilter和ServiceFilter
public class TestTypeFilter : IActionFilter
{
private readonly ILogger _logger; public TestTypeFilter(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TestTypeFilter");
} public void OnActionExecuted(ActionExecutedContext context)
{
var path = context.HttpContext.Request.Path;
_logger.LogDebug($"{path} 开始运行了");
} public void OnActionExecuting(ActionExecutingContext context)
{ }
}
这里的代码和上面修改过的TestActionFilterAttribute一模一样,修改下Controller文件:
[TypeFilter(typeof(TestTypeFilter))]
public IActionResult Index()
{
return View();
}
运行测试,效果如下:

可以看到,代码运行正常。
下面再看看ServiceFilter的用法,新建文件 TestServiceFilter
public class TestServiceFilter : IActionFilter
{
private readonly ILogger _logger; public TestServiceFilter(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TestServiceFilter");
} public void OnActionExecuted(ActionExecutedContext context)
{
var path = context.HttpContext.Request.Path;
_logger.LogDebug($"{path} 开始运行了");
} public void OnActionExecuting(ActionExecutingContext context)
{ }
}
修改Controller文件:
//[TypeFilter(typeof(TestTypeFilter))]
[ServiceFilter(typeof(TestServiceFilter))]
public IActionResult Index()
{
return View();
}
仅仅这样是不够的,顾名思义,ServiceFilter(服务过滤器),我们需要到startup.cs的ConfiguraionServices中注册TestServiceFilter:
services.AddSingleton<TestServiceFilter>();
运行测试,效果如下:

OK,运行正常!
下面是补充内容,添加一个全局异常过滤器:
新建文件 MvcGlobalExceptionFilter.cs
public class MvcGlobalExceptionFilter : IExceptionFilter
{
private readonly ILogger _logger; public MvcGlobalExceptionFilter(ILoggerFactory logger)
{
_logger = logger.CreateLogger("MvcGlobalExceptionFilter");
} public void OnException(ExceptionContext context)
{
// 全局异常的错误处理
_logger.LogError(context.Exception, "全局异常");
}
}
修改Startup.cs中的ConfigurationServices:
services.AddMvc(options =>
{
// 添加全局异常
options.Filters.Add<MvcGlobalExceptionFilter>();
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
修改Controller文件,手动抛出异常:
[ServiceFilter(typeof(TestServiceFilter))]
public IActionResult Index()
{
throw new Exception("异常测试,这是手动抛出的异常");
return View();
}
运行测试,效果如下:

可以看到,我们定义的过滤器捕获并打印了异常信息。
【aspnetcore】在过滤器(Filter)中使用注入服务(ServiceFilter|TypeFilter)的更多相关文章
- java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序
过滤器拦截到响应url的请求后会先执行doFilter()方法中chain.doFilter()之前的代码,然后执行下一个过滤器或者servelt.紧接着执行chain.doFilter()之后的代码 ...
- .Net Core中依赖注入服务使用总结
一.依赖注入 引入依赖注入的目的是为了解耦和.说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用.这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将 ...
- FluentValidation 验证(二):WebApi 中使用 注入服务
比如你要验证用户的时候判断一下这个用户名称在数据库是否已经存在了,这时候FluentValidation 就需要注入查询数据库 只需要注入一下就可以了 public class Login3Reque ...
- IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用
Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...
- 如何在自定义Filter中优雅的实现静态资源放行
在javaweb开发中,过滤器Filter比较常用于类似登录的拦截等场景.但是,当过滤器的配置不当时就会把所有的请求都拦截,静态资源也会被拦截掉,导致静态页面加载不出来. 一般的解决方 ...
- .NET 使用自带 DI 批量注入服务(Service)和 后台服务(BackgroundService)
今天教大家如何在asp .net core 和 .net 控制台程序中 批量注入服务和 BackgroundService 后台服务 在默认的 .net 项目中如果我们注入一个服务或者后台服务,常规的 ...
- servlet filter中使用autowired无法注入
问题: 我们为了避免未经授权的人直接通过url访问我们的页面,配置了如下filter <!-- 登录过滤器 --> <filter> <filter-name>se ...
- ASP.NET Core中使用自定义MVC过滤器属性的依赖注入
除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作. ASP.NET Core中常用的 ...
- 避免在ASP.NET Core 3.0中为启动类注入服务
本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0类库转换为.NET Core 3.0类库 Part 2 - IHostingE ...
随机推荐
- uboot之logo显示【转】
本文转载自:http://blog.csdn.net/tuwenqi2013/article/details/60583735 版权声明:本文为博主原创文章,博主欢迎各位转载. 一.logo的调用流程 ...
- this.triggerEvent()用法
在对组件进行封装时 在当前页面想要获取组件中的某一状态,需要使用到this.triggerEvent(' ',{},{}),第一个参数是自定义事件名称,这个名称是在页面调用组件时bind的名称,第二个 ...
- codeforces B. Roma and Changing Signs 解题报告
题目链接:http://codeforces.com/problemset/problem/262/B 题目意思:给出 n 个数和恰好一共要做的操作总数k.通过对n个数进行k次操作,每次操作可以把a[ ...
- c/c++生成预编译文件
Preprocesses C and C++ source files and writes the preprocessed output to a file. /P Remarks The f ...
- 「LOJ#10043」「一本通 2.2 例 1」剪花布条 (KMP
题目描述 原题来自:HDU 2087 一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? 输入格式 输入数据 ...
- spring配置数据库连接池
1. jdbcConfig.properties文件中 jdbc.jdbcUrl=jdbc:mysql:///ssm-crudjdbc.driverClass=com.mysql.jdbc.Drive ...
- 基于候选区域的R-CNN系列网络简介
使用候选区域方法(region proposal method)创建目标检测的感兴趣区域(ROI).在选择性搜索(selective search,SS)中,首先将每个像素作为一组.然后,计算每一组的 ...
- Day02:数据类型、字符编码、文件处理
一.基础数据类型与其内置方法 1. int基本使用:int(3.1) 用途:记录年龄,职级等 只能将包含纯数字的字符串类型转换成整形 特点:1.存一个值. 2.不可变 2.float基本使用 floa ...
- android手机各大分区详解
1. bootloader 当我们拿到一款手机,第一件事应该就是按下电源键开机,那么从开机到进入到桌面程序这中间发生了些什么呢,我们从下面这张简化了的手机结构图开始: 注意:该结构图并不反映手机的实 ...
- Docker 与 宿主机之间的文件cp
Docker 与 宿主机之间的文件cp 第一种方法是官方比较推荐的,其实和第二种方法实现是一样的. 第一种方法例: 将主机/www/runoob目录拷贝到容器96f7f14e99ab的/www目录下. ...