MVC strongly-typed action route helper
May 9th, 2009
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
You must be logged in to post a comment.