在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)的更多相关文章

  1. java 过滤器Filter中chain.doFilter()之前和之后代码的执行顺序

    过滤器拦截到响应url的请求后会先执行doFilter()方法中chain.doFilter()之前的代码,然后执行下一个过滤器或者servelt.紧接着执行chain.doFilter()之后的代码 ...

  2. .Net Core中依赖注入服务使用总结

    一.依赖注入 引入依赖注入的目的是为了解耦和.说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用.这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将 ...

  3. FluentValidation 验证(二):WebApi 中使用 注入服务

    比如你要验证用户的时候判断一下这个用户名称在数据库是否已经存在了,这时候FluentValidation 就需要注入查询数据库 只需要注入一下就可以了 public class Login3Reque ...

  4. IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用

    Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...

  5. 如何在自定义Filter中优雅的实现静态资源放行

            在javaweb开发中,过滤器Filter比较常用于类似登录的拦截等场景.但是,当过滤器的配置不当时就会把所有的请求都拦截,静态资源也会被拦截掉,导致静态页面加载不出来. 一般的解决方 ...

  6. .NET 使用自带 DI 批量注入服务(Service)和 后台服务(BackgroundService)

    今天教大家如何在asp .net core 和 .net 控制台程序中 批量注入服务和 BackgroundService 后台服务 在默认的 .net 项目中如果我们注入一个服务或者后台服务,常规的 ...

  7. servlet filter中使用autowired无法注入

    问题: 我们为了避免未经授权的人直接通过url访问我们的页面,配置了如下filter <!-- 登录过滤器 --> <filter> <filter-name>se ...

  8. ASP.NET Core中使用自定义MVC过滤器属性的依赖注入

    除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作. ASP.NET Core中常用的 ...

  9. 避免在ASP.NET Core 3.0中为启动类注入服务

    本篇是如何升级到ASP.NET Core 3.0系列文章的第二篇. Part 1 - 将.NET Standard 2.0类库转换为.NET Core 3.0类库 Part 2 - IHostingE ...

随机推荐

  1. ansible-playbook 打通ssh无秘钥

    建议参考: http://www.cnblogs.com/jackchen001/p/6514018.html 这个代码清晰,效果佳! 参考链接: http://www.cnblogs.com/cao ...

  2. 网络抓取功能实现 将获取的结果进行过滤并写入到TXT文档中

    下面是自己编写的 网络抓取功能实现 将获取的结果进行过滤并写入到TXT文档中 (以防忘记) 原创哟 import java.io.BufferedReader;import java.io.Buffe ...

  3. __attribute__((noreturn))的用法

    外文地址:http://www.unixwiz.net/techtips/gnu-c-attributes.html __attribute__ noreturn    表示没有返回值 This at ...

  4. Solr查询空值字段

    摘要: Solr的查询一般都是查找满足某个关键词的文档,偶然一个需求是查询Solr中某个字段不为空的数据.查询空值数据字符串类型 可以通过下面这种查询方式找到所有描述description为空的数据. ...

  5. DataWindow.NET 控件 实现点击列头排序

    1.定义字段                         Boolean ib_SetSort = true;                string is_SortType = " ...

  6. activeMQ:java消息机制初试(一)

    前言:自打学习编程以来,就知道activeMQ这么个东西,但是仅仅限于只知其名,不闻其详.现在加入到新的项目组,项目中使用了这个.现在想重新去学习和了解.最后整合成一个完成的demo,在网上看的Dem ...

  7. 利用PDF.JS插件解决了本地pdf文件在线浏览问题(根据需要隐藏下载功能,只保留打印功能)

    我是在IE11和谷歌上做的测试,都可以显示,把做出的东西记录下来,方便大家还有自己学习! 可以在IIS7服务器上也可以下载Tomcat来做服务器 Tomcat下载地址   http://pan.bai ...

  8. no more URLs to fetch

    Generator: records selected for fetching, exiting ... Stopping at depth= - no more URLs to fetch. 出现 ...

  9. Eclipse安装反编译插件,查看.class文件的源码

    2017-08-24 这样我们就可以通过Eclipse查看.class文件的源码了. 1.参考别人的博客,亲测有效 https://www.cnblogs.com/JealousGirl/p/setu ...

  10. roguelike地牢生成算法

    文章原地址 上一个地图生成算法,这一次是一个地牢的生成算法,是一个国外的人写的算法,用dart语言写,我把它改成了unity-c#. 原作者博客地址:Rooms and Mazes: A Proced ...