using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web.Routing;
public class UsersController : Controller
public ActionResult Index()
var model = new UsersModel
public ActionResult Match(String name, Int32 age)
throw new NotImplementedException();
internal static class Utils
internal const String ControllerNameSuffix = "Controller";
internal static String GetActionNameFromMethod(MethodInfo method)
var attribute = method.GetCustomAttribute<ActionNameAttribute>(inherit: false);
if ((attribute != null) && !String.IsNullOrEmpty(attribute.Name))
internal static String GetControllerNameFromType(Type type)
if ((type.Name.Length > ControllerNameSuffix.Length) && type.Name.EndsWith(ControllerNameSuffix))
return type.Name.Substring(0, (type.Name.Length - ControllerNameSuffix.Length));
internal static Dictionary<String, Object> GetMethodParameters(MethodCallExpression expression)
var dictionary = new Dictionary<String, Object>();
ParameterInfo[] parameters = expression.Method.GetParameters();
for (Int32 index = 0; (index < parameters.Length); index++)
Expression argument = expression.Arguments[index];
String name = parameters[index].Name;
Object value = Expression.Lambda(Expression.Convert(argument, argument.Type)).Compile().DynamicInvoke();
dictionary.Add(name, value);
internal sealed class ActionInfo
private String actionName;
private String controllerName;
private RouteValueDictionary routeValues;
public String ControllerName
return this.controllerName;
public RouteValueDictionary RouteValues
internal static ActionInfo Create<TController>(Expression<Func<TController, ActionResult>> expression) where TController : Controller
throw new ArgumentNullException("expression");
var body = (MethodCallExpression)expression.Body;
var routeValues = new RouteValueDictionary(Utils.GetMethodParameters(body));
String actionName = Utils.GetActionNameFromMethod(body.Method);
String controllerName = Utils.GetControllerNameFromType(typeof(TController));
controllerName = controllerName,
routeValues = routeValues
public static class MvcExtensions
public static String Action<TController>(this UrlHelper urlHelper, Expression<Func<TController, ActionResult>> expression) where TController : Controller
throw new ArgumentNullException("urlHelper");
else if (expression == null)
throw new ArgumentNullException("expression");
var info = ActionInfo.Create(expression);
if (info.RouteValues.Count == 0)
return urlHelper.Action(info.ActionName, info.ControllerName);
return urlHelper.Action(info.ActionName, info.ControllerName, info.RouteValues);