asp.net-mvc 如何在 ASP.NET MVC 中使用小写路由?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/878578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 23:34:40  来源:igfitidea点击:

How can I have lowercase routes in ASP.NET MVC?

asp.net-mvcurlroutescase

提问by pupeno

How can I have lowercase, plus underscore if possible, routes in ASP.NET MVC? So that I would have /dinners/details/2call DinnersController.Details(2)and, if possible, /dinners/more_details/2call DinnersController.MoreDetails(2)?

如何在 ASP.NET MVC 中使用小写和下划线(如果可能)路由?所以我会/dinners/details/2打电话DinnersController.Details(2),如果可能的话,/dinners/more_details/2打电话DinnersController.MoreDetails(2)

All this while still using patterns like {controller}/{action}/{id}.

所有这一切,同时仍然使用像{controller}/{action}/{id}.

回答by ITmeze

With System.Web.Routing 4.5 you may implement this straightforward by setting LowercaseUrls property of RouteCollection:

使用 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 }
        );
    }

Also assuming you are doing this for SEO reasons you want to redirect incoming urls to lowercase (as said in many of the links off this article).

还假设您出于 SEO 原因这样做,您希望将传入的 url 重定向为小写(如本文中的许多链接所述)。

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();
    }
 }
}

回答by Derek Lawless

These two tutorials helped when I wanted to do the same thing and work well:

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

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

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

EDIT: For projects with areas, you need to modify the GetVirtualPath() method:

编辑:对于有区域的项目,您需要修改 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);
}

回答by Ebrahim Byagowi

If you happened to use ASP.NET Core, you probably should have a look at this:

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

Add the following line to the ConfigureServicesmethod of the Startupclass.

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

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

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

回答by Matt

If you are using the UrlHelper to generate the link, you can simply specify the name of the action and controller as lowercase:

如果您使用 UrlHelper 生成链接,您可以简单地将操作和控制器的名称指定为小写:

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

Results in: /media/photos/delete/64 (even though my controller and action are pascal case).

结果为:/media/photos/delete/64(即使我的控制器和动作是 pascal 大小写)。

回答by John Oxley

I found this at Nick Berardi's Coder Journal, but it did not have information on how to implement the LowercaseRouteclass. Hence reposting here with additional information.

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

First extend the Routeclass to 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;
    }
}

Then modify the RegisterRoutesmethod of Global.asax.cs

然后修改RegisterRoutesGlobal.asax.cs的方法

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
    //);
}

I would however like to know a way to use routes.MapRoute...

但是,我想知道一种使用 routes.MapRoute 的方法...

回答by Markus Wolters

You can continue use the MapRoute syntax by adding this class as an extension to RouteCollection:

您可以通过将此类添加为 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;
    }
}

Now you can use in your application's startup "MapRouteLowerCase" instead of "MapRoute":

现在您可以在应用程序的启动中使用“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
        );
    }

回答by GalacticCowboy

This actually has two answers:

这实际上有两个答案:

  1. You can already do this: the route engine does case-insensitive comparison. If you type a lower-case route, it will be routed to the appropriate controller and action.
  2. If you are using controls that generate route links (ActionLink, RouteLink, etc.) they will produce mixed-case links unless you override this default behavior.
  1. 您已经可以这样做了:路由引擎进行不区分大小写的比较。如果您键入小写路由,它将被路由到适当的控制器和操作。
  2. 如果您正在使用生成路由链接(ActionLink、RouteLink 等)的控件,除非您覆盖此默认行为,否则它们将生成大小写混合的链接。

You're on your own for the underscores, though...

但是,您需要自己使用下划线...

回答by GuyIncognito

Could you use the ActionName attribute?

您可以使用 ActionName 属性吗?

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

 }

I don't think case matters. More_Details, more_DETAILS, mOrE_DeTaILs in the URL all take you to the same Controller Action.

我认为案子不重要。URL 中的 More_Details、more_DETAILS、mOrE_DeTaILs 都会将您带到同一个控制器操作。