Asp.Net Core MVC框架内置过滤器
第一部分、MVC框架内置过滤器
下图展示了Asp.Net Core MVC框架默认实现的过滤器的执行顺序:
Authorization Filters:身份验证过滤器,处在整个过滤器通道的最顶层。对应的类型为: AuthorizeAttribute.cs
Resource Filters:资源过滤器。因为所有的请求和响应都将经过这个过滤器,所以在这一层可以实现类似缓存的功能。对应的接口有同步和异步两个版本: IResourceFilter.cs 、 IAsyncResourceFilter.cs
Action Filters:方法过滤器。在控制器的Action方法执行之前和之后被调用,一个很常用的过滤器。对应的接口有同步和异步两个版本: IActionFilter.cs 、 IAsyncActionFilter.cs
Exception Filters:异常过滤器。当Action方法执行过程中出现了未处理的异常,将会进入这个过滤器进行统一处理,也是一个很常用的过滤器。对应的接口有同步和异步两个版本: IExceptionFilter.cs 、 IAsyncExceptionFilter.cs
Result Filters:返回值过滤器。当Action方法执行完成的结果在组装或者序列化前后被调用。对应的接口有同步和异步两个版本: IResultFilter.cs 、 IAsyncResultFilter.cs
下面通过代码示例来演示上面图示里的流程顺序:
1. 在工程里分别添加如下几个过滤器
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace WebApiFrame.Core.Filters
{
public class SimpleResourceFilterAttribute : Attribute, IResourceFilter
{
private readonly ILogger<SimpleResourceFilterAttribute> logger;
public SimpleResourceFilterAttribute(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<SimpleResourceFilterAttribute>();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
logger.LogInformation("ResourceFilter Executed!");
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
logger.LogInformation("ResourceFilter Executing!");
}
}
}
SimpleResourceFilterAttribute.cs
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class SimpleResourceFilterAttribute : Attribute, IResourceFilter
8 {
9 private readonly ILogger<SimpleResourceFilterAttribute> logger;
10
11 public SimpleResourceFilterAttribute(ILoggerFactory loggerFactory)
12 {
13 logger = loggerFactory.CreateLogger<SimpleResourceFilterAttribute>();
14 }
15
16 public void OnResourceExecuted(ResourceExecutedContext context)
17 {
18 logger.LogInformation("ResourceFilter Executed!");
19 }
20
21 public void OnResourceExecuting(ResourceExecutingContext context)
22 {
23 logger.LogInformation("ResourceFilter Executing!");
24 }
25 }
26 }
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace WebApiFrame.Core.Filters
{
public class SimpleActionFilterAttribute : Attribute, IActionFilter
{
private readonly ILogger<SimpleActionFilterAttribute> logger;
public SimpleActionFilterAttribute(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<SimpleActionFilterAttribute>();
}
public void OnActionExecuted(ActionExecutedContext context)
{
logger.LogInformation("ActionFilter Executed!");
}
public void OnActionExecuting(ActionExecutingContext context)
{
logger.LogInformation("ActionFilter Executing!");
}
}
}
SimpleActionFilterAttribute.cs
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class SimpleActionFilterAttribute : Attribute, IActionFilter
8 {
9 private readonly ILogger<SimpleActionFilterAttribute> logger;
10
11 public SimpleActionFilterAttribute(ILoggerFactory loggerFactory)
12 {
13 logger = loggerFactory.CreateLogger<SimpleActionFilterAttribute>();
14 }
15
16 public void OnActionExecuted(ActionExecutedContext context)
17 {
18 logger.LogInformation("ActionFilter Executed!");
19 }
20
21 public void OnActionExecuting(ActionExecutingContext context)
22 {
23 logger.LogInformation("ActionFilter Executing!");
24 }
25 }
26 }
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace WebApiFrame.Core.Filters
{
public class SimpleExceptionFilterAttribute : Attribute, IExceptionFilter
{
private readonly ILogger<SimpleExceptionFilterAttribute> logger;
public SimpleExceptionFilterAttribute(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<SimpleExceptionFilterAttribute>();
}
public void OnException(ExceptionContext context)
{
logger.LogError("Exception Execute! Message:" + context.Exception.Message);
context.ExceptionHandled = true;
}
}
}
SimpleExceptionFilterAttribute.cs
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class SimpleExceptionFilterAttribute : Attribute, IExceptionFilter
8 {
9 private readonly ILogger<SimpleExceptionFilterAttribute> logger;
10
11 public SimpleExceptionFilterAttribute(ILoggerFactory loggerFactory)
12 {
13 logger = loggerFactory.CreateLogger<SimpleExceptionFilterAttribute>();
14 }
15
16 public void OnException(ExceptionContext context)
17 {
18 logger.LogError("Exception Execute! Message:" + context.Exception.Message);
19 context.ExceptionHandled = true;
20 }
21 }
22 }
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace WebApiFrame.Core.Filters
{
public class SimpleResultFilterAttribute : Attribute, IResultFilter
{
private readonly ILogger<SimpleResultFilterAttribute> logger;
public SimpleResultFilterAttribute(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<SimpleResultFilterAttribute>();
}
public void OnResultExecuted(ResultExecutedContext context)
{
logger.LogInformation("ResultFilter Executd!");
}
public void OnResultExecuting(ResultExecutingContext context)
{
logger.LogInformation("ResultFilter Executing!");
}
}
}
SimpleResultFilterAttribute.cs
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class SimpleResultFilterAttribute : Attribute, IResultFilter
8 {
9 private readonly ILogger<SimpleResultFilterAttribute> logger;
10
11 public SimpleResultFilterAttribute(ILoggerFactory loggerFactory)
12 {
13 logger = loggerFactory.CreateLogger<SimpleResultFilterAttribute>();
14 }
15
16 public void OnResultExecuted(ResultExecutedContext context)
17 {
18 logger.LogInformation("ResultFilter Executd!");
19 }
20
21 public void OnResultExecuting(ResultExecutingContext context)
22 {
23 logger.LogInformation("ResultFilter Executing!");
24 }
25 }
26 }
2. 修改 Startup.cs 内的ConfigureServices方法,作为全局过滤器添加到MVC框架内
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WebApiFrame.Core.Filters;
namespace WebApiFrame
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 注入MVC框架
services.AddMvc(options =>
{
options.Filters.Add(typeof(SimpleResourceFilterAttribute));
options.Filters.Add(typeof(SimpleActionFilterAttribute));
options.Filters.Add(typeof(SimpleExceptionFilterAttribute));
options.Filters.Add(typeof(SimpleResultFilterAttribute));
});
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
// 添加日志支持
loggerFactory.WithFilter(new FilterLoggerSettings()
{
{ "Microsoft", LogLevel.Warning }
})
.AddConsole().AddDebug();
// 添加NLog日志支持
//loggerFactory.AddNLog();
// 添加MVC中间件
app.UseMvc();
}
}
}
Startup.cs
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Core.Filters;
5
6 namespace WebApiFrame
7 {
8 public class Startup
9 {
10 public void ConfigureServices(IServiceCollection services)
11 {
12 // 注入MVC框架
13 services.AddMvc(options =>
14 {
15 options.Filters.Add(typeof(SimpleResourceFilterAttribute));
16 options.Filters.Add(typeof(SimpleActionFilterAttribute));
17 options.Filters.Add(typeof(SimpleExceptionFilterAttribute));
18 options.Filters.Add(typeof(SimpleResultFilterAttribute));
19 });
20 }
21
22 public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
23 {
24 // 添加日志支持
25 loggerFactory.WithFilter(new FilterLoggerSettings()
26 {
27 { "Microsoft", LogLevel.Warning }
28 })
29 .AddConsole().AddDebug();
30
31 // 添加NLog日志支持
32 //loggerFactory.AddNLog();
33
34 // 添加MVC中间件
35 app.UseMvc();
36 }
37 }
38 }
3. 控制器添加两个方法,一个方法正常返回内容,另一个方法抛出一个未处理的异常
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using WebApiFrame.Models;
namespace WebApiFrame.Controllers
{
[Route("api/[controller]")]
public class UsersController : Controller
{
private ILogger<UsersController> _logger;
public UsersController(ILogger<UsersController> logger){
_logger = logger;
}
[HttpGet]
public IActionResult GetAll(){
throw new Exception("GetAll function failed!");
}
[HttpGet("{id}")]
public IActionResult Get(int id)
{
var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
return new ObjectResult(user);
}
[HttpPost]
public IActionResult Post([FromBody] User user){
if(user == null){
return BadRequest();
}
// TODO:新增操作
user.Id = new Random().Next(1, 10);
return CreatedAtAction("Get", new { id = user.Id }, user);
}
[HttpPut("{id}")]
public IActionResult Put(int id, [FromBody] User user){
if(user == null){
return BadRequest();
}
// TODO: 更新操作
return new NoContentResult();
}
[HttpDelete("{id}")]
public void Delete(int id){
// TODO: 删除操作
}
}
}
UsersController.cs
1 using System;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Models;
5
6 namespace WebApiFrame.Controllers
7 {
8
9 [Route("api/[controller]")]
10 public class UsersController : Controller
11 {
12 private ILogger<UsersController> _logger;
13
14 public UsersController(ILogger<UsersController> logger){
15 _logger = logger;
16 }
17
18 [HttpGet]
19 public IActionResult GetAll(){
20 throw new Exception("GetAll function failed!");
21 }
22
23 [HttpGet("{id}")]
24 public IActionResult Get(int id)
25 {
26 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
27 return new ObjectResult(user);
28 }
29
30 [HttpPost]
31 public IActionResult Post([FromBody] User user){
32 if(user == null){
33 return BadRequest();
34 }
35
36 // TODO:新增操作
37 user.Id = new Random().Next(1, 10);
38 return CreatedAtAction("Get", new { id = user.Id }, user);
39 }
40
41 [HttpPut("{id}")]
42 public IActionResult Put(int id, [FromBody] User user){
43 if(user == null){
44 return BadRequest();
45 }
46
47 // TODO: 更新操作
48 return new NoContentResult();
49 }
50
51 [HttpDelete("{id}")]
52 public void Delete(int id){
53 // TODO: 删除操作
54
55 }
56 }
57 }
4. 打开cmd窗口,使用命令行 dotnet run 启动程序,访问地址 http://localhost:5000/api/users/1 ,查看窗口日志,会发现日志打印顺序与图片标识顺序相符。
再次访问地址 http://localhost:5000/api/users/ ,查看窗口日志,发现异常过滤器被调用,输出了异常日志
第二部分、过滤器的引用
先创建一个自定义的ActionFilter作为演示例子
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3
4 namespace WebApiFrame.Core.Filters
5 {
6 public class MyActionFilterAttribute : Attribute, IActionFilter
7 {
8 public void OnActionExecuted(ActionExecutedContext context)
9 {
10
11 }
12
13 public void OnActionExecuting(ActionExecutingContext context)
14 {
15 context.HttpContext.Response.Headers.Add("My-Header", "WebApiFrame-Header");
16 }
17 }
18 }
一、作为特性标识引用
标识在控制器上,则访问这个控制器下的所有方法都将调用这个过滤器
1 using System;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Core.Filters;
5 using WebApiFrame.Models;
6
7 namespace WebApiFrame.Controllers
8 {
9
10 [Route("api/[controller]")]
11 [MyActionFilter]
12 public class UsersController : Controller
13 {
14 private ILogger<UsersController> _logger;
15
16 public UsersController(ILogger<UsersController> logger)
17 {
18 _logger = logger;
19 }
20
21 [HttpGet]
22 public IActionResult GetAll()
23 {
24 throw new Exception("GetAll function failed!");
25 }
26
27 [HttpGet("{id}")]
28 public IActionResult Get(int id)
29 {
30 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
31 return new ObjectResult(user);
32 }
33
34 #region 其他方法
35 // ......
36 #endregion
37 }
38 }
通过Fiddle工具访问地址 http://localhost:5000/api/users/1 ,查看响应内容,可以发现响应头部增加了自定义内容
也可以标识在方法上,则只有被标识的方法被调用时才会调用过滤器
1 using System;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Core.Filters;
5 using WebApiFrame.Models;
6
7 namespace WebApiFrame.Controllers
8 {
9
10 [Route("api/[controller]")]
11 public class UsersController : Controller
12 {
13 private ILogger<UsersController> _logger;
14
15 public UsersController(ILogger<UsersController> logger)
16 {
17 _logger = logger;
18 }
19
20 [HttpGet]
21 public IActionResult GetAll()
22 {
23 throw new Exception("GetAll function failed!");
24 }
25
26 [HttpGet("{id}")]
27 [MyActionFilter]
28 public IActionResult Get(int id)
29 {
30 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
31 return new ObjectResult(user);
32 }
33
34 #region 其他方法
35 // ......
36 #endregion
37 }
38 }
二、全局过滤器
在第一部分的示例中采用的就是全局过滤器的方式。使用了全局过滤器后,所有的控制器下的所有方法被调用时都将调用这个过滤器。
下面的代码示例是通过生成实例的形式注册过滤器
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Core.Filters;
5
6 namespace WebApiFrame
7 {
8 public class Startup
9 {
10 public void ConfigureServices(IServiceCollection services)
11 {
12 // 注入MVC框架
13 services.AddMvc(options =>
14 {
15 options.Filters.Add(new MyActionFilterAttribute());
16 });
17 }
18
19 public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
20 {
21 // 添加日志支持
22 loggerFactory.WithFilter(new FilterLoggerSettings()
23 {
24 { "Microsoft", LogLevel.Warning }
25 })
26 .AddConsole().AddDebug();
27
28 // 添加NLog日志支持
29 //loggerFactory.AddNLog();
30
31 // 添加MVC中间件
32 app.UseMvc();
33 }
34 }
35 }
也可以通过类型进行注册
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Core.Filters;
5
6 namespace WebApiFrame
7 {
8 public class Startup
9 {
10 public void ConfigureServices(IServiceCollection services)
11 {
12 // 注入MVC框架
13 services.AddMvc(options =>
14 {
15 // 实例注册
16 //options.Filters.Add(new MyActionFilterAttribute());
17
18 // 类型注册
19 options.Filters.Add(typeof(MyActionFilterAttribute));
20 });
21 }
22
23 public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
24 {
25 // 添加日志支持
26 loggerFactory.WithFilter(new FilterLoggerSettings()
27 {
28 { "Microsoft", LogLevel.Warning }
29 })
30 .AddConsole().AddDebug();
31
32 // 添加NLog日志支持
33 //loggerFactory.AddNLog();
34
35 // 添加MVC中间件
36 app.UseMvc();
37 }
38 }
39 }
三、通过ServiceFilter引用
通过在控制器或者Action方法上使用ServiceFilter特性标识引用过滤器。通过此方法可以将通过构造方法进行注入并实例化的过滤器引入框架内。
修改一下 MyActionFilterAttribute.cs 内容,添加一个带参数的构造方法,引入日志记录
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class MyActionFilterAttribute : Attribute, IActionFilter
8 {
9 private readonly ILogger<MyActionFilterAttribute> logger;
10
11 public MyActionFilterAttribute(ILoggerFactory loggerFactory)
12 {
13 logger = loggerFactory.CreateLogger<MyActionFilterAttribute>();
14 }
15
16 public void OnActionExecuted(ActionExecutedContext context)
17 {
18
19 }
20
21 public void OnActionExecuting(ActionExecutingContext context)
22 {
23 context.HttpContext.Response.Headers.Add("My-Header", "WebApiFrame-Header");
24 logger.LogInformation("MyActionFilterAttribute Executiong!");
25 }
26 }
27 }
修改 Startup.cs 的ConfigureServices方法,将过滤器类型注入到DI(依赖注入)容器里
1 public void ConfigureServices(IServiceCollection services)
2 {
3 // 注入MVC框架
4 services.AddMvc(options =>
5 {
6 // 实例注册
7 //options.Filters.Add(new MyActionFilterAttribute());
8
9 // 类型注册
10 //options.Filters.Add(typeof(MyActionFilterAttribute));
11 });
12
13 // 将过滤器类型添加到DI容器里
14 services.AddScoped<MyActionFilterAttribute>();
15 }
四、通过TypeFilter引入
再次修改 MyActionFilterAttribute.cs 的构造器方法,添加普通的参数
1 using System;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class MyActionFilterAttribute : Attribute, IActionFilter
8 {
9 private readonly string _key;
10 private readonly string _value;
11
12 public MyActionFilterAttribute(string key, string value)
13 {
14 _key = key;
15 _value = value;
16 }
17
18 public void OnActionExecuting(ActionExecutingContext context)
19 {
20 context.HttpContext.Response.Headers.Add(_key, _value);
21 }
22
23 public void OnActionExecuted(ActionExecutedContext context)
24 {
25
26 }
27 }
28 }
在 UsersController.cs 控制器的Action方法上添加特性标识,同时注释掉 Startup.cs 的ConfigureServices的类型注入方法。因为用TypeFilter引用过滤器不需要将类型注入到DI容器
1 [HttpGet("{id}")]
2 [TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[]{ "My-Header", "WebApiFrame-Header" })]
3 public IActionResult Get(int id)
4 {
5 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
6 return new ObjectResult(user);
7 }
另外,也可以通过TypeFilter引用需要通过构造方法注入进行实例化的过滤器。将上面第三点的例子里的进行改写
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.AspNetCore.Mvc.Filters;
3 using Microsoft.Extensions.Logging;
4
5 namespace WebApiFrame.Core.Filters
6 {
7 public class MyActionFilterAttribute : TypeFilterAttribute
8 {
9 public MyActionFilterAttribute() : base(typeof(MyActionFilterImpl))
10 {
11
12 }
13
14 private class MyActionFilterImpl : IActionFilter
15 {
16 private readonly ILogger<MyActionFilterImpl> logger;
17
18 public MyActionFilterImpl(ILoggerFactory loggerFactory)
19 {
20 logger = loggerFactory.CreateLogger<MyActionFilterImpl>();
21 }
22
23 public void OnActionExecuting(ActionExecutingContext context)
24 {
25 context.HttpContext.Response.Headers.Add("My-Header", "WebApiFrame-Header");
26 logger.LogInformation("MyActionFilterAttribute Executiong!");
27 }
28
29 public void OnActionExecuted(ActionExecutedContext context)
30 {
31
32 }
33 }
34 }
35 }
修改 UsersController.cs 控制器的Action方法的特性标识
1 [HttpGet("{id}")]
2 [MyActionFilter]
3 public IActionResult Get(int id)
4 {
5 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
6 return new ObjectResult(user);
7 }
第三部分、自定义过滤器执行顺序
以ActionFilter执行顺序为例,默认执行顺序如下图
1. Controller OnActionExecuting
2. Global OnActionExecuting
3. Class OnActionExecuting
4. Method OnActionExecuting
5. Method OnActionExecuted
6. Class OnActionExecuted
7. Global OnActionExecuted
8. Controller OnActionExecuted
下面用代码验证这个顺序
修改 MyActionFilterAttribute.cs 内容。添加实现接口 IOrderedFilter.cs ,设置默认顺序为0
using System;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging; namespace WebApiFrame.Core.Filters
{
public class MyActionFilterAttribute : Attribute, IActionFilter, IOrderedFilter
{
private readonly int _order; private readonly string _target; private readonly ILogger<MyActionFilterAttribute> logger; public int Order
{
get
{
return _order;
}
} public MyActionFilterAttribute(string target, int order = 0)
{
_order = order;
_target = target; ILoggerFactory loggerFactory = new LoggerFactory();
loggerFactory.WithFilter(new FilterLoggerSettings()
{
{ "Microsoft", LogLevel.Warning }
})
.AddConsole().AddDebug(); logger = loggerFactory.CreateLogger<MyActionFilterAttribute>();
} public void OnActionExecuted(ActionExecutedContext context)
{
logger.LogInformation($"{_target} Executed!");
} public void OnActionExecuting(ActionExecutingContext context)
{
logger.LogInformation($"{_target} Executing!");
}
}
}
在 UsersController.cs 重写OnActionExecuting和OnActionExecuted。同时分别注册全局过滤器、标识控制器过滤器和方法过滤器
1 using System;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.AspNetCore.Mvc.Filters;
4 using Microsoft.Extensions.Logging;
5 using WebApiFrame.Core.Filters;
6 using WebApiFrame.Models;
7
8 namespace WebApiFrame.Controllers
9 {
10
11 [Route("api/[controller]")]
12 [MyActionFilter("Class")]
13 public class UsersController : Controller
14 {
15 private ILogger<UsersController> _logger;
16
17 public UsersController(ILogger<UsersController> logger)
18 {
19 _logger = logger;
20 }
21
22 [HttpGet]
23 public IActionResult GetAll()
24 {
25 throw new Exception("GetAll function failed!");
26 }
27
28 [HttpGet("{id}")]
29 [MyActionFilter("Method")]
30 public IActionResult Get(int id)
31 {
32 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
33 return new ObjectResult(user);
34 }
35
36 public override void OnActionExecuting(ActionExecutingContext context)
37 {
38 _logger.LogInformation("Controller Executing!");
39 }
40
41 public override void OnActionExecuted(ActionExecutedContext context)
42 {
43 _logger.LogInformation("Controller Executd!");
44 }
45
46 #region 其他方法
47 // ......
48 #endregion
49 }
50 }
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Logging;
4 using WebApiFrame.Core.Filters;
5
6 namespace WebApiFrame
7 {
8 public class Startup
9 {
10 public void ConfigureServices(IServiceCollection services)
11 {
12 // 注入MVC框架
13 services.AddMvc(options =>
14 {
15 // 实例注册
16 options.Filters.Add(new MyActionFilterAttribute("Global"));
17 });
18 }
19
20 // ......
21 }
22 }
启动程序,访问地址 http://localhost:5000/api/users/1 ,查看日志
接下来,修改一下标识方法控制器的参数
1 [HttpGet("{id}")]
2 [MyActionFilter("Method", -1)]
3 public IActionResult Get(int id)
4 {
5 var user = new User() { Id = id, Name = "Name:" + id, Sex = "Male" };
6 return new ObjectResult(user);
7 }
再次启动程序,访问地址 http://localhost:5000/api/users/1 ,查看日志
当顺序被设置为-1时,对应标识位置的过滤器将优先调用。但是无法先于控制器的重写方法调用。
第四部分、过滤器与中间件
1. 过滤器是MVC框架的一部分,中间件属于Asp.Net Core管道的一部分。
2. 过滤器在处理请求和响应时更加的精细一些,在用户权限、资源访问、Action执行、异常处理、返回值处理等方面都能进行控制和处理。而中间件只能粗略的过滤请求和响应。
Asp.Net Core MVC框架内置过滤器的更多相关文章
- asp.net core MVC 过滤器之ActionFilter过滤器(二)
本系类将会讲解asp.net core MVC中的内置全局过滤器的使用,将分为以下章节 asp.net core MVC 过滤器之ExceptionFilter过滤器(一) asp.net core ...
- 通过极简模拟框架让你了解ASP.NET Core MVC框架的设计与实现[上篇]
<200行代码,7个对象--让你了解ASP.NET Core框架的本质>让很多读者对ASP.NET Core管道有了真实的了解.在过去很长一段时间中,有很多人私信给我:能否按照相同的方式分 ...
- ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用
一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 使用Visual Studio Code开发基于解决方案(sln+csproj)的项目 Visual ...
- ASP.NET Core 入门笔记3,使用ASP.NET Core MVC框架构建Web应用
一.ASP.NET Core MVC 输出Hello World,Friend! 1.引入 ASP.NET Core MVC 修改应用启动类(Startup.cs),引入MVC模块并配置默认路由 pu ...
- 阅读了这三篇文章,你也就基本理解了ASP.NET Core MVC框架的工作原理
<200行代码,7个对象--让你了解ASP.NET Core框架的本质>让很多读者对ASP.NET Core管道有深刻的理解,知道了ASP.NET Core框架针对每个请求的处理流程.在过 ...
- asp.net core MVC 过滤器之ExceptionFilter过滤器(一)
简介 异常过滤器,顾名思义,就是当程序发生异常时所使用的过滤器.用于在系统出现未捕获异常时的处理. 实现一个自定义异常过滤器 自定义一个异常过滤器需要实现IExceptionFilter接口 publ ...
- ASP.NET Core 入门教程 4、ASP.NET Core MVC控制器入门
一.前言 1.本教程主要内容 ASP.NET Core MVC控制器简介 ASP.NET Core MVC控制器操作简介 ASP.NET Core MVC控制器操作简介返回类型简介 ASP.NET C ...
- ASP.NET Core 入门笔记5,ASP.NET Core MVC控制器入门
摘抄自https://www.cnblogs.com/ken-io/p/aspnet-core-tutorial-mvc-controller-action.html 一.前言 1.本教程主要内容 A ...
- ASP.NET Core 中文文档 第四章 MVC(01)ASP.NET Core MVC 概览
原文:Overview of ASP.NET Core MVC 作者:Steve Smith 翻译:张海龙(jiechen) 校对:高嵩 ASP.NET Core MVC 是使用模型-视图-控制器(M ...
随机推荐
- Oracle ASM 相关的 视图(V$) 和 数据字典(X$)
本文转自: http://blog.csdn.net/tianlesoftware/article/details/6733039 ASM由于其高度的封装性,使得我们很难知道窥探其内部的原理.可以通过 ...
- C# Winform 中如何获取本机安装输入法,并设置为默认输出语言,如何打开搜狗输入法和手写板
一.问题: 今天,我整理了一下两个问题 1.如何获取本机安装所有输入法,并设置为系统输出语言 2.如何打开搜狗拼音输入法工具栏和手写板: 二.解决方法 比如:我们要设置搜狗输入法为本机输入语言,要怎么 ...
- Windows各种各种消息投递函数
1.SendMessage:发送消息给指定的窗口过程:直到窗口过程处理了消息才返回. 2.PostMessage:将消息放入消息队列(与指定窗口创建的线程相关)中:无需等待消息处理,立即返回. 不 ...
- 各种格式的压缩包解压,7zip 命令行
由于7z.exe所在路径,以及解压目录中可能包含中文特殊字符,导致解压失败,所以最好将各部分路径使用双引号包含起来. 如:CString str; str.Format(L"\"% ...
- flask+APScheduler 任务调度,计划任务,定时任务
from flask import Flask from flask_apscheduler import APScheduler # 引入APScheduler from test124 impor ...
- 指针和const一些注意事项
1.常量指针(底层const) 指向常量的指针,指针所指向的对象的值无法被修改,若想存放常量对象的地址,只能使用指向常量的指针. 2.指针常量(顶层const) 指针本身是常量,指针本身的值不可修改. ...
- xml与json
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式. JSON现在基本上作为前后端数据交互的重要载体,在JSON之前,前后端主要的传输方式主要是通过XML或者文 ...
- 【Android 】查看被测应用程序package和launchable-activity
[appt] appt 工具所在位置..\sdk\build-tools\23.0.1\aapt.exe #查看Package>aapt dump badging C:\QQemail.apk ...
- tensorflow中的参数初始化方法
1. 初始化为常量 tf中使用tf.constant_initializer(value)类生成一个初始值为常量value的tensor对象. constant_initializer类的构造函数定义 ...
- [LeetCode&Python] Problem 559. Maximum Depth of N-ary Tree
Given a n-ary tree, find its maximum depth. The maximum depth is the number of nodes along the longe ...