asp.net core 终结点 Action
net core 3 时代
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
6.0 默认的终结点匹配简化:
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
再看 MapControllerRoute的源码如下:
public static ControllerActionEndpointConventionBuilder MapControllerRoute( this IEndpointRouteBuilder endpoints, string name, string pattern, object? defaults = null, object? constraints = null, object? dataTokens = null) { if (endpoints == null) { throw new ArgumentNullException(nameof(endpoints)); } EnsureControllerServices(endpoints); //MvcMarkerService var dataSource = GetOrCreateDataSource(endpoints); return dataSource.AddRoute( name, pattern, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens)); }
private static ControllerActionEndpointDataSource GetOrCreateDataSource(IEndpointRouteBuilder endpoints) { var dataSource = endpoints.DataSources.OfType<ControllerActionEndpointDataSource>().FirstOrDefault(); if (dataSource == null) { var orderProvider = endpoints.ServiceProvider.GetRequiredService<OrderedEndpointsSequenceProviderCache>(); var factory = endpoints.ServiceProvider.GetRequiredService<ControllerActionEndpointDataSourceFactory>(); dataSource = factory.Create(orderProvider.GetOrCreateOrderedEndpointsSequenceProvider(endpoints)); endpoints.DataSources.Add(dataSource); } return dataSource; }
如上图 从service中获取ControllerActionEndpointDataSource实例的时候,也会初始化ControllerActionDescriptorProvider和DefaultActionDescriptorCollectionProvider,
ControllerActionEndpointDataSource的构造函数如下
public ControllerActionEndpointDataSource( ControllerActionEndpointDataSourceIdProvider dataSourceIdProvider, IActionDescriptorCollectionProvider actions, ActionEndpointFactory endpointFactory, OrderedEndpointsSequenceProvider orderSequence) : base(actions) { _endpointFactory = endpointFactory; DataSourceId = dataSourceIdProvider.CreateId(); _orderSequence = orderSequence; _routes = new List<ConventionalRouteEntry>(); DefaultBuilder = new ControllerActionEndpointConventionBuilder(Lock, Conventions); // IMPORTANT: this needs to be the last thing we do in the constructor. // Change notifications can happen immediately! Subscribe(); }
Subscribe 会调用到DefaultActionDescriptorCollectionProvider对象的UpdateCollection 执行ControllerActionDescriptorProvider的如下方法,实现把Action加入到ActionDescriptorProviderContext中
public void OnProvidersExecuting(ActionDescriptorProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } foreach (var descriptor in GetDescriptors()) { context.Results.Add(descriptor); } } internal IEnumerable<ControllerActionDescriptor> GetDescriptors() { var controllerTypes = GetControllerTypes(); var application = _applicationModelFactory.CreateApplicationModel(controllerTypes); return ControllerActionDescriptorBuilder.Build(application); }
作者:RunStone
出处:https://www.cnblogs.com/RunStone/p/16805211.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构