MVC strongly-typed action route helper

A sample for the following post can be downloaded from here

Go and use it! it’s simple!

routes.MapRoute<HomeController>(
                "Index",
                "",
                c => c.Index());

or maybe you have parameters on your action, and default values…

routes.MapRoute<HomeController>(
                "Echo",
                "Echo/{echo}",
                c => c.Echo("I am the default value of the echo parameter!"));

You want to use it now? It’s ok, here it is:

You can copy and paste the following classes:

ControllerAction.cs
namespace System.Web.Mvc
{
    using System;
    using System.Linq.Expressions;
    using System.Web.Mvc;
    using System.Web.Routing;

    ///<summary>
    /// Typed controller action that provides a <c ref="RouteValueDictionary">RouteValueDictionary</c> based on the parameters passed.
    /// </summary>
    /// <typeparam name="TController">The type of the controller.</typeparam>
    public class ControllerAction<TController>
        where TController : IController
    {
        /// <summary>
        /// Initializes a new instance of the ControllerAction class.
        /// </summary>
        /// <param name="action">The controller action.</param>
        public ControllerAction(Expression<Func<TController, ActionResult>> action)
        {
            this.DefaultValues = new RouteValueDictionary();
            this.DefaultValues.Add("controller", typeof(TController).Name.Remove(typeof(TController).Name.LastIndexOf("Controller")));

            var decorations = (action.Body as MethodCallExpression).Method.GetCustomAttributes(typeof(ActionNameAttribute), true);

            var methodCall = action.Body as MethodCallExpression;

            if (decorations != null && decorations.Length == 1)
            {
                this.DefaultValues.Add("action", (decorations[0] as ActionNameAttribute).Name);
            }
            else
            {
                this.DefaultValues.Add("action", methodCall.Method.Name);
            }

            var paremeters = methodCall.Method.GetParameters();

            for (int parameterIndex = 0; parameterIndex < paremeters.Length; parameterIndex++)
            {
                object value = null;
                var argumentExpression = methodCall.Arguments[parameterIndex];

                if (argumentExpression is ConstantExpression)
                {
                    value = (argumentExpression as ConstantExpression).Value;

                    this.DefaultValues.Add(
                        paremeters[parameterIndex].Name,
                        value);
                }
            }
        }

        /// <summary>
        /// Gets the default route values.
        /// </summary>
        /// <value>The default route values.</value>
        public RouteValueDictionary DefaultValues
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the controller name from the default values.
        /// </summary>
        /// <value>The controller name.</value>
        public string Controller
        {
            get
            {
                return this.DefaultValues["controller"] as string;
            }
        }

        /// <summary>
        /// Gets the controller action from the default values.
        /// </summary>
        /// <value>The controller action.</value>
        public string Action
        {
            get
            {
                return this.DefaultValues["action"] as string;
            }
        }
    }
}
RouteCollectionExtensions.cs
namespace System.Web.Mvc
{
    using System;
    using System.Linq.Expressions;
    using System.Web.Mvc;
    using System.Web.Routing;

    /// <summary>
    /// Route collection extension methods class.
    /// </summary>
    public static class RouteCollectionExtensions
    {
        /// <summary>
        /// Adds a typed route into a RouteCollection.
        /// </summary>
        /// <typeparam name="TController">The controller type.</typeparam>
        /// <param name="routes">The route collection to fill in.</param>
        /// <param name="routeName">Name of the route.</param>
        /// <param name="url">The URL for the route.</param>
        /// <param name="action">The controller action.</param>
        public static void MapRoute<TController>(
            this RouteCollection routes,
            string routeName,
            string url,
            Expression<Func<TController, ActionResult>> action)
            where TController : IController
        {
            if (routes == null)
            {
                throw new ArgumentNullException("routes");
            }

            var typedControllerAction = new ControllerAction<TController>(action);

            routes.Add(routeName, new Route(url, typedControllerAction.DefaultValues, new MvcRouteHandler()));
        }
    }
}

Thanks,

             Diego



Leave a Reply