Return to Snippet

Revision: 22879
at January 25, 2010 10:36 by jmcd


Updated Code
public static class AreaLinkBuilder
{
    public static string BuildUrlFromExpression<TController>(RequestContext context, RouteCollection routeCollection, Expression<Action<TController>> action) where TController : Controller
    {
        var memberInfo = ExpressionMemberFinder.FindMemberOrNull(action);
        var targetNamespace = memberInfo.DeclaringType.Namespace;

        var collection = new RouteCollection();
        routeCollection.Where(x =>
                                  {
                                      var route = x as Route;
                                      if (route != null)
                                      {
                                          var namespaces = route.DataTokens["Namespaces"] as string[];
                                          if (namespaces != null)
                                          {
                                              foreach (var @namespace in namespaces)
                                              {
                                                  if (@namespace == targetNamespace)
                                                  {
                                                      return true;
                                                  }
                                              }
                                          }
                                      }
                                      return false;
                                  }).ForEach(collection.Add);

        var routeValues = ExpressionHelper.GetRouteValuesFromExpression(action);
        var vpd = collection.GetVirtualPath(context, routeValues);
        return (vpd == null) ? null : vpd.VirtualPath;
    }
}


public class ExpressionMemberFinder
{
    public static MemberInfo FindMemberOrNull(Expression expression)
    {
        switch (expression.NodeType)
        {
            case ExpressionType.Coalesce:
                return FindMemberOrNull(((BinaryExpression)expression).Left) ?? FindMemberOrNull(((BinaryExpression)expression).Right);
            case ExpressionType.Convert:
                return FindMemberOrNull(((UnaryExpression)expression).Operand);
            case ExpressionType.Lambda:
                return FindMemberOrNull(((LambdaExpression)expression).Body);
            case ExpressionType.Call:
                return ((MethodCallExpression)expression).Method;
            case ExpressionType.MemberAccess:
                return ((MemberExpression)expression).Member;
            default:
                return null;
        }
    }
}


public static class ControllerExtensions
    {
        public static string ActionUrl<TController>(this Controller @this, Expression<Action<TController>> action) where TController : Controller
        {
            return AreaLinkBuilder.BuildUrlFromExpression(@this.ControllerContext.RequestContext, RouteTable.Routes, action);
        }
    }


public static class ViewExtensions
    {
        public static string ActionUrl<TController>(this SparkView @this, Expression<Action<TController>> action) where TController : Controller
        {
            return AreaLinkBuilder.BuildUrlFromExpression(@this.ViewContext.RequestContext, RouteTable.Routes, action);
        }
    }

Revision: 22878
at January 25, 2010 10:34 by jmcd


Updated Code
public static class AreaLinkBuilder
{
    public static string BuildUrlFromExpression<TController>(RequestContext context, RouteCollection routeCollection, Expression<Action<TController>> action) where TController : Controller
    {
        var memberInfo = ExpressionMemberFinder.FindMemberOrNull(action);
        var targetNamespace = memberInfo.DeclaringType.Namespace;

        var collection = new RouteCollection();
        routeCollection.Where(x =>
                                  {
                                      var route = x as Route;
                                      if (route != null)
                                      {
                                          var namespaces = route.DataTokens["Namespaces"] as string[];
                                          if (namespaces != null)
                                          {
                                              foreach (var @namespace in namespaces)
                                              {
                                                  if (@namespace == targetNamespace)
                                                  {
                                                      return true;
                                                  }
                                              }
                                          }
                                      }
                                      return false;
                                  }).ForEach(collection.Add);

        var routeValues = ExpressionHelper.GetRouteValuesFromExpression(action);
        var vpd = collection.GetVirtualPath(context, routeValues);
        return (vpd == null) ? null : vpd.VirtualPath;
    }
}


public static class ControllerExtensions
    {
        public static string ActionUrl<TController>(this Controller @this, Expression<Action<TController>> action) where TController : Controller
        {
            return AreaLinkBuilder.BuildUrlFromExpression(@this.ControllerContext.RequestContext, RouteTable.Routes, action);
        }
    }


public static class ViewExtensions
    {
        public static string ActionUrl<TController>(this SparkView @this, Expression<Action<TController>> action) where TController : Controller
        {
            return AreaLinkBuilder.BuildUrlFromExpression(@this.ViewContext.RequestContext, RouteTable.Routes, action);
        }
    }

Revision: 22877
at January 25, 2010 10:33 by jmcd


Initial Code
public static class AreaLinkBuilder
{
    public static string BuildUrlFromExpression<TController>(RequestContext context, RouteCollection routeCollection, Expression<Action<TController>> action) where TController : Controller
    {
        var memberInfo = ExpressionMemberFinder.FindMemberOrNull(action);
        var targetNamespace = memberInfo.DeclaringType.Namespace;

        var collection = new RouteCollection();
        routeCollection.Where(x =>
                                  {
                                      var route = x as Route;
                                      if (route != null)
                                      {
                                          var namespaces = route.DataTokens["Namespaces"] as string[];
                                          if (namespaces != null)
                                          {
                                              foreach (var @namespace in namespaces)
                                              {
                                                  if (@namespace == targetNamespace)
                                                  {
                                                      return true;
                                                  }
                                              }
                                          }
                                      }
                                      return false;
                                  }).ForEach(collection.Add);

        var routeValues = ExpressionHelper.GetRouteValuesFromExpression(action);
        var vpd = collection.GetVirtualPath(context, routeValues);
        return (vpd == null) ? null : vpd.VirtualPath;
    }
}

Initial URL


Initial Description
The LinkBuilder implementation provided with the MVC Futures assembly does not work with areas.  This re-implementation matches routes with areas via declared namespaces.

Initial Title
LinkBuilder For Areas in ASP.NET MVC2

Initial Tags


Initial Language
C#