为Slug创建Asp Mvc路线,不留任何痕迹

时间:2013-12-24 14:08:12

标签: c# asp.net-mvc-4 razor asp.net-mvc-routing slug

假设我有三个实体:EventsPeoplePicturesEvents还有一个slug属性来美化我的网址。

我想通过slug路由事件,并显式路由所有其他实体。另外,我不想要默认路由。

  • / => EventController /索引/ {searchFilder}
  • / {slug} => EventController /详情/弹头
  • / Event / {action} => EventController / {动作}
  • /个人资料=> ProfileController可/ {动作} / {ID}
  • / Picture => PictureController / {动作} / {ID}

事件控制器被映射三次。使用slug获取现有事件,没有站点索引页面的参数以及其他操作,因此我可以执行Create(例如,当时没有slug)。

考虑到这一点,我的地图如下:

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

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

routes.MapRoute(
    name: "EventBySlug",
    url: "{slug}/{action}",
    defaults: new { controller = "Event", action = "Details"} );

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

routes.MapRoute(
    name: "Default",
    url: "",
    defaults: new { controller = "Event", action = "Index" } );

这很好,直到我为主页面(在我的布局中)创建一个ActionLink

@Html.ActionLink("Home", "Index", "Events")

如果我在观看活动/christmass-2013时点击了主页链接,我会转到/christmass-2013/Index。此外,如果我从新索引执行搜索,则新网址为/christmass-2013/Index?filter=Summer2014

如何配置它以便我不留下任何痕迹?

1 个答案:

答案 0 :(得分:2)

由于处理顺序和匹配路线您不希望它们匹配,路线定义可能很挑剔。我从零开始创建了一个MVC应用程序,并且能够让您的路由正常工作,并且实际上能够删除一个。首先是代码,然后是解释:

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

routes.MapRoute(
    name: "Pictures",
    url: "Picture/{action}/{id}",
    defaults: new
    {
        controller = "Picture",
        action = "Index",
        id = UrlParameter.Optional
    });
routes.MapRoute(
    name: "Events",
    url: "{controller}/{action}",
    defaults: new { controller = "Event", action = "Index"},
    constraints: new { controller = "Event" });

routes.MapRoute(
    name: "EventBySlug",
    url: "{slug}",
    defaults: new { controller = "Event", action = "Details" });

首先,由于您的第四条和第五条路线基本相同(没有URL),我们能够将这些路线组合到我的第三条路线中。其次,我们需要你的slug路由只在没有其他路由匹配时被调用,所以我们将它移动到最后一个路由(这会处理你提到的路径)。最后,由于我的路径3和4都可能被调用(我们如何知道它是slug还是控制器),还有第四个参数基本上限制了“Controller”的值。我不知道你是否有任何其他控制器在Event,Profile,Picture之外,这假设你没有。由于Profile和Picture已经映射到以前的路径中,因此我们不必在此处约束它们。但是,如果您有一个帮助控制器或类似的东西,您需要更新我的第三条路线

routes.MapRoute(
  name: "Events",
  url: "{controller}/{action}",
  defaults: new { controller = "Event", action = "Index"},
  constraints: new { controller = "Event|Help" });

|运算符用作"OR" - controller must equal Event Or Help

谨慎的话。一,确保slug永远不会是控制器的名称,否则slug会尝试映射到控制器/动作而不是细节。第二,如果通过slug进行路由,请确保它们在您的系统中是唯一的,否则您可能会提取错误的数据。

修改

看来这个路由配置也适用于我(没有约束)

routes.MapRoute(
   name: "EventBySlug",
   url: "{slug}",
   defaults: new { controller = "Event", action = "Details" });

routes.MapRoute(
   name: "Events",
   url: "{controller}/{action}",
   defaults: new { controller = "Event", action = "Index"});

在索引页面上:

@Html.ActionLink("Christmas 2013!", "Details", new {controller="Event", slug="Christmas-2013"})

返回网址:http://localhost:11319/Christmas-2013

我的活动详情页面:@Html.ActionLink("Home", "Index", "Event")

返回网址:http://localhost:11319/

所以基本上我已经确定有几种可能的方法来实现这一目标。这实际上取决于您的其他一些URL的复杂程度。