c# - 为什么在ApiController中获取ActionName这么复杂?更简单的方法?

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

获取 Action 名称和 Controller 名称的 MVC Controller :

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;
}

难道就不能简单点吗? 问这个问题的原因是因为目前我正在实现一种确定谁可以打开什么 Action 的通用方法。有些操作在 WebApi 中,每次我都需要执行上述“查询”。所以整个转换过程会占用一些性能时间。

为什么?

在不深入细节的情况下,假设您有 40 个 MVC Controller 和 20 个 API Controller ,每个 Controller 大约有 5-10 个操作。所有这些都存储在数据库中(在启动时循环遍历它们)并且可以链接到身份角色。管理员能够选择特定角色可以执行的操作。在收到第一个答案后,我可能不太清楚为什么我想创建一个 Controller 覆盖,我只想在其中进行一次编程。

最佳答案

潜在的解决方案之一可能是 ActionFilterAttribute:

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

然后在你的 Controller 上:

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

您甚至可以将参数传递给这些属性并让它们“智能化”,例如每个 Action 都属于某个组,并且访问验证将基于组而不是 Action 名称。这可能很难维护。

例如

public class ValidateAccessAttribute2 : ActionFilterAttribute
{
    private readonly FunctionalArea _area;

    public ValidateAccessAttribute2(FunctionalArea area)
    {
        _area = area;
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);
        if (!actionContext.Request.Headers.Contains(AuthorizationHeaders.UserNameHeader))
        {
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            return;
        }
        var userName = actionContext.Request.Headers.GetValues("UserNameHeader").First();
        if (!UserCanAccessArea(userName, _area))
        {
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            return;
        }
    }
}


    [ValidateAccess2(FunctionalArea.AccessToGenericStuff)]
    public async Task<IHttpActionResult> Stuff()

关于c# - 为什么在ApiController中获取ActionName这么复杂?更简单的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49058676/

相关文章:

c# - 我们怎样才能得到照片的评论

multithreading - 用线程编程,有什么好处?

sql-server - Memcached 与 SQL Server 缓存

.net - 使用.net API将音频实时流传输到android客户端的最佳方法是什么

c# - 在 Xamarin.Forms 中创建默认短信应用程序

c# - 为什么 WPF 数据绑定(bind)会吞下异常?

javascript - javascript 中的脚本性能

asp.net-web-api - NewtonJson.NET 版本 4.0.8.0 的 RavenDb 客户端问题

c# - 为什么我会在这个 Web API 请求上收到 HTTP 404?

VS 代码中的 C# 控制台应用程序未在 Application Insight 中编写