Attributes are dumb
Attributes don't do anything by themselves, except hold data. The only reason attributes like FilterAttribute
do anything is because the MVC framework looks for them and invokes them before or after calling the method they are applied to.
How MVC invokes them
Here is what it looks like in the MVC reference code base:
protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
Func<ActionExecutedContext> continuation = () =>
new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
// need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
return thunk();
}
Sort of hard to follow without context, and the loop is hard to spot (they use a bit of LINQ and the Aggregate method to invoke each filter in the collection) but suffice it to say that MVC will look at the method, look for attributes of a certain kind, and invoke them before and after the actual action method invocation. So it's not automatic.
How you can do it
You could do something similar, if you're willing to write code to invoke the attribute. Here's an example how to do it.
First, we define out custom attribute. This custom attribute will output a message to the console when its OnBeforeExecute
method is invoked.
public class HelloWorldAttribute : System.Attribute
{
private string _someString;
public HelloWorldAttribute(string text)
{
_someString = text;
}
public void OnBeforeExecute()
{
Console.WriteLine("OnBeforeExecute says '{0}'.", _someString);
}
}
Now we write a class that applies the attribute to one of its methods:
public class MyClass
{
[HelloWorld("This is a test!!")]
public void MyClassMethod(string text)
{
Console.WriteLine("MyClassMethod says '{0}'", text);
}
}
Now by itself, the attribute does nothing at run-time:
public class Program
{
public static void Main()
{
//By itself, the attribute does nothing
var c = new MyClass();
c.MyClassMethod("Main call");
}
}
Output:
MyClassMethod says 'Main call'
But if we write code to look for the attribute and invoke it, we can get the message to appear. This is a very simple example:
public class Program
{
public static void Main()
{
var c = new MyClass();
typeof(MyClass)
.GetMethod(nameof(c.MyClassMethod))
.GetCustomAttributes(true)
.OfType<HelloWorldAttribute>()
.First()
.OnBeforeExecute();
c.MyClassMethod("Main call");
}
}
Output:
OnBeforeExecute says 'This is a test!!'.
MyClassMethod says 'Main call'
Full example on Fiddle.