ASP.NET Core替换Action实际执行方法
RequestDelegate
上次,我们在《如何判断当前请求的API类型》中查看endpoints.MapControllers()实现时,最终定位到ActionEndpointFactory.cs,其中有这样一段代码:
private static RequestDelegate CreateRequestDelegate()
{
// We don't want to close over the Invoker Factory in ActionEndpointFactory as
// that creates cycles in DI. Since we're creating this delegate at startup time
// we don't want to create all of the things we use at runtime until the action
// actually matches.
//
// The request delegate is already a closure here because we close over
// the action descriptor.
IActionInvokerFactory? invokerFactory = null;
return (context) =>
{
var endpoint = context.GetEndpoint()!;
var dataTokens = endpoint.Metadata.GetMetadata<IDataTokensMetadata>();
var routeData = new RouteData();
routeData.PushState(router: null, context.Request.RouteValues, new RouteValueDictionary(dataTokens?.DataTokens));
// Don't close over the ActionDescriptor, that's not valid for pages.
var action = endpoint.Metadata.GetMetadata<ActionDescriptor>()!;
var actionContext = new ActionContext(context, routeData, action);
if (invokerFactory == null)
{
invokerFactory = context.RequestServices.GetRequiredService<IActionInvokerFactory>();
}
var invoker = invokerFactory.CreateInvoker(actionContext);
return invoker!.InvokeAsync();
};
}
从代码上理解,应该是执行请求时,会创建IActionInvokerFactory实例,由它创建 invoker 执行。
是不是这样呢,我们验证一下!
IActionInvokerFactory
新建CustomActionInvokerFactory.cs,继承IActionInvokerFactory,实现代码如下:
public class CustomActionInvokerFactory : IActionInvokerFactory
{
private readonly IActionInvokerProvider[] _actionInvokerProviders;
public ActionInvokerFactory(IEnumerable<IActionInvokerProvider> actionInvokerProviders)
{
_actionInvokerProviders = actionInvokerProviders.OrderBy(item => item.Order).ToArray();
}
public IActionInvoker? CreateInvoker(ActionContext actionContext)
{
var context = new ActionInvokerProviderContext(actionContext);
foreach (var provider in _actionInvokerProviders)
{
provider.OnProvidersExecuting(context);
}
for (var i = _actionInvokerProviders.Length - 1; i >= 0; i--)
{
_actionInvokerProviders[i].OnProvidersExecuted(context);
}
return context.Result;
}
}
代码 Copy 自 ASP.NET Core 内部实现类ActionInvokerFactory。
然后在 Startup.cs 注册实现:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IActionInvokerFactory, CustomActionInvokerFactory>();
...
}
打上断点,执行API,发现确实如设想中一样,请求时执行CreateInvoker方法:


查看ControllerActionInvokerCache.cs实现:
var objectMethodExecutor = ObjectMethodExecutor.Create(
actionDescriptor.MethodInfo,
actionDescriptor.ControllerTypeInfo,
parameterDefaultValues);
原来,还要替换actionDescriptor.ControllerTypeInfo:
var actionDescriptor = actionContext.ActionDescriptor as ControllerActionDescriptor;
actionDescriptor.MethodInfo = typeof(WeatherForecast2Controller).GetMethod("Get2");
actionDescriptor.ControllerTypeInfo = typeof(WeatherForecast2Controller).GetTypeInfo();
再次运行,执行成功!

结论
替换 Action 实际执行方法,最好的使用场景是定制化开发,比如客户需求和产品实现完全不同,可以保证请求不变的情况下执行客户定制化实现。
ASP.NET Core替换Action实际执行方法的更多相关文章
- 《ASP.NET Core In Action》读书笔记系列一 ASP.NET Core 的诞生
最近打算系统学习一下asp.net core ,苦于没有好的中文书藉,只好找来一本英文的 <ASP.NET Core In Action>学习.我和多数人一样,学习英文会明显慢于中文.希 ...
- 《ASP.NET Core In Action》读书笔记系列,这是一个手把手的从零开始的教学系列目录
最近打算系统学习一下asp.net core ,苦于没有好的中文书藉,只好找来一本英文的 <ASP.NET Core In Action>学习.我和多数人一样,学习英文会明显慢于中文.希 ...
- 第12章 使用 Entity Framework Core 保存数据(ASP.NET Core in Action, 2nd Edition)
本章包括(请点击这里阅读其他章节) 什么是实体框架核心以及为什么应该使用它 向 ASP.NET Core 应用程序添加实体框架核心 构建数据模型并使用它创建数据库 使用实体框架核心查询.创建和更新数据 ...
- 第10章 带有依赖注入的服务配置(ASP.NET Core in Action, 2nd Edition)
第2部分 构建完整的应用程序 我们在第一部分中讨论了很多内容.您看到了ASP.NET Core应用程序是如何由中间件组成的,我们主要关注RazorPages框架.您了解了如何使用Razor语法构建传统 ...
- 第9章 使用MVC为移动和客户端应用程序创建Web API(ASP.NET Core in Action, 2nd Edition)
本章包括 创建Web API控制器以向客户端返回JSON 使用属性路由自定义URL 使用内容协商生成响应 使用[ApiController]属性应用通用约定 在前五章中,您已经完成了服务器端渲染ASP ...
- 第8章 使用标记帮助工具构建表单(ASP.NET Core in Action, 2nd Edition)
本章包括 使用Tag Helpers轻松构建表单 使用锚标记帮助程序生成URL 使用Tag Helpers为Razor添加功能 在第7章中,您了解了Razor模板以及如何使用它们为应用程序生成视图.通 ...
- asp.net core 动态更新 appsetting.json方法
如何将值更新到appsetting.json? 我正在使用官方文档中IOptions描述的模式. 当我从中读取值时appsetting.json,这可以正常工作,但是如何更新值并将更改保存回来apps ...
- 第17章 使用日志记录监视和排除错误(ASP.NET Core in Action, 2nd Edition)
第3部分 扩展应用程序 我们在第1部分和第2部分中介绍了大量内容:我们查看了您将用于构建传统服务器渲染的 Razor Pages 应用程序以及 Web API 的所有主要功能组件.在第3部分中,我们将 ...
- 第15章 授权:保护您的应用程序(ASP.NET Core in Action, 2nd Edition)
本章包括 使用授权控制谁可以使用你的应用 对策略使用基于声明的授权 创建自定义策略以处理复杂的需求 根据所访问的资源授权请求 隐藏用户未经授权访问的Razor模板中的元素 在第14章中,我向您展示了如 ...
- 第14章 身份验证:使用Identity将用户添加到应用程序(ASP.NET Core in Action, 2nd Edition)
本章包括 ASP.NET Core中web应用程序的身份验证工作原理 使用ASP.NET Core标识系统创建项目 向现有web应用添加用户功能 自定义默认ASP.NET Core标识UI 像ASPN ...
随机推荐
- .NET MAUI开源免费的UI工具包 - Uranium
前言 一直有小伙伴在微信公众号后台留言让我分享一下.NET MAUI相关的UI框架,今天大姚分享一个.NET MAUI开源.免费的UI工具包:Uranium. Uranium介绍 Uranium是一个 ...
- 抓包整理————tcp 三次握手[九]
前言 简单抓包一下3次握手. 正文 握手的目标: 同步sequence 序列化 初始化序列化ISN(Initial Sequence Number) 交换tcp 通信参数 如MSS.窗口比例因子.选择 ...
- huggingface vit训练CIFAR10数据集代码 ,可以改dataset训练自己的数据
上代码,使用hugging face fineturn vit模型 自己写的代码 from transformers import ViTImageProcessor, ViTForImageClas ...
- CF1995E Long Inversions(贪心 + 差分)
见代码 点击查看代码 //背景:夸一下自己,CF1955A~E均是自己想出来的,这道题思路是自己想的,唯一没想到用差分数组维护 //原理:贪心(想最左边的1开始,不可能对其左边包括自己操作了,否则又要 ...
- PolarDB-X拆分键推荐
简介: PolarDB-X 2.0提供了透明分布式的能力,默认进行主键的哈希拆分,让用户无感知的从单机数据库迁移到分布式数据库.拆分键的选择是学术界和工业界研究已久的问题,一个重要选型是tp优先还是a ...
- 🎊这个 OpenTiny 开源项目的 CLI 可太牛了,两行命令创建一个美观大气的 Vue Admin 后台管理系统,有手就会,连我的设计师朋友都学会啦啦
大家好,我是 Kagol,OpenTiny 开源社区运营,TinyVue 跨端.跨框架组件库核心贡献者,专注于前端组件库建设和开源社区运营. 近期尝试了下 OpenTiny 的 CLI 工具,不得不说 ...
- WPF 简单实现一个支持删除自身的应用
我准备写一个逗比的应用,然而我担心被小伙伴看到这个应用的文件从而知道是我写的,于是我就需要实现让应用能自删除的功能.核心实现方法就是调用 cmd 传入命令行,等待几秒之后删除文件 应用程序在运行时,是 ...
- k8s安全---安全机制之RBAC授权(14)
一.k8s 安全管理:认证.授权.准入控制概述 k8s 对我们整个系统的认证,授权,访问控制做了精密的设置:对于 k8s 集群来说,apiserver 是整 个集群访问控制的唯一入口,我们在 k8s ...
- js的几个截取
jsfun(){ let str = '01234567' let str1 str1 = str.slice(2,5) ...
- Mybatis学习四(分页助手pagehelper)
Mybatis学习过程中有一个很重要的插件分页助手(pagehelper) 能够运用这个插件也非常简单 1.导入jar包 [jsqlparser-2.0.jar包] [点击下载https://gith ...