Creating custom CodeAccessSecurityAttribute leads to exception on compile

2k views Asked by At

I'm building a custom CodeAccessSecurityAttribute to handle authorization for my WCF services. I built class A as such:

public class A : CodeAccessSecurityAttribute
{
    public A() : base(SecurityAction.Demand)
    {
        // Constructor Code
    }

    public override IPermission CreatePermission()
    {
        // Permission Creation Code
    }

}

And on compilation it produces this error.

Error emitting 'A' attribute -- 'Serialized security custom attribute is 
truncated or incorrectly formed.'

After playing with it a little I came up with the next sample that does compile without error:

public class B : CodeAccessSecurityAttribute
{
    public B(SecurityAction Action) : base(Action)
    {
        // Constructor Code
    }

    public override IPermission CreatePermission()
    {
        // Permission Creation Code
    }

}

I know it's because the SecurityAction enum isn't directly referenced to public side of Class A, but what I can't figure out is how to make it so that I can do it the Class A method instead of the Class B.

2

There are 2 answers

3
Mormegil On BEST ANSWER

I don’t know the exact reason for the requirement, but the MSDN documentation on CodeAccessSecurityAttribute clearly states

Notes to Inheritors

All permission attributes derived from this class must have only a single constructor that takes a SecurityAction as its only parameter.

Amended: The reason for this requirement is that CodeAccessSecurityAttribute is, from a low-level view, quite different from other custom attributes. Generally, custom attributes are stored in the compiled metadata in the CustomAttribute table. But the security attributes, deriving from SecurityAttribute, are stored separately in the DeclSecurity table. And this table does not contain the general data like the CustomAttribute table, this table contains the value of Action, the name of the attribute type, plus a set of the properties (named arguments) like in the custom attribute case. So, the compiler needs to convert a general custom attribute syntax to an entry in this metadata table, so it needs it to follow the fixed form noted above. (See also this blog post, or Partition II, section 22.11 DeclSecurity : 0x0E of the Common Language Infrastructure (CLI) standard.)

0
Terminator On

If you supply the constructor with a default value you don't have to specify it in the attribute.

public class B : CodeAccessSecurityAttribute 
{ 
    public B(SecurityAction Action = SecurityAction.Demand) : base(Action) 
    { 
        // Constructor Code 
    } 

    public override IPermission CreatePermission() 
    { 
        // Permission Creation Code 
    } 
}