Search code examples
c#.netattributescustom-attributes

How do C# derived Attributes work internally?When are the methods inside it called to act upon the class/method/property on which they are declared?


I was writing MVC code, where I used ValidationAttributes on the model , e.g - RequiredAttribute, RangeAttribute , etc. I just do not understand how these work internally. I have a CustomAttribute deriving from ValidationAttribute where IsValid was overridden and some custom check was made.When I put breakpoint on my CustomAttribute , it got called while updating the model , which makes sense. However I do not understand where the object gets passed to the Attribute. How and why is the Method called.

1.In Visual Studio I keep checking definitions of the Attributes, and there seems to be something missing. How is the object on which attribute is applied passed to the attribute class/object(is attribute object even instantiated?) 2.I went into my directory - C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7 and dragged System.ComponentModel.DataAnnotations.dll into justdecompile window. I do not see any implementations at all. IsValid has a blank body.

namespace System.ComponentModel.DataAnnotations
{
    //
    // Summary:
    //     Specifies that a data field value is required.
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
    public class RequiredAttribute : ValidationAttribute
    {
        //
        // Summary:
        //     Initializes a new instance of the System.ComponentModel.DataAnnotations.RequiredAttribute
        //     class.
        public RequiredAttribute();

        //
        // Summary:
        //     Gets or sets a value that indicates whether an empty string is allowed.
        //
        // Returns:
        //     true if an empty string is allowed; otherwise, false. The default value is false.
        public bool AllowEmptyStrings { get; set; }

        //
        // Summary:
        //     Checks that the value of the required data field is not empty.
        //
        // Parameters:
        //   value:
        //     The data field value to validate.
        //
        // Returns:
        //     true if validation is successful; otherwise, false.
        //
        // Exceptions:
        //   T:System.ComponentModel.DataAnnotations.ValidationException:
        //     The data field value was null.
        public override bool IsValid(object value);
    }
}

The above is from metadata when pressed F12 on Required attribute. Here IsValid has a value parameter. But there is no code which shows where its called or parameter is being passed.

What I would like to see as answer is a sample code snipped with maybe Required/Range/Conditional Attribute applied on a method/property(as applicable) and then step by step on when the Attribute actually does the work or if its not the attribute then where is the work done.


Solution

  • The call to the IsValid method is made automatically by the framework. It searches in the class you specified for all attributes derived from ValidationAttribute using reflection and calls their IsValid method.

    But this is a special case. If you make a custom attribute which is derived directly from Attribute you have to call it yourself.

    You can search for the exact workflow in the source code of ASP.NET if you like: https://github.com/aspnet/AspNetWebStack