No. You can't. Because the attribute name is already a magic string, and for all intents and purposes the name of the controller method is itself a magic string (in the case that you are using an implicit name for the action). Magic strings aren't bad, they're just commonly misused. In this case, you're probably better off just using a constant.
internal const string ContactActionName2 = nameof(ContactActionName2);
and
[ActionName(ContactActionName2)]
and
HomeController.ContactActionName2
should be sufficient for your use case.
However, since everyone is making a big stink about this I decided to go and find a solution which simply doesn't rely on strings (except for the one you cannot avoid relying on - the action name). I don't like this solution because 1) it's overkill, 2) it's still just accessing a string value, which can be done more simply using a constant, 3) you actually have to write out an entire method call as an expression, and 4) it allocates an expression every time you use it.
public static class ActionNameExtensions<TController>
{
public static string FindActionName<T>(Expression<Func<TController, T>> expression)
{
MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;
if (outermostExpression == null)
{
throw new ArgumentException("Not a " + nameof(MethodCallExpression));
}
return outermostExpression.Method.GetCustomAttribute<ActionNameAttribute>().Name;
}
}
Example usage:
public class HomeController : Controller
{
[ActionName("HelloWorld")]
public string MyCoolAction(string arg1, string arg2, int arg4)
{
return ActionNameExtensions<HomeController>.FindActionName(
controller => controller.MyCoolAction("a", "b", 3)
);
}
}
An overload can be written to accept methods without void
returns. Although that's sort of weird, because this is suppose to be used for controller methods, which usually return a value.