asp.net core 终结点 Action
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); }

浙公网安备 33010602011771号