如何在ASP.NET MVC中使用小写路由?

时间:2009-05-18 16:30:31

标签: asp.net-mvc url routes case

如何在ASP.NET MVC中使用小写,加上下划线(如果可能)?那么我会/dinners/details/2拨打DinnersController.Details(2),如果可能,/dinners/more_details/2拨打DinnersController.MoreDetails(2)

所有这些仍在使用{controller}/{action}/{id}等模式。

8 个答案:

答案 0 :(得分:228)

使用System.Web.Routing 4.5,您可以通过设置RouteCollection的LowercaseUrls属性来直接实现这一点:

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

        routes.LowercaseUrls = true;

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

另外假设您出于搜索引擎优化的原因这样做,您希望将传入的网址重定向为小写(如本文中的许多链接所述)。

protected void Application_BeginRequest(object sender, EventArgs e)
{
  //You don't want to redirect on posts, or images/css/js
  bool isGet = HttpContext.Current.Request.RequestType.ToLowerInvariant().Contains("get");
  if (isGet && HttpContext.Current.Request.Url.AbsolutePath.Contains(".") == false)    
  {
     string lowercaseURL = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
     if (Regex.IsMatch(lowercaseURL, @"[A-Z]"))
     {
      //You don't want to change casing on query strings
      lowercaseURL = lowercaseURL.ToLower() + HttpContext.Current.Request.Url.Query;

      Response.Clear();
      Response.Status = "301 Moved Permanently";
      Response.AddHeader("Location", lowercaseURL); 
      Response.End();
    }
 }
}

答案 1 :(得分:44)

当我想做同样的事情并且运作良好时,这两个教程很有帮助:

http://www.coderjournal.com/2008/03/force-mvc-route-url-lowercase/ http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/

编辑:对于包含区域的项目,您需要修改GetVirtualPath()方法:

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
  var lowerCaseValues = new RouteValueDictionary();

  foreach (var v in values)
  {
    switch (v.Key.ToUpperInvariant())
    {
      case "ACTION":
      case "AREA":
      case "CONTROLLER":
        lowerCaseValues.Add(v.Key, ((string)v.Value).ToLowerInvariant());
        break;
      default:
        lowerCaseValues.Add(v.Key.ToLowerInvariant(), v.Value);
        break;
    }
  }
  return base.GetVirtualPath(requestContext, lowerCaseValues);
}

答案 2 :(得分:21)

如果您使用UrlHelper生成链接,则只需将操作和控制器的名称指定为小写:

itemDelete.NavigateUrl = Url.Action("delete", "photos", new { key = item.Key });

结果:/ media / photos / delete / 64(即使我的控制器和动作都是pascal的情况)。

答案 3 :(得分:15)

我在Nick Berardi’s Coder Journal找到了这个,但它没有关于如何实现LowercaseRoute类的信息。因此在此重新发布附加信息。

首先将Route课程延伸至LowercaseRoute

public class LowercaseRoute : Route
{
    public LowercaseRoute(string url, IRouteHandler routeHandler)
        : base(url, routeHandler) { }
    public LowercaseRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
        : base(url, defaults, routeHandler) { }
    public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
        : base(url, defaults, constraints, routeHandler) { }
    public LowercaseRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler) : base(url, defaults, constraints, dataTokens, routeHandler) { }
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        VirtualPathData path = base.GetVirtualPath(requestContext, values);

        if (path != null)
            path.VirtualPath = path.VirtualPath.ToLowerInvariant();

        return path;
    }
}

然后修改Global.asax.cs的RegisterRoutes方法

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

    routes.Add(new LowercaseRoute("{controller}/{action}/{id}", 
        new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }), 
        new MvcRouteHandler()));

    //routes.MapRoute(
    //    "Default",                                              // Route name
    //    "{controller}/{action}/{id}",                           // URL with parameters
    //    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    //);
}

我想知道一种使用routes.MapRoute ...

的方法

答案 4 :(得分:14)

如果你碰巧使用ASP.NET Core,你可能应该看看this

  

将以下行添加到ConfigureServices类的Startup方法。

services.AddRouting(options => options.LowercaseUrls = true);

答案 5 :(得分:11)

您可以通过将此类添加为RouteCollection的扩展来继续使用MapRoute语法:

public static class RouteCollectionExtension
{
    public static Route MapRouteLowerCase(this RouteCollection routes, string name, string url, object defaults)
    {
        return routes.MapRouteLowerCase(name, url, defaults, null);
    }

    public static Route MapRouteLowerCase(this RouteCollection routes, string name, string url, object defaults, object constraints)
    {
        Route route = new LowercaseRoute(url, new MvcRouteHandler())
        {
            Defaults = new RouteValueDictionary(defaults),
            Constraints = new RouteValueDictionary(constraints)
        };

        routes.Add(name, route);

        return route;
    }
}

现在您可以在应用程序的启动中使用“MapRouteLowerCase”而不是“MapRoute”:

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

        // Url shortcuts
        routes.MapRouteLowerCase("Home", "", new { controller = "Home", action = "Index" });
        routes.MapRouteLowerCase("Login", "login", new { controller = "Account", action = "Login" });
        routes.MapRouteLowerCase("Logout", "logout", new { controller = "Account", action = "Logout" });

        routes.MapRouteLowerCase(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );
    }

答案 6 :(得分:6)

这实际上有两个答案:

  1. 您已经可以执行此操作:路由引擎执行不区分大小写的比较。如果键入小写路由,它将路由到相应的控制器和操作。
  2. 如果您使用生成路由链接的控件(ActionLink,RouteLink等),除非您覆盖此默认行为,否则它们将生成混合大小写链接。
  3. 你可以通过自己的下划线,但是......

答案 7 :(得分:2)

你能使用ActionName属性吗?

 [ActionName("more_details")]
 public ActionResult MoreDetails(int? page)
 {

 }

我认为案件不重要。 URL中的More_Details,more_DETAILS,mOrE_DeTaILs将带您进入相同的Controller Action。