Loading

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);
        }

 

posted @ 2022-10-20 22:11  奔跑石头  阅读(69)  评论(0)    收藏  举报