ASP.NET Core Resolve Controller 并按名称调用 Action

ASP.NET Core Resolve Controller and call Action by name

我有一个通用的捕获所有 controller/action 接收文件,解析 json 内容并从中找出要调用的控制器名称和操作名称。

这是我以前的 .NET Framework(旧 ASP)实现,效果很好:

public async Task<ActionResult> Run(PackingSlip packingSlip, IEnumerable<HttpPostedFileBase> files)
{
    var controllerName = packingSlip.service_name;
    var actionName = packingSlip.service_object;

    // get the controller
    var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
    var ctrl = ctrlFactory.CreateController(this.Request.RequestContext, controllerName) as Controller;
    var ctrlContext = new ControllerContext(this.Request.RequestContext, ctrl);
    var ctrlDescAsync = new ReflectedAsyncControllerDescriptor(ctrl.GetType());
    ctrl.ControllerContext = ctrlContext;

    // get the action
    var actionDesc = ctrlDescAsync.FindAction(ctrlContext, actionName);

    // execute
    ActionResult result;
    if (actionDesc is AsyncActionDescriptor actionDescAsync)
        result = await Task.Factory.FromAsync((asyncCallback, asyncState) => actionDescAsync.BeginExecute(ctrlContext, new Dictionary<string, object> { { "packingSlip", packingSlip }, { "files", files } }, asyncCallback, asyncState), asyncResult => actionDescAsync.EndExecute(asyncResult), null) as ActionResult;
    else
        result = actionDesc.Execute(ctrlContext, new Dictionary<string, object> { { "packingSlip", packingSlip }, { "files", files } }) as ActionResult;

    // return the other action result as the current action result
    return result;
}

现在有了 ASP.NET Core(或 .NET 5),ControllerBuilder 不再存在,其中大部分都发生了变化。

我尝试注入 IControllerFactory 并使用它,但找不到使用它来调用已知“controllerName”和“actionName”的动作的正确方法。它还应该像以前一样,确定它是否是一个异步操作,并采取相应的行动。

自己找到答案。

A​​spCore 有一个隐藏的几乎没有记录的扩展方法,它在 DI 容器中注册控制器:AddControllersAsServices.

services.AddMvc().AddControllersAsServices();

然后你可以使用IServiceProvider来解析你的控制器。