【问题标题】:mvcSitemap and multiple routesmvcSitemap 和多条路线
【发布时间】:2015-02-26 13:18:49
【问题描述】:

我正在尝试使用 MVC 站点地图为我的应用程序创建面包屑路径。我有多个路由到用户控制器,需要为每个路由保留面包屑。 mvcSiteMap 如何将每个节点映射到路由?

我有以下可能的途径进入用户:

/用户/{action}/{userid}

/User/{groupid}/{action}/{userid}

我分别想要以下面包屑路径:

应用根目录 > 用户 > {用户名} > {操作}

App Root > Group Management > {Group Name} > {User Name} > {Action}

上面的第一条路线很简单,我用 [SiteMapTitle("Mail")] 装饰 Details 控制器以显示对象 Mail 属性而不是 "Details",并且用 [SiteMapTitle("Mail" ", Target = AttributeTarget.ParentNode)] 以在编辑时保留电子邮件地址。

但是,当使用第二条路线时,我无法弄清楚如何做到这一切。面包屑路径根本不显示任何内容。组部分中的用户部分似乎什么都不做。实现这一目标的最佳方法是什么?

Mvc.Sitemap:

    <mvcSiteMapNode title="User Management" controller="User" action="Index">
      <mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id">
        <mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id"/>
      </mvcSiteMapNode>
    </mvcSiteMapNode>

    <mvcSiteMapNode title="Group Management" controller="Group" action="Index">
      <mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="id">
        <mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="id"/>

        <mvcSiteMapNode title="Users" controller="User" action="Index" preservedRouteParameters="groupid">
          <mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id, groupid">
            <mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id, groupid"/>
            <mvcSiteMapNode title="Manage" action="Manage" controller="User" preservedRouteParameters="id, groupid"/>
          </mvcSiteMapNode>
        </mvcSiteMapNode>


      </mvcSiteMapNode>
      <mvcSiteMapNode title="New" action="Create" controller="Group" />
    </mvcSiteMapNode>
    ...
  </mvcSiteMapNode>

路线:

routes.MapRoute("ByGroup", "User/{groupid}/{action}/{id}",
                        new { controller = "User", action = "Index", id = UrlParameter.Optional }, new { groupid = new GuidConstraint() });

routes.MapRoute("ByGroup2", "User/{groupid}/{action}/{id}",
                        new { controller = "User", action = "Index", id = UrlParameter.Optional, groupid = UrlParameter.Optional }, new { groupid = new GuidConstraint() });


routes.MapRoute("User", "User/{action}/{id}",
                        new { controller = "User", action = "Index", id = UrlParameter.Optional });

        
routes.MapRoute("Default", "{controller}/{action}/{id}",
                        new { controller = "Home", action = "Index", id = UrlParameter.Optional });

【问题讨论】:

  • 你能显示你的整个路由配置,包括默认值和约束吗?如果您确实按照该顺序列出了您的用户路线,没有任何限制,那么您的路线就有问题。
  • 添加路线 - 根据要求。

标签: asp.net-mvc asp.net-mvc-routing mvcsitemapprovider


【解决方案1】:

节点:

<mvcSiteMapNode title="User Management" controller="User" action="Index" route="Default">
    <mvcSiteMapNode title="Details" action="Details" controller="User" route="Default" preservedRouteParameters="id">
        <mvcSiteMapNode title="Edit" action="Edit" controller="User" route="Default" preservedRouteParameters="id"/>
    </mvcSiteMapNode>
</mvcSiteMapNode>

<mvcSiteMapNode title="Group Management" controller="Group" action="Index">
    <mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="groupid">
        <mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="groupid"/>

        <mvcSiteMapNode title="Users" controller="User" action="Index" route="ByGroup" preservedRouteParameters="groupid">
            <mvcSiteMapNode title="Details" action="Details" controller="User" route="ByGroup" preservedRouteParameters="id, groupid">
                <mvcSiteMapNode title="Edit" action="Edit" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
                <mvcSiteMapNode title="Manage" action="Manage" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
            </mvcSiteMapNode>
        </mvcSiteMapNode>

    </mvcSiteMapNode>
    <mvcSiteMapNode title="New" action="Create" controller="Group" />
</mvcSiteMapNode>

路线:

routes.MapRoute(
    name: "Group", 
    url: "Group/{action}/{groupid}",
    defaults: new { controller = "Group", action = "Index", groupid = UrlParameter.Optional });

routes.MapRoute(
    name: "ByGroup",
    url: "User/{groupid}/{action}/{id}",
    defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
    constraints: new { groupid = new GuidConstraint() });

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

说明

您在 ByGroup2 路由上定义了 2 个可选段,这是不允许的。可选段必须位于 URL 的最右侧,并且后面不能跟必需段。这可能会导致问题。

此外,我没有看到 ByGroup2 路由的任何真正用途。

/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Edit/123 - matches ByGroup
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Index - matches ByGroup
/User/Edit/123 - matches User
/User/Index - matches User

我想不出一个匹配ByGroup2 的案例。但是如果它匹配,你的参数将被放入不同的路由键中,而不是它匹配User 路由,这可能会造成混淆。

此外,您的 User 路由似乎没有在 Default 路由上添加任何内容。因此,您的路线配置可能看起来像这样并做完全相同的事情(减去路线值位置的混淆,这可能会给您带来问题)。

routes.MapRoute("ByGroup", "User/{groupid}/{action}/{id}",
                    new { controller = "User", action = "Index", id = UrlParameter.Optional }, new { groupid = new GuidConstraint() });

routes.MapRoute("Default", "{controller}/{action}/{id}",
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional });

然后匹配将如下所示。

/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Edit/123 - matches ByGroup
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Index - matches ByGroup
/User/Edit/123 - matches Default
/User/Index - matches Default

但是,您的 reservedRouteParameters 也存在问题。

<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="id">
    <mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="id"/>

        <mvcSiteMapNode title="Users" controller="User" action="Index" preservedRouteParameters="groupid">
            <mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id, groupid">
                <mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id, groupid"/>
                <mvcSiteMapNode title="Manage" action="Manage" controller="User" preservedRouteParameters="id, groupid"/>
            </mvcSiteMapNode>
        </mvcSiteMapNode>
    </mvcSiteMapNode>
</mvcSiteMapNode>

为了使preservedRouteParameters 匹配多个级别,必须提供祖先 节点的所有自定义路由值(在本例中为idgroupid)。此外,它们必须具有相同的含义。为此,id 必须始终通过节点一直引用同一个实体,并且无论多深都必须包含在每个链接中。您必须为组实体选择一个不同的路由键而不是用户实体。

要清理这一点,您可以再次更改路线,将所有信息放入所需的路线中。您已经完成了大部分工作 - 您只需要修复 Group 节点的 id。

routes.MapRoute(
    name: "Group", 
    url: "Group/{action}/{groupid}",
    defaults: new { controller = "Group", action = "Index", groupid = UrlParameter.Optional });

routes.MapRoute(
    name: "ByGroup",
    url: "User/{groupid}/{action}/{id}",
    defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
    constraints: new { groupid = new GuidConstraint() });

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

和节点:

<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="groupid">
    <mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="groupid"/>

    <mvcSiteMapNode title="Users" controller="User" action="Index"  route="ByGroup" preservedRouteParameters="groupid">
        <mvcSiteMapNode title="Details" action="Details" controller="User" route="ByGroup" preservedRouteParameters="id, groupid">
        <mvcSiteMapNode title="Edit" action="Edit" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
    <mvcSiteMapNode title="Manage" action="Manage" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>

注意到/Group/Index 节点下方的每条路由现在都有一个groupid,而groupid 键始终指向同一个实体?

此外,为了确保我们只匹配相关路由,我们明确指定它。如果我们不这样做,用户节点将不明确,因此您将得到错误的面包屑路径(匹配的第一个节点获胜)。

route="ByGroup"

使用上述配置,您需要构建指向UsersUsers/DetailsUsers/EditUsers/Manage 的链接,其中包括当前groupid(当然还有当前用户ID) .

@Html.ActionLink("Edit User", "Edit", "User", new { id = <userid>, groupid = <groupid> }, null)

然后,当您导航到“编辑用户”链接时,groupid 将出现在当前请求中,在解析 URL 时会将其提供给 Users/Details 节点、Group/Edit 节点和 Group/Details 节点,因此您可以通过面包屑路径导航回这些位置。

有关另一个示例,请参阅代码下载 of this article 中的 Forcing-A-Match-2-Levels 示例。

没有组的用户部分将匹配Default 路由,并在构建没有groupid 的URL 时显示适当的面包屑路径。

所以我们明确指定默认路由:

route="Default"

并构建如下 URL:

@Html.ActionLink("Edit User", "Edit", "User", new { id = <userid> }, null)

【讨论】:

  • 先生,这是一个绝妙的答案,也是一个近乎完美的解决方案。我说几乎是因为在组/用户/编辑级别时,面包屑路径是根 > 组管理 > 详细信息 > 用户 > user@mail.com > 编辑。我需要的是用组名替换“详细信息”,但是我想我知道解决方案。谢谢!
  • 我替换细节的计划失败了...不过我会为那个开始另一个线程。
  • 正如您的问题,[SiteMapTitle] 属性是解决方案。但是,它在控制器级别无效,因为它需要模型中的值或 ViewData 中的值才能起作用,因此您需要将其放置在每个适用的操作方法上。
猜你喜欢
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 2023-03-10
  • 1970-01-01
  • 2011-07-10
  • 2016-06-04
相关资源
最近更新 更多