2012-04-26 40 views

回答

1

您可以使用MVC contrlib。我做了類似的事情,而不需要contrlib

public static class UrlExtensions 
{ 
    public static string Action<TController>(this UrlHelper urlHelper, Expression<Action<TController>> expression) where TController : Controller 
    { 
     return BuildUrlFromExpression(urlHelper.RequestContext, urlHelper.RouteCollection, expression); 
    } 

    public static string ActionWithParameters<TController>(this UrlHelper urlHelper, Expression<Action<TController>> expression) where TController : Controller 
    { 
     return BuildUrlFromExpressionWithParameters(urlHelper.RequestContext, urlHelper.RouteCollection, expression); 
    } 

    public static RedirectToRouteResult Redirect<TController>(this TController controller, Expression<Action<TController>> expression) where TController : Controller 
    { 
     var valuesFromExpression = ExpressionHelper.GetRouteValuesFromExpressionWithParameters(expression); 

     return new RedirectToRouteResult(valuesFromExpression); 

    } 

    private static string BuildUrlFromExpression<TController>(RequestContext context, RouteCollection routeCollection, Expression<Action<TController>> action) where TController : Controller 
    { 
     var valuesFromExpression = ExpressionHelper.GetRouteValuesFromExpression(action); 
     var virtualPathForArea = RouteCollectionExtensions.GetVirtualPathForArea(routeCollection, context, valuesFromExpression); 
     if (virtualPathForArea != null) 
      return virtualPathForArea.VirtualPath; 
     return null; 
    } 

    private static string BuildUrlFromExpressionWithParameters<TController>(RequestContext context, RouteCollection routeCollection, Expression<Action<TController>> action) where TController : Controller 
    { 
     var valuesFromExpression = ExpressionHelper.GetRouteValuesFromExpressionWithParameters(action); 
     var virtualPathForArea = RouteCollectionExtensions.GetVirtualPathForArea(routeCollection, context, valuesFromExpression); 
     if (virtualPathForArea != null) 
      return virtualPathForArea.VirtualPath; 
     return null; 
    } 
} 

public static class ExpressionHelper 
{ 
    public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) where TController : Controller 
    { 
     MethodCallExpression call; 
     return GetRouteValuesFromExpression(action, out call); 
    } 

    public static RouteValueDictionary GetRouteValuesFromExpressionWithParameters<TController>(Expression<Action<TController>> action) where TController : Controller 
    { 
     MethodCallExpression call; 
     var rvd = GetRouteValuesFromExpression(action, out call); 
     AddParameterValuesFromExpressionToDictionary(rvd, call); 
     return rvd; 
    } 

    private static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action, out MethodCallExpression call) where TController : Controller 
    { 
     if (action == null) 
      throw new ArgumentNullException("action"); 
     call = action.Body as MethodCallExpression; 
     if (call == null) 
      throw new ArgumentException("MustBeMethodCall", "action"); 
     string name = typeof(TController).Name; 
     if (!name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)) 
      throw new ArgumentException("TargetMustEndInController", "action"); 
     string str = name.Substring(0, name.Length - "Controller".Length); 
     if (str.Length == 0) 
      throw new ArgumentException("CannotRouteToController", "action"); 
     string targetActionName = GetTargetActionName(call.Method); 
     var rvd = new RouteValueDictionary(); 
     rvd.Add("Controller", (object)str); 
     rvd.Add("Action", (object)targetActionName); 
     var linkAreaAttribute = typeof(TController).GetCustomAttributes(typeof(ActionLinkAreaAttribute), true).FirstOrDefault() as ActionLinkAreaAttribute; 
     if (linkAreaAttribute != null) 
     { 
      string area = linkAreaAttribute.Area; 
      rvd.Add("Area", (object)area); 
     } 
     return rvd; 
    } 

    public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression) 
    { 
     if (expression.Body.NodeType == ExpressionType.Call) 
      return GetInputName((MethodCallExpression)expression.Body).Substring(expression.Parameters[0].Name.Length + 1); 
     else 
      return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1); 
    } 

    public static PropertyInfo GetPropertyInfo<TModel, TValue>(Expression<Func<TModel, TValue>> expression) 
    { 
     var member = expression.Body as MemberExpression; 
     if (member == null) 
      return null; 
     var propInfo = member.Member as PropertyInfo; 

     return propInfo; 
    } 


    private static string GetInputName(MethodCallExpression expression) 
    { 
     var expression1 = expression.Object as MethodCallExpression; 
     if (expression1 != null) 
      return GetInputName(expression1); 
     else 
      return expression.Object.ToString(); 
    } 

    private static string GetTargetActionName(MethodInfo methodInfo) 
    { 
     if (methodInfo == null) throw new ArgumentNullException("methodInfo"); 
     var name = methodInfo.Name; 
     if (methodInfo.IsDefined(typeof (NonActionAttribute), true)) 
     { 
      throw new InvalidOperationException(string.Format(Helpers.MyFormat, "CannotCallNonAction {0}", name)); 
     } 

     var actionNameAttribute = methodInfo.GetCustomAttributes(typeof (ActionNameAttribute), true).OfType<ActionNameAttribute>().FirstOrDefault(); 
     if (actionNameAttribute != null) 
      return actionNameAttribute.Name; 
     if (methodInfo.DeclaringType.IsSubclassOf(typeof (AsyncController))) 
     { 
      if (name.EndsWith("Async", StringComparison.OrdinalIgnoreCase)) 
       return name.Substring(0, name.Length - "Async".Length); 
      if (name.EndsWith("Completed", StringComparison.OrdinalIgnoreCase)) 
       throw new InvalidOperationException(string.Format(Helpers.MyFormat, "CannotCallCompletedMethod: {0}", name)); 
     } 
     return name; 
    } 

    private static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary rvd, MethodCallExpression call) 
    { 
     var parameters = call.Method.GetParameters(); 
     if (parameters.Length <= 0) 
      return; 
     for (int index = 0; index < parameters.Length; ++index) 
     { 
      var expression = call.Arguments[index]; 
      var constantExpression = expression as ConstantExpression; 
      var obj = constantExpression == null ? CachedExpressionCompiler.Evaluate(expression) : constantExpression.Value; 
      rvd.Add(parameters[index].Name, obj); 
     } 
    } 
} 

從你的觀點,你現在可以做的,默認值將被傳遞的LINQ表達式的工作,但他們西港島線不會被渲染

@(Url.Action<MyController>(x => x.MethodName(null, 0, 0))) 
+0

謝謝您的幫助 :) – 2012-04-26 09:19:25

相關問題