[asp.net-mvc] ASP.NET MVC에서 소문자 경로를 사용하려면 어떻게해야합니까?

ASP.NET MVC에서 소문자와 가능한 경우 밑줄을 사용하여 라우팅 할 수 있습니까? 그래서 내가 가진 것이라고 /dinners/details/2전화를 DinnersController.Details(2), 가능하다면, 그리고 /dinners/more_details/2전화를 DinnersController.MoreDetails(2)?

이 모든 것은 여전히 ​​같은 패턴을 사용합니다 {controller}/{action}/{id}.



답변

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

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


답변

이 두 튜토리얼은 똑같은 일을하고 잘 작동하고 싶을 때 도움이되었습니다.

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


답변

ASP.NET Core를 사용한 경우 다음을 살펴보아야 합니다 .

클래스 의 ConfigureServices메소드에 다음 행을 추가하십시오 Startup.

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

답변

UrlHelper를 사용하여 링크를 생성하는 경우 조치 및 컨트롤러 이름을 소문자로 간단히 지정할 수 있습니다.

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

결과 : / media / photos / delete / 64 (내 컨트롤러와 액션이 파스칼 케이스 임에도 불구하고).


답변

Nick Berardi의 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;
    }
}

그런 다음 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
    //);
}

그러나 route.MapRoute를 사용하는 방법을 알고 싶습니다.


답변

이 클래스를 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;
    }
}

이제 “MapRoute”대신 응용 프로그램 시작 “MapRouteLowerCase”에서 사용할 수 있습니다.

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


답변

실제로 두 가지 답변이 있습니다.

  1. 경로 엔진은 대소 문자를 구분하지 않습니다. 소문자 경로를 입력하면 해당 컨트롤러 및 작업으로 경로가 지정됩니다.
  2. 경로 링크 (ActionLink, RouteLink 등)를 생성하는 컨트롤을 사용하는 경우이 기본 동작을 무시하지 않으면 대소 문자가 혼합 된 링크가 생성됩니다.

당신은 밑줄로 당신 자신에 있습니다.