- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章在Asp.Net Core中使用ModelConvention实现全局过滤器隔离由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
从何说起 。
这来自于我把项目迁移到Asp.Net Core的过程中碰到一个问题。在一个web程序中同时包含了MVC和WebAPI,现在需要给WebAPI部分单独添加一个接口验证过滤器 IActionFilter ,常规做法一般是写好过滤器后给需要的控制器挂上这个标签,高级点的做法是注册一个全局过滤器,这样可以避免每次手动添加同时代码也更好管理。注册全局过滤器的方式为:
1
2
3
4
|
services.AddMvc(options =>
{
options.Filters.Add(
typeof
(AccessControlFilter));
});
|
但这样做会带来一个问题,那就是MVC部分控制器也会受影响,虽然可以在过滤器中进行一些判断来区分哪些是MVC Controller哪些是API Controller,但是平白无故给MVC增加这么一个没用的Filter,反正我是不能忍,所以寻找有没有更好的办法来实现这个功能.
于是ModelConvention(可以翻译为模型约定)闪亮登场.
先认识下ApplicationModel 。
看一下官方文档是怎么描述应用程序模型(ApplicationModel)的:
ASP.NET Core MVC defines an application model representing the components of an MVC app. You can read and manipulate this model to modify how MVC elements behave. By default, MVC follows certain conventions to determine which classes are considered to be controllers, which methods on those classes are actions, and how parameters and routing behave. You can customize this behavior to suit your app's needs by creating your own conventions and applying them globally or as attributes. 。
简单一点说,ApplicationModel描述了MVC应用中的各种对象和行为,这些内容包含Application、Controller、Action、Parameter、Router、Page、Property、Filter等等,而Asp.Net Core框架本身内置一套规则(Convention)用来处理这些模型,同时也提供了接口给我们自定义约定来扩展模型以实现更符合需要的应用.
和应用程序模型有关的类都定义在命名空间 Microsoft.AspNetCore.Mvc.ApplicationModels 中,这些模型通过 IApplicationModelProvider 构建出来,Asp.Net Core框架提供的默认Provider是 DefaultApplicationModelProvider 。我们可以编辑这些模型,从而更改它的表现行为,这就要借助它的ModelConvention来实现.
ModelConvention 。
ModelConvention定义了操作模型的入口,又或者说是一种契约,通过它我们可以对模型进行修改,常用的Convention包括:
这些接口提供了一个共同的方法 Apply ,方法参数是各自的应用程序模型,以 IControllerModelConvention 为例看一下它的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
namespace
Microsoft.AspNetCore.Mvc.ApplicationModels
{
//
// 摘要:
// Allows customization of the Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel.
//
// 言论:
// To use this interface, create an System.Attribute class which implements the
// interface and place it on a controller class. Microsoft.AspNetCore.Mvc.ApplicationModels.IControllerModelConvention
// customizations run after Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelConvention
// customizations and before Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention
// customizations.
public
interface
IControllerModelConvention
{
//
// 摘要:
// Called to apply the convention to the Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel.
//
// 参数:
// controller:
// The Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel.
void
Apply(ControllerModel controller);
}
}
|
从接口摘要可以看到,这个接口允许自定义 ControllerModel 对象,而如何自定义内容正是通过 Apply 方法来实现,这个方法提供了当前 ControllerModel 对象的实例,我们可以在它身上获取到的东西实在太多了,看看它包含些什么:
有了这些,我们可以做很多很灵活的操作,例如通过设置 ControllerName 字段强制更改控制器的名称让程序中写死的控制器名失效,也可以通过 Filters 字段动态更新它的过滤器集合,通过 RouteValues 来更改路由规则等等.
说到这里,很多人会觉得这玩意儿和自定义过滤器看起来差不多,最开始我也这么认为,但经过实际代码调试我发现它的生命周期要比过滤器早的多,或者说根本无法比较, 这个家伙只需要在应用启动时执行一次并不用随着每次请求而执行 。也就是说,它的执行时间比激活控制器还要早,那时候根本没有过滤器什么事儿,它的调用是发生在 app.UseEndpoints() .
回到最开始的需求。基于上面的介绍,我们可以自定义如下的约定:
1
2
3
4
5
6
7
8
9
10
|
public
class
ApiControllerAuthorizeConvention : IControllerModelConvention
{
public
void
Apply(ControllerModel controller)
{
if
(controller.Filters.Any(x => x
is
ApiControllerAttribute) && !controller.Filters.Any(x => x
is
AccessControlFilter))
{
controller.Filters.Add(
new
AccessControlAttribute());
}
}
}
|
上面的主要思路就是通过判断控制器本身的过滤器集合是否包含 ApiControllerAttribute 来识别是否API Controller,如果是API Controller并且没有标记过 AccessControlAttribute 的话就新建一个实例加入进去.
那么如何把这个约定注册到应用中呢?在Microsoft.AspNetCore.Mvc.MvcOptions中提供了 Conventions 属性:
1
2
3
4
5
6
|
//
// 摘要:
// Gets a list of Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelConvention
// instances that will be applied to the Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel
// when discovering actions.
public
IList<IApplicationModelConvention> Conventions {
get
; }
|
通过操作它就能把自定义约定注入进去:
1
2
3
4
|
services.AddMvc(options =>
{
options.Conventions.Add(
new
ApiControllerAuthorizeConvention());
})
|
细心的人会发现,Conventions是一个 IApplicationModelConvention 类型的集合,而我们自定义的Convention是一个 IControllerModelConvention ,正常来说应该会报错才对?原因是Asp.Net Core的DI框架帮我们提供了一系列扩展方法来简化Convention的添加不用自己再去转换:
通过代码调试发现,应用启动时遍历了系统中的所有控制器去执行Apply操作,那么通过 IApplicationModelConvention 一样也能实现这个功能,因为它里面包含了控制器集合:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public
class
ApiControllerAuthorizeConvention : IApplicationModelConvention
{
public
void
Apply(ApplicationModel application)
{
foreach
(var controller
in
application.Controllers)
{
if
(controller.Filters.Any(x => x
is
ApiControllerAttribute) && !controller.Filters.Any(x => x
is
AccessControlFilter))
{
controller.Filters.Add(
new
AccessControlFilter());
}
}
}
}
|
再改进一下 。
实际开发中我的AccessControlFilter需要通过构造函数注入业务接口,类似于这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
class
AccessControlFilter : IActionFilter
{
private
IUserService _userService;
public
AccessControlFilter(IUserService service)
{
_userService = service;
}
public
void
OnActionExecuting(ActionExecutingContext context)
{
//模拟一下业务操作
//var user=_userService.GetById(996);
//.......
}
public
void
OnActionExecuted(ActionExecutedContext context)
{
}
}
|
如何优雅的在Convention中使用DI自动注入呢?Asp.Net Core MVC框架提供的 ServiceFilter 可以解决这个问题, ServiceFilter 本身是一个过滤器,它的不同之处在于能够通过构造函数接收一个Type类型的参数,我们可以在这里把真正要用的过滤器传进去,于是上面的过滤器注册过程演变为:
1
|
controller.Filters.Add(
new
ServiceFilterAttribute(
typeof
(AccessControlFilter)));
|
当然了,要从DI中获取这个filter实例,必须要把它注入到DI容器中:
1
|
services.AddScoped<AccessControlFilter>();
|
至此,大功告成,继续愉快的CRUD.
突然想起来我上篇文章提到的扩展DI属性注入功能估计也能通过这个玩意实现,eeeeeee...有空了试一下.
总结 。
总体来说,我通过曲线救国的方式实现了全局过滤器隔离,虽然去遍历目标控制器再手动添加Filter的方式没有那种一行代码就能实现的方式优雅,但我大体来说还算满意,是目前能想到的最好办法。我估摸着, options.Filters.Add(xxx) 也是在框架某个时候一个个把xxx丢给各自主人的,瞎猜的,说错不负责~hhhh:see_no_evil::see_no_evil::see_no_evil
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://www.cnblogs.com/hohoa/p/12134019.html 。
最后此篇关于在Asp.Net Core中使用ModelConvention实现全局过滤器隔离的文章就讲到这里了,如果你想了解更多关于在Asp.Net Core中使用ModelConvention实现全局过滤器隔离的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
创建使用.NET框架的asp.net页面时,访问该页面的客户端是否需要在其计算机上安装.NET框架? IE。用户访问www.fakesite.com/default.aspx,如果他们没有安装框架,他
我阅读了很多不同的博客和 StackOverflow 问题,试图找到我的问题的答案,但最后我找不到任何东西,所以我想自己问这个问题。 我正在构建一个应用程序,其中有一个长时间运行的工作线程,它执行一些
已锁定。这个问题及其答案是locked因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。 我一直想知道为什么微软为这样一个伟大的平台选择了一个如此奇怪的、对搜索引擎不友好的名称。他们就
.Net Framework .Net .NET Standard的区别 1、.NET Framework 在未来.NET Framework或许成为过去时,目前还是有很多地方在使用的。这一套
如果有选择的话,您会走哪条路? ASP.NET Webforms + ASP.NET AJAX 或 ASP.NET MVC + JavaScript Framework of your Choice
我有一个 Web 服务,它通过专用连接通过 https 使用第三方 Web 服务,我应用了 ServicePointManager.ServerCertificateValidationCallbac
为什么我应该选择ASP.NET Web Application (.NET Framework)而不是ASP.NET Core Web Application (.NET Framework)? 我在
我在网络上没有找到任何关于包含 .NET Standard、.NET Core 和 .NET Framework 项目的 .NET 解决方案的公认命名约定。 就我而言,我们在 .NET 框架项目中有以
.NET Compact 是 .NET 的完美子集吗? 假设我考虑了屏幕大小和其他限制并避免了 .NET Compact 不支持的类和方法,或者 .NET Compact 是一个不同且不兼容的 GUI
我已经阅读了所有我能找到的关于 connectionManagement 中的 maxconnection 设置的文章:即 http://support.microsoft.com/kb/821268
我现在正在使用asp.net mvc,想知道使用内置的Json或 Json.Net哪个是更好的选择,但我不确定一个人是否比另一个人有优势。 另外,如果我确实选择沿用Json.Net的路线,那么我应该选
在 Visual Studio 中,您至少可以创建三种不同类型的类库: 类库(.NET Framework) 类库(.NET 标准) 类库(.NET Core) 虽然第一个是我们多年来一直使用的,但我
.NET 和 ASP.NET 之间有什么区别?它们有什么关系? 最佳答案 ASP.Net 基于 .Net 框架构建,提供有关 Web 开发的附加功能。 你可以去看看wikipedia article
在安装更高版本(3.0)之前,我需要安装.net框架1.1和2.0吗?或者单独安装 3.0 框架就足够了,并为在早期框架版本上编写的软件提供支持?谢谢 ,丽然 最佳答案 不,您不必安装以前的框架。 我
我正在开发一个项目,人们可以“更新”类别,例如更改类别的名称。我收到以下消息 This is called after clicking update 按钮 with the SQL statemen
.NET 类 System.Net.CookieContainer 线程安全吗? --更新:交 key 答复-- 是否有任何方法可以确保异步请求期间修改的变量(即 HttpWebRequest.Coo
我正在使用 JScript.NET 在我编写的 C# WinForms 应用程序中编写脚本。它工作得很好,但我只是尝试在脚本中放置一些异常处理,但我无法弄清楚如何判断我的 C# 代码抛出了哪种类型的异
我需要你的帮助, 比如我有一个小数类型的变量,我想这样取整。 例如 3.0 = 3 3.1 = 4 3.2 = 4 3.3 = 4 3.4 = 4 3.5 = 4 3.6 = 4 3.7 = 4 3.
我使用过这样的代码:http://msdn.microsoft.com/en-us/library/dw70f090.aspx在 ASP.NET 中工作之前访问数据库(2-3 年前)。我没有意识到我正
自 ConfigurationManager .NET Standard 中不存在,检索正在执行的程序集的应用程序设置的最佳方法是什么,无论是 web.config或 appSettings.{env
我是一名优秀的程序员,十分优秀!