在MVC Razor View中通过Route Name获取RouteTemplate

时间:2015-03-03 22:46:50

标签: asp.net-mvc razor asp.net-mvc-5 asp.net-mvc-routing

我想生成一个路由对象,我的JavaScript在进行AJAX调用时可以引用这些路径。

我在MVC 5.2.2中使用AttributeRouting。

例如,我有一个控制器,其属性如下:

[RoutePrefix("api/v1/my-controller")]
public class MyController : ApiController {
    [Route(Name = "MyController.GetSomeString")]
    [HttpGet]
    public string GetSomeString()
    {
        return "Hello World!";
    }
}

然后在我的Razor视图中,我有以下内容:

var routes = {
    'MyController.GetSomeString': '@(Url.HttpRouteUrl("MyController.GetSomeString", new {})'
};

这会产生以下结果:

var routes = {
    'MyController.GetSomeString': '/api/v1/my-controller'
};

没关系,但是现在我想要一个采用参数的动作的路线,但是还没有路线数据的值。例如,请考虑来自同一控制器的以下控制器操作:

[Route("{id}/special", Name = "MyController.GetSpecialString")]
[HttpGet]
public string GetSpecialString(string id)
{
    return String.Format("Special string with id {0}.", id);
}

我想用令牌生成这个字符串。我称之为RouteTemplate。我发现无法检索此值:

/api/v1/my-controller/{id}/special

如果我用空路由值调用HttpRouteUrl,那么我将得到一个空字符串,而不是RouteTemplate。

我不想为{id}提供值。这很简单。相反,我想要输出字符串中的{id}标记。

这可能吗?如果是这样,我该怎么做呢?

1 个答案:

答案 0 :(得分:2)

您应该可以通过以下方式在控制器中进行选择:

var url = ((System.Web.Routing.Route)this.ControllerContext.RouteData.Route).Url;

立即窗口

  ?

URL;   " {控制器} / {行动} / {ID}"

然后,如果您将其填入ViewBag或您的模型等,您可以在视图中选择它。

修改

如果您想访问所有路线,那么它就是:

var routeUrls = new List<string>();
foreach (var r in RouteTable.Routes)
{
   routeUrls.Add(((Route)r).Url);
}

如果你想按路线名称进行过滤,那么你&#34; cant&#34;根据Phil Haacks的帖子关于这个Getting the route name for a route

  

由于名称,无法获取路线的路线名称   不属于路线的财产。添加路由到   RouteCollection,该名称用作内部唯一索引   路由,以便查找路由非常快。这个指数是   永远不会暴露。

菲尔·哈克,菲尔·哈克,然后继续展示如何做到这一点,但需要注意的是,如果你将相同的路线添加到多个集合中,会失败。

您可以创建一些扩展方法,以便您轻松地将路由名称添加到路径数据标记属性中:

public static Route Map(this RouteCollection routes, string name, 
    string url) {
  return routes.Map(name, url, null, null, null);
}

public static Route Map(this RouteCollection routes, string name, 
    string url, object defaults) {
  return routes.Map(name, url, defaults, null, null);
}

public static Route Map(this RouteCollection routes, string name, 
    string url, object defaults, object constraints) {
  return routes.Map(name, url, defaults, constraints, null);
}

public static Route Map(this RouteCollection routes, string name, 
    string url, object defaults, object constraints, string[] namespaces) {
  return routes.MapRoute(name, url, defaults, constraints, namespaces)
    .SetRouteName(name);
}

public static string GetRouteName(this Route route) {
    if (route == null) {
        return null;
    }
    return route.DataTokens.GetRouteName();
}

public static string GetRouteName(this RouteData routeData) {
    if (routeData == null) {
        return null;
    }
    return routeData.DataTokens.GetRouteName();
}

public static string GetRouteName(this RouteValueDictionary routeValues) {
    if (routeValues == null) {
        return null;
    }
    object routeName = null;
    routeValues.TryGetValue("__RouteName", out routeName);
    return routeName as string;
}
public static Route SetRouteName(this Route route, string routeName) {
    if (route == null) {
        throw new ArgumentNullException("route");
    }
    if (route.DataTokens == null) {
        route.DataTokens = new RouteValueDictionary();
    }
    route.DataTokens["__RouteName"] = routeName;
    return route;
}

然后你只需从路线中提取路线名称:

var route = routes.Map("rName", "url");
route.GetRouteName();

然后你可以做类似的事情:

Route ajaxRoute = routes.FirstOrDefault(r => ((Route) r).GetRouteName() == "myName"));