【问题标题】:MVC route rule to default to Home controller when no controller passed in url当没有控制器传入 url 时,MVC 路由规则默认为 Home 控制器
【发布时间】:2017-11-18 03:43:28
【问题描述】:

我在 Home 控制器中有一些简单的视图,例如“关于我们”和“联系我们”。

我希望 url 中没有 home 部分,例如 www.xyz.com/ContactUs 而不是 www.xyz.com/Home/ContactUs

我添加了一个新的路由来处理这个问题,但是当没有在 url 中指定操作时会破坏其他控制器

// Home Routes
RouteTable.Routes.MapRoute("HomeRoute", "{action}", new { controller = "Home", action = "Index" });

// Default
RouteTable.Routes.MapRoute("Default", "{controller}/{action}", new { controller = "Home", action = "Index" });

这显然是因为路由引擎无法判断像www.xyz.com/ContactUs 这样的url 使用哪个路由并使用第一个来匹配。

我也知道我可以为每个控制器制作控制器,但这似乎是一种效率较低的方法。我不想以 30 个控制器结束,而只是为每个视图包装一个空视图操作。

无论如何,我可能最终都会为每个控制器制作控制器,但我想知道是否有办法制作一条类似 “如果只传递一个参数,首先检查它是否匹配控制器,如果不是,则假定它用于家庭控制器。”

【问题讨论】:

  • Why map special routes first before common routes in asp.net mvc?。您需要 something 来告诉 MVC 何时跳过第一条路线并移动到第二条路线。最简单的选择是在路由配置中使用静态 URL,例如 ContactUs 而不是使用 {action}(它可以匹配任何内容)。属性路由是另一种选择,但它有自己的一组问题(即,当您创建属性时,您必须始终注意默认情况下属性具有 undefined order,因此您可能必须显式设置 Order 属性)。

标签: asp.net-mvc routes


【解决方案1】:

您可以使用 MVC 属性路由来创建这些对 SEO 友好的路由。

[Route("About")]
public ActionResult About()
{
    return View();
}
[Route("Contact")]
public ActionResult Contact()
{
    return View();
}

假设您启用了属性路由。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

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

    );
}

另一种选择是进行 2 个与您尝试过的类似的路由注册。它将用于处理yourSite/About/ 之类的请求(它将呈现在您的 HomeController 中执行 About 操作)。但是当您请求类似yourSite/Books 的内容时,它不会由Books 控制器的Index 操作处理,因为该url 与我们为SEO 友好路由定义的第一个模式匹配,如果没有,您将获得404 BooksHomeController 中的操作方法! (如果你没有这个路由注册,它会工作)

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

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

另一种选择,如果你不喜欢属性路由的方式,你可以在你的RegisterRoutes方法中为这个特定的路由一一注册路由。 (这类似于通过属性路由定义路由,但我们在一个地方进行。确保在通用默认路由之前注册了特定路由)。我个人更喜欢属性路由,因为我觉得它更具可读性。

【讨论】:

  • 我想我并没有考虑只为每个视图制作一条特定的路线,而不是尝试制作一个通用的路线。在性能、测试等方面使用属性路由有什么缺点吗?
  • 我知道没有性能开销。我个人更喜欢属性路由方法而不是单独的特定路由定义,因为我觉得它更具可读性。
  • 当然,使用属性路由会有性能开销。它依靠反射来读取您放入属性的值。不过,这种开销通常仅限于应用程序启动。
猜你喜欢
  • 2012-12-27
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-07
  • 2013-06-12
  • 2014-09-20
  • 1970-01-01
相关资源
最近更新 更多