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