Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a method in using attributes parameters

I have a static method by name GetRole() that return a string value.
Now I want to call that in using attribute parameters.
for example:

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

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

But compiler get below error:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

Please help me to call a method in attributes.

like image 293
Ahmad Aghazadeh Avatar asked Apr 14 '16 11:04

Ahmad Aghazadeh


People also ask

What is parameter attribute in C#?

The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are: One of the following types: bool , byte , char , double , float , int , long , sbyte , short , string , uint , ulong , ushort . The type object . The type System.

What is attribute parameter?

Attribute vs Parameter An attribute is a variable of any type that is declared directly in a class. A parameter is a variable defined by the function that receives a value when it is called. Usage. An attribute is used with classes and objects. A parameter is used with a function or a method.


2 Answers

Compiler error is pretty clear, you can't call any method when declaring an attribute (because its value must be known at compile-time) but you can derive your own custom attribute, derived from AuthorizeAttribute to perform all logic you need. Isn't what we all did to localize NameAttribute & friends before fancy long-waited localization-aware data annotations?

Proof of concept:

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

And then:

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

This is just one possible way, there you can put your own logic or simply update Roles property and delegate to usual logic simply calling base.AuthorizeCore(context). Be aware that all your code here must be thread-safe.

If you're working with static methods and you want to keep that logic inside your controller then you can play around to accept (for example) something like this:

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

Note that you can access controller and view names from context.HttpContext.Request.RequestContext.RouteData.

Then invoke such static method. Note that if logic is really complex and greatly vary then you may want to centralize this logic and use other MVC tools to do this.

like image 193
Adriano Repetti Avatar answered Oct 21 '22 04:10

Adriano Repetti


An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

This is a fact. There is no way around, an attribute argument must be compile time constant. You cannot call a method.

What you can do is define a constant:

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

Constants are (as the name suggests) compile time constant, so you maybe this workaround helps you.

If you want to determine a value at run-time, this won't work as the attributes are assigned at compile time.

like image 45
René Vogt Avatar answered Oct 21 '22 06:10

René Vogt