通过反射调用WebApi在另一个控制器中的另一个动作?

时间:2014-12-30 09:43:30

标签: c# reflection asp.net-web-api

我们的系统中有很多服务。 (与移动公司合并)

所以,(例如)我们有:

Action1 in Controller1
Action2 in Controller1
...

Action4 in Controller4
Action5 in Controller4
...

目前,移动公司通过单一请求调用每个操作。

但最近他们告诉我们,“我们可以向您发送要调用的动作列表吗?而不是每次手动运行单个动作......?

所以我尝试了反思:

ServicesController

    [HttpGet]
    [AllowAnonymous]
    public HttpResponseMessage AAA( )
    {
        Type type = typeof(UsersController);

        var instance = Activator.CreateInstance(type);

        MethodInfo method = type.GetMethod("Test2", BindingFlags.Instance | BindingFlags.Public);
        var t=  method.Invoke(instance, new object[] { "royi" });

        return Request.CreateResponse(HttpStatusCode.OK, t);
    }

并且:

UseresController :

 [HttpGet]
 [AllowAnonymous]
 public HttpResponseMessage Test2( string ggg)
 { 
     return Request.CreateResponse(HttpStatusCode.OK, "hello"+ggg);
 }

当我通过fiddler跑道时:

http://es.com/api/services/aaa(GET)

它确实有效,但(显然)另一边的Request为空:

enter image description here

问题

如何让Test2按预期运行?我正朝着正确的方向解决这个问题吗?或者webApi是否为此类内容构建了机制?

1 个答案:

答案 0 :(得分:6)

您最好使用ActionInvoker来执行此操作:

public HttpResponseMessage AAA()
{
    var ctrlDesc = new HttpControllerDescriptor(this.Configuration, "UsersController", typeof(UsersController));
    var actionDesc = new ReflectedHttpActionDescriptor(ctrlDesc, typeof(UsersController).GetMethod("Test2"));
    var ctrlCtx = new HttpControllerContext(this.Configuration, this.Request.GetRouteData(), this.Request);

    var apiCtrl = ctrlDesc.CreateController(this.Request) as ApiController;

    apiCtrl.Request = this.Request;
    apiCtrl.Configuration = this.Configuration;
    apiCtrl.ControllerContext = ctrlCtx;

    ctrlCtx.Controller = apiCtrl;
    ctrlCtx.ControllerDescriptor = ctrlDesc;
    ctrlCtx.Request = this.Request;
    ctrlCtx.RouteData = this.Request.GetRouteData();

    var actionContext = new HttpActionContext(ctrlCtx, actionDesc);
    actionContext.ActionArguments.Add("ggg", "royi");

    var invoker = this.Configuration.Services.GetActionInvoker();

    return invoker.InvokeActionAsync(actionContext, CancellationToken.None).Result;
}