天天看點

.net core startup中執行controller下的action

private static async Task DriveControllerAction(HttpContext context, RouteData routeData, IApplicationBuilder app)
        {
            var actionDesciptor = CreateActionDescriptor<HomeController>(nameof(HomeController.Init), routeData);
            var actionContext = new ActionContext(context, routeData, actionDesciptor);
            var actionInvokerFactory = app.ApplicationServices.GetRequiredService<IActionInvokerFactory>(); //ActionInvokerFactory
            IActionInvoker invoker = actionInvokerFactory.CreateInvoker(actionContext); //ControllerActionInvoker
            await invoker.InvokeAsync();
        }
           
private static ActionDescriptor CreateActionDescriptor<TController>(string actionName, RouteData routeData)
        {
            var controllerType = typeof(TController);
            var actionDesciptor = new ControllerActionDescriptor()
            {
                ControllerName = controllerType.Name,
                ActionName = actionName,
                FilterDescriptors = new List<FilterDescriptor>(),
                MethodInfo = controllerType.GetMethod(actionName, BindingFlags.Public | BindingFlags.Instance),
                ControllerTypeInfo = controllerType.GetTypeInfo(),
                Parameters = new List<ParameterDescriptor>(),
                Properties = new Dictionary<object, object>(),
                BoundProperties = new List<ParameterDescriptor>()
            };

            if (actionDesciptor.MethodInfo == null)
            {
                throw new ArgumentNullException($"actionDesciptor.MethodInfo for '{actionName}'");
            }

            //For searching View
            routeData.Values.Add("controller", actionDesciptor.ControllerName.Replace("Controller", ""));
            routeData.Values.Add("action", actionDesciptor.ActionName);

            //For binding action parameters
            foreach (var routeValue in routeData.Values)
            {
                var parameter = new ParameterDescriptor
                {
                    Name = routeValue.Key
                };
                var attributes = new object[]
                {
                    new FromRouteAttribute { Name = parameter.Name },
                };
                parameter.BindingInfo = BindingInfo.GetBindingInfo(attributes);
                parameter.ParameterType = routeValue.Value.GetType();
                actionDesciptor.Parameters.Add(parameter);
            }

            return actionDesciptor;
        }
           
public override void Configure(IApplicationBuilder app)
        {
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    var routeData = new RouteData();
                    routeData.Values.Add("message", "Hello World!");
                    await DriveControllerAction(context, routeData, app);
                });
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=job}/{action=Index}/{id?}");
            });
        }