为什么在ApiController中获取ActionName这么复杂?更方便吗?

时间:2018-03-01 21:05:33

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

MVC控制器获取操作名称和控制器名称:

public class AuthorizeController : Controller
{

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string actionName = filterContext.ActionDescriptor.ActionName;
        string controllerNamespace = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
        //..more code
        base.OnActionExecuting(filterContext);
    }
}

非常直接。

但是当我有一个ApiController(System.Web.Http.ApiController)时,情况会更复杂:

enter image description here

最终在一些rsharper提示的帮助下,我能够将它减少到少数几个'线。

private string GetActionName(HttpControllerContext context)
{
    var httpRouteDataCollection = context.RouteData.Values.Values;
    var httpRouteDataCollection2 = httpRouteDataCollection.FirstOrDefault();
    if (!(httpRouteDataCollection2 is IHttpRouteData[] httpRouteData))
    {
        return null;
    }

    IHttpRouteData routeData = httpRouteData.FirstOrDefault();
    var httpActionDescriptorCollection = routeData?.Route.DataTokens["actions"];
    if (!(httpActionDescriptorCollection is HttpActionDescriptor[] httpActionDescriptor))
    {
        return null;
    }
    HttpActionDescriptor reflectedHttpActionDescriptor = httpActionDescriptor.FirstOrDefault();
    return reflectedHttpActionDescriptor?.ActionName;
}

不能轻松完成吗? 问这个的原因是因为目前我正在实施一种确定谁可以开启什么行动的通用方法。有些操作属于WebApi,每次我都需要执行上面的查询操作。因此,整个转换过程会耗费一些性能时间。

为什么?

如果不详细介绍,请假设您有40个MVC控制器和20个API控制器,每个控制器大约有5-10个动作。所有这些都存储在数据库中(在启动时循环遍历它们),并且可以链接到Identity角色。管理员可以选择某个角色可以执行的操作。在收到第一个答案后,我可能不太清楚为什么我想创建一个控制器覆盖,我只想编程一次。

2 个答案:

答案 0 :(得分:3)

其中一个潜在的解决方案可能是ActionFilterAttribute:

help(Startup)

然后在您的控制器上:

public class ValidateAccessAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var actionName = actionContext.ActionDescriptor.ActionName;
        ......
        base.OnActionExecuting(actionContext);
    }
}

您甚至可以将参数传递给这些属性,并将它们与#34; smart"相比,每个操作都属于某个组,访问验证将基于组而非操作名称。这可能很难维持。

例如

    [ValidateAccess]
    public async Task<IHttpActionResult> Stuff()

答案 1 :(得分:2)

为什么不使用ActionContext和ControllerContext?

public class ValuesController : ApiController
{
    [HttpGet]
    [AllowAnonymous]
    public IHttpActionResult Get()
    {
        var actionName = this.ActionContext.ActionDescriptor.ActionName;
        var controlerName = this.ControllerContext.ControllerDescriptor.ControllerName;
        return this.Ok();
    }
}