3

For authorization in an Entity Framework application, I've written this class which check's whether the current user is in the specified role.

public class AuthorizeDesignatedRoles : AuthorizeAttribute {

        public const string DELETE = System.Configuration.ConfigurationManager.AppSettings["GroupAuthorizedForDeleteAction"].ToString();
        public string DesignatedRoles { get; set; }

        protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) {
            bool isAuthorizedBase = base.IsAuthorized(actionContext);
            if (!isAuthorizedBase)
                return false;


            string[] roles = DesignatedRoles.Split(';');  // Multiple roles can be seperated by a semicolon ;
            foreach (string role in roles) {
                if (System.Web.Security.Roles.IsUserInRole(role))
                    return true;
            }
            return false;
        }

    }

Now I can allow controller actions only to be carried out by users who are in a designated role.

[AuthorizeDesignatedRoles(DesignatedRoles = AuthorizeDesignatedRoles.DELETE)]
public HttpResponseMessage DeleteThisAndThat(long id) { ... }

The problem is that I do not want to put the name of the designated DELETE group in the code but in the web.config file. By doing so, Visual Studio complains that it is not a constant string any more.

How can I make it a constant string again?

Edit: When I leave out the const keyword and make DELETE static readonly instead, the compiler says An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

Explicat
  • 1,075
  • 5
  • 16
  • 40
  • 1
    A `const` is a compile-time constant. So you cannot use `const` if it's coming from a file. But what's the problem? [Config files are cached from .NET](http://stackoverflow.com/a/9569262/284240) automatically. – Tim Schmelter Mar 10 '14 at 08:27
  • What are you trying to achieve here? What does `AppSettings["GroupAuthorizedForDeleteAction"]` contain? The reason for your error regarding `static readonly` field is because you can only use constants for attribute arguments and a `readonly` field is not constant. – Henk Mollema Mar 10 '14 at 08:48
  • Only people who are in a special windows role should be allowed to carry out some controller actions. And I want to have the name of this special role not in the code. Instead I'd put it in the web.config file with the key "GroupAuthorizedForDeleteAction". – Explicat Mar 10 '14 at 08:54
  • Ah, I understand. I proposed a possible solution below. – Henk Mollema Mar 10 '14 at 10:02

2 Answers2

2

What about storing the AppSettings key in the constant and fetch its value in the IsAuthorized method:

public class AuthorizeDesignatedRoles : AuthorizeAttribute
{
    public const string DELETE = "GroupAuthorizedForDeleteAction";

    public string DesignatedRoles { get; set; }

    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) {
    {
        // ...

        string[] roles = DesignatedRoles.Split(';')
                                        .Select(s => ConfigurationManager.AppSettings[s].ToString())
                                        .ToArray();

        foreach (string role in roles)
        {
            // ...
        }
    }
}
Henk Mollema
  • 44,194
  • 12
  • 93
  • 104
  • Nice idea! Thank you! One thing with the types: You need to cast the roles explicitly to an array, like DesignatedRoles.Split(";").Select(..).ToArray() or use IEnumerable roles. – Explicat Mar 10 '14 at 10:34
1

TL;DR: Use readonly rather than const.

Constants need to be set at compile time, and not change in compatible updates. The compiler can and does copy the values of constants from referenced assemblies into their output assembly.

Read-only values can be set in code before references to the type (static readonly) or in the constructor (member readonly) but no further changes is then enforced.

Richard
  • 106,783
  • 21
  • 203
  • 265
  • 1
    I replaced const with static readonly, but this is giving me another error. See the edit in the original post. – Explicat Mar 10 '14 at 08:34
  • 2
    OP is trying to use the constant as an attribute argument. You can't use `readonly` fields for that, so this won't work. – Henk Mollema Mar 10 '14 at 08:50