【问题标题】:How to call a method in using attributes parameters使用属性参数如何调用方法
【发布时间】:2016-08-05 22:55:45
【问题描述】:

我有一个名为GetRole() 的静态方法,它返回一个字符串值。
现在我想使用属性参数来调用它。
例如:

[Authorize(Roles = GetRole())]
public ActionResult Get()
{
}

public static string GetRole()
{
   return "Admin";
}

但编译器出现以下错误:

属性参数必须是属性参数类型的常量表达式、typeof表达式或数组创建表达式

请帮我调用属性中的方法。

【问题讨论】:

  • 你不能。只接受可以在编译时解析的参数值。
  • 属性不存储为代码,它们存储为元数据 - 这就是为什么您只能在其中使用有限范围的构造。

标签: c# asp.net methods attributes


【解决方案1】:

编译器错误很明显,声明属性时不能调用任何方法(因为它的值必须在编译时知道)但是你可以派生你自己的自定义属性,派生自AuthorizeAttribute 执行您需要的所有逻辑。在期待已久的本地化感知数据注释之前,我们所做的不就是对NameAttribute 和朋友进行本地化吗?

概念证明:

class DynamicAuthorizeAttribute : AuthorizeAttribute {
    protected bool AuthorizeCore(HttpContextBase context) {
        // Perform your logic here, eventually update Roles property
    }
}

然后:

[DynamicAuthorize]
public ActionResult Get() {
    // ...
}

这只是一种可能的方式,您可以在其中放置自己的逻辑或简单地更新Roles 属性并委托给通常的逻辑,只需调用base.AuthorizeCore(context)。请注意,这里的所有代码都必须是线程安全的。

如果您正在使用静态方法并且希望将该逻辑保留在控制器中,那么您可以尝试接受(例如)这样的内容:

[DynamicAuthorize(typeof(MyView), nameof(GetRole))]

请注意,您可以从 context.HttpContext.Request.RequestContext.RouteData 访问控制器和视图名称。

然后调用这样的静态方法。请注意,如果逻辑非常复杂并且变化很大,那么您可能希望集中该逻辑并使用其他 MVC 工具 来执行此操作。

【讨论】:

    【解决方案2】:

    属性参数必须是属性参数类型的常量表达式、typeof表达式或数组创建表达式。

    这是一个事实。没有办法,属性参数必须是编译时间常数。你不能调用方法。

    可以做的是定义一个常量:

    public class MyClass
    {
        public const string Role = "Admin";
        [Authorize(Roles = Role)]
        public ActionResult Get()
        {
        }    
    }
    

    常量是(顾名思义)编译时间常量,所以你也许这个解决方法可以帮助你。

    如果您想在运行时确定一个值,这将不起作用,因为属性是在编译时分配的。

    【讨论】:

    • 投反对票是为了什么?可能是因为我不知道Authorize 属性。但是这个问题从未说明它是关于具有特定实现的特定属性。甚至不知道在哪里调用 AuthorizeCore(如 Adriano Repetti 所述)。
    【解决方案3】:

    我使用自己的方法来授权登录用户。

    看看吧,也许对你有帮助。

     public static bool GetRole(string Codename)
        {            
            if (LogInUser == null)
            {
                return false;
            }
    
            return true;
        } 
    

    并检查用户是否有访问权限,

    if (!Utility.GetRole("Admin"))
                return View("AccessDenied");
    

    我也有标准内置授权代码,

    如果需要,请在下方评论。

    【讨论】:

      【解决方案4】:

      你可以这样做,

      这种方法更好,因为在这里你可以传递要授权的角色列表,而不是单个角色。(看下面,我通过了 admin 和 master)

      [Authorization(Roles = "admin,master")]
      public class MyController : Controller
      {
         //Your remaining code.
      }
      

      要授权,我有这些方法。

      public class Authorization : AuthorizeAttribute
      {
      
      public string Roles { get; set; }
      
      protected override bool AuthorizeCore(HttpContextBase httpContext)
      {
          if (User != null)
          {
              if (String.IsNullOrEmpty(Roles))
              {
                  return true;
              }
      
              string[] split = Roles.Split(',');
      
              foreach (UserRole item in User)
              {
                  if (split.Contains(item.Role.CodeName))
                  {
                      return true;
                  }
              }
              return false;
      
          }
          else
              return false;
      }
      
      protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
      {
          filterContext.Result = new HttpUnauthorizedResult();
      }
      }
      

      【讨论】:

      • 嗯,我的反对意见,因为它没有对现有答案添加任何内容,也对现有 AuthorizeAttribute(已经处理多个角色...)没有任何添加,同时仍然没有回答问题(调用方法...)。至少您的其他答案采用了另一种方法(命令式而不是声明式授权)
      • 是的@AdrianoRepetti,也许那是因为我们都在某个时间给出答案..我不知道你给出了相同概念的答案..
      猜你喜欢
      • 2013-06-13
      • 2012-01-27
      • 2012-10-24
      • 2023-04-03
      • 1970-01-01
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多