C# 为Slug创建一个不留痕迹的AspMvc路由

C# 为Slug创建一个不留痕迹的AspMvc路由,c#,asp.net-mvc-4,razor,asp.net-mvc-routing,slug,C#,Asp.net Mvc 4,Razor,Asp.net Mvc Routing,Slug,假设我有三个实体:Events、People和Pictures,而且Events有一个slug属性来美化我的URL 我想按slug路由事件,并显式路由所有其他实体。另外,我不想要默认路由 /=>EventController/Index/{searchFilder} /{slug}=>EventController/Details/slug /Event/{action}=>EventController/{action} /Profile=>ProfileController/{action

假设我有三个实体:
Events
People
Pictures
,而且
Events
有一个slug属性来美化我的URL

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

  • /=>EventController/Index/{searchFilder}
  • /{slug}=>EventController/Details/slug
  • /Event/{action}=>EventController/{action}
  • /Profile=>ProfileController/{action}/{id}
  • /Picture=>PictureController/{action}/{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

如果我在查看事件时单击主页链接,我会转到
/christmass-2013/Index
。此外,如果我从新索引执行搜索,则新url为
/christmass-2013/index?filter=Summer2014


如何配置它,使其不留痕迹?

由于处理和匹配的顺序,路由定义可能会很挑剔,因为您不希望它们匹配。我从头开始创建了一个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),因此第四个参数本质上限制了“controller”的值。我不知道在事件、配置文件、图片之外是否还有其他控制器,假设您没有。由于配置文件和图片已在以前的路线中映射,因此我们不必在此处约束它们。但是,如果您有帮助控制器或类似的东西,则需要将我的第三条路线更新为

routes.MapRoute(
  name: "Events",
  url: "{controller}/{action}",
  defaults: new { controller = "Event", action = "Index"},
  constraints: new { controller = "Event|Help" });
|
操作符用作
或“
-
控制器必须等于事件或帮助

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

编辑

看来这个路由配置对我来说也很有效(没有限制)

在索引页上:

@Html.ActionLink("Christmas 2013!", "Details", new {controller="Event", slug="Christmas-2013"})
返回URL:
http://localhost:11319/Christmas-2013年

我的事件详细信息页面:
@Html.ActionLink(“主页”、“索引”、“事件”)

返回URL:
http://localhost:11319/


因此,基本上我已经确定有几种可能的方法来实现这一点。这实际上取决于其他URL的复杂程度

如果您将第三条路线(包含url:{slug}/{action}的路线)移动到最后,您是否仍然存在此问题?没有,但我现在无法为slug创建ActionLinks
@Url.Action(“Details”,“Event”,new{slug=Model.slug})
转到
/Events/Details?slug=christmass-2013
而不是
/christmass-2013
明白了,在我的测试中也看到了这一点。创建了一个工作示例,解释如下。让我知道,如果这在你的情况下(假设只看到你的项目的一小部分)首先,我真的很感激像你这样的人,陷入困境,帮助社区。谢谢!其次,我有几个控制器,但将它们添加到约束中不是问题。第三,必须通过文本将每个控制器添加到该约束中是容易出错的,但是如果这样做有效的话,我将继续使用它,直到找到避免该细节的方法为止。我会让你知道这是否解决了我的问题。@odyodyodys我同意,但是如果slug本身没有控制器前缀,那么路由IMHO就有点困难了。可能有一些约束的组合可以使这变得更简单,或者,您可以在使用slug时使用Html.RouteLink并指定一个特定的路由,这样可以避免手动约束控制器名称。@odyodyodys-稍微使用路由字典,在我的简单测试项目中,可能会有一个替代方案。PS-谢谢你帮我拖延,今天我根本不想写代码:)你的第一个答案有两个问题我无法解决:1。我不能开车回家。我的问题与我在问题下方的第一次评论中的问题相同。关于您的编辑:一切正常,但您忽略了一个事实,即我想要
{slug}/{action}
,而不仅仅是
{slug}
。如果我将操作添加到第三条规则中,我将获得与我在问题下方的第一条注释中描述的
{slug}/Event/Create
相同的行为。@odyodyodys-您将如何获得URL
{slug}/Event/Create'。根据你的路线规则,那不应该是{slug}/Create
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"})