【问题标题】:MVC - Given a route name, can I get the default action name and controller name?MVC - 给定路由名称,我可以获得默认操作名称和控制器名称吗?
【发布时间】:2017-04-02 09:00:26
【问题描述】:

给定一个路由名称,我可以得到默认的动作名称和控制器名称吗?

routes.MapRoute(
      name: "MonthlyCalendar",
      url: "FMB/Calendar/{jamaatName}/{year}/{month}",
      defaults: new { controller = "FMB", action = "MonthlyCalendar", 
         jamaatName = UrlParameter.Optional,year = UrlParameter.Optional,
         month=UrlParameter.Optional}
);

【问题讨论】:

  • 我已从您的问题中删除了重复的句子,这将其简化为一个并不能真正显示您尝试过的内容。你能用那个更新你的问题吗?它似乎也与Get "Default" Route Url in Controller 重复。
  • 在运行时?从哪里/什么背景?
  • 我在一个控制器动作中..我有一个路由名称..
  • 我已经用我的路线更新了问题

标签: c# asp.net asp.net-mvc asp.net-mvc-routing


【解决方案1】:

不,当然,您不能仅从路由名称中获取控制器和操作名称。路由映射可能如下所示:{controller}/{action}/{id}。如果你只有一个路线名称,那是你唯一能得到的东西。

另一方面,如果您有一个完整的 URL,例如 http://example.com/Home/Index,那么这是一个完全不同的故事。现在您可以从 RouteData 中获取 controller=Home 和 action=Index。


更新:

您似乎正试图从给定路由名称的路由配置中提取控制器和操作的默认值。这可以通过在 DataTokens 属性中注册时存储路由名称来轻松完成:

RouteTable.Routes.MapRoute(
    "foo",
    "{controller}/{action}", 
    new { controller = "Home", action = "Index" }
).DataTokens["__RouteName"] = "foo";

然后:

var route = RouteTable.Routes.OfType<Route>().FirstOrDefault(x => 
    x.DataTokens.ContainsKey("__RouteName") && 
    (string)x.DataTokens["__RouteName"] == "foo"
);
if (route != null)
{
    var defaultController = route.Defaults["controller"];
    var defaultAction = route.Defaults["action"];
}

之所以需要在 DataTokens 中存储路由名称是因为 Route 实例中没有信息。


更新:

在某些时候,MS 向RouteCollection 添加了一个索引器以按名称查找,因此不再需要上述内容:

 ((System.Web.Routing.Route)Url.RouteCollection["MyRouteName"]).Defaults

您可能应该先检查以确保它存在以避免空异常。

【讨论】:

  • 为什么不呢?路由中定义了一些默认值。为什么我不能访问它?
  • 我的路由映射中没有默认定义的控制器名称和操作名称
  • 那么您想访问路由配置的默认值吗?这就是您应该在问题中写的内容,因为这非常令人困惑。我会更新我的答案。
  • @DarinDimitrov,这 __RouteName 是 Microsoft 的一些特定于 MVC 的固有值或保留值,例如 Namespace 或 UseFallbackNamespace,还是您编造的?我问这个是因为在 MS 平台上,他们通常将这种双下划线约定用于内部使用。
  • @HuseinRoncevic,不,绝对不是。是我把它放在那里,以便我以后可以按名称检索路线。看看我的路线定义。我需要把它放在那里,因为微软的人没有这样做,这是一种耻辱——根据他们对事物的理解,一条路线可以在没有名字的情况下完美地生活。如果你给它一个名字,它就不是路由的一部分,而是存储在一些内部哈希表中。
【解决方案2】:

我创建了这个扩展方法,它将“活动”css 类添加到路由链接。如果 RouteValueDictionary 中没有提供动作和控制器,则此方法根据路由名称从路由中获取默认动作和控制器。

您可以从RouteTable 中的路由获取默认操作,但是您需要将返回值转换为Route 而不是RouteBase

示例:

var action = (RouteTable.Routes["Default"] as Route).Defaults["action"] as string;

完全扩展方法:

public static MvcHtmlString MenuRouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, RouteValueDictionary routeValues,
    IDictionary<string, object> htmlAttributes)
{
    string currentAction = htmlHelper.ViewContext.RouteData.GetRequiredString("action");
    string currentController = htmlHelper.ViewContext.RouteData.GetRequiredString("controller");

    var route = RouteTable.Routes[routeName] as Route;
    if (route != null)
    {
        routeValues = routeValues ?? new RouteValueDictionary();
        string routeAction = (routeValues["action"] as string ?? route.Defaults["action"] as string) ?? string.Empty;
        string routeController = (routeValues["controller"] as string ?? route.Defaults["controller"] as string) ?? string.Empty;

        if (routeAction.Equals(currentAction, StringComparison.OrdinalIgnoreCase) && routeController.Equals(currentController, StringComparison.OrdinalIgnoreCase))
        {
            htmlAttributes = htmlAttributes ?? new Dictionary<string, object>();
            var currentCssClass = htmlAttributes["class"] as string ?? string.Empty;
            htmlAttributes["class"] = string.Concat(currentCssClass, currentCssClass.Length > 0 ? " " : string.Empty, "active");
        }
    }

    return htmlHelper.RouteLink(linkText, routeName, routeValues, htmlAttributes);
}

【讨论】:

    【解决方案3】:

    您可以通过阅读ControllerContext.RouteData 来获取应该为您的请求提供服务的 RouteData。 RouteData 对象具有 Values,而 Keys 可以检查并应用于 Values 以获取路线的所有片段。

    通常,您可以遍历RouteCollection(这取决于您所在的上下文,例如ViewContext,或使用HtmlHelper 对象)并提取每个项目并将其转换为Route 对象。之后调用Route.GetRouteData(YourHttpContextBaseHere) 返回RouteData 或null。如果它返回一个对象,则表明 Route 服务于您的请求并检查 Defaults 属性。

    例如,假设您正在构建一个 HTML 帮助程序并且您可以访问 HtmlHelper 对象。以下代码向您展示了您可以做什么:

    var defaults = (RouteValueDictionary) null;
    foreach (var routeBase in html.RouteCollection)
    {
        var route = (Route) routeBase;
        var routeData = route.GetRouteData(html.ViewContext.HttpContext);
    
        if (routeData != null) 
        {
            defaults = route.Defaults;
            break;
        }
    }
    
    // Do something with defaults object
    

    【讨论】:

      【解决方案4】:

      您可以查看System.Web.Routing.RouteTable.Routes。它包含系统中的所有路由。但是如果没有指定 default 动作和控制器,则找不到它们

      【讨论】:

        猜你喜欢
        • 2020-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        • 2012-11-04
        相关资源
        最近更新 更多