时有可能得到从动作的URL而不知道ViewContext(例如,在一个控制器)?是这样的:

LinkBuilder.BuildUrlFromExpression(ViewContext context, Expression<Action<T>> action)

...但使用Controller.RouteData代替ViewContext。我似乎对这种金属块。

有帮助吗?

解决方案

下面是如何做到这一点在一个单元测试:

    private string RouteValueDictionaryToUrl(RouteValueDictionary rvd)
    {
        var context = MvcMockHelpers.FakeHttpContext("~/");
        // _routes is a RouteCollection
        var vpd = _routes.GetVirtualPath(
            new RequestContext(context, _
                routes.GetRouteData(context)), rvd);
        return vpd.VirtualPath;
    }

每评论,我会适应控制器:

string path = RouteTable.Routes.GetVirtualPath(
    new RequestContext(HttpContext, 
        RouteTable.Routes.GetRouteData(HttpContext)),
    new RouteValueDictionary( 
        new { controller = "Foo",
              action = "Bar" })).VirtualPath;

用真实姓名替换“富”与“酒吧”。这是把我的头顶部,所以我不能保证这是最有效的解决方案成为可能,但它应该让你在正确的轨道上。

其他提示

克雷格,感谢您的正确答案。它的伟大工程,而且还去我的思维。所以在我的驱动器,以消除那些重构性能稳定的“魔术字符串”我已经制定了解决方案的变化:

public static string GetUrlFor<T>(this HttpContextBase c, Expression<Func<T, object>> action)
    where T : Controller
{
    return RouteTable.Routes.GetVirtualPath(
        new RequestContext(c, RouteTable.Routes.GetRouteData(c)), 
        GetRouteValuesFor(action)).VirtualPath;
}

public static RouteValueDictionary GetRouteValuesFor<T>(Expression<Func<T, object>> action) 
    where T : Controller
{
    var methodCallExpresion = ((MethodCallExpression) action.Body);
    var controllerTypeName = methodCallExpresion.Object.Type.Name;
    var routeValues = new RouteValueDictionary(new
    {
        controller = controllerTypeName.Remove(controllerTypeName.LastIndexOf("Controller")), 
        action = methodCallExpresion.Method.Name
    });
    var methodParameters = methodCallExpresion.Method.GetParameters();
    for (var i = 0; i < methodParameters.Length; i++)
    {
        var value = Expression.Lambda(methodCallExpresion.Arguments[i]).Compile().DynamicInvoke();
        var name = methodParameters[i].Name;
        routeValues.Add(name, value);
    }
    return routeValues;
}

我知道有些人会说......可怕的体现!在我的具体应用,我觉得可维护性远远超过性能值得关注的问题的好处。我欢迎这个想法和代码的任何反馈。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top