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


145

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

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


어쨌든 여러 가지 이유로 모든 경로를 수동으로 작성했으며 CRUD뿐만 아니라 다른 것으로도 피하는 것이 어렵다고 생각합니다. 방금 소문자로 썼습니다.
— pupeno

웹 양식 사용 ? 여기로 이동 : msdn.microsoft.com/en-us/library/...를 . (저는 점차 프로젝트를 웹 양식에서 MVC로 변환하고 있으며 프로젝트에 둘 다 가지고 있습니다)
— Jess

확신 기본적으로이 작업을 수행 할 수있는 메신저

소문자 또는 대문자로 경로를 입력하면 중요하지 않다고 생각합니다.

답변:


238

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

4
이것은 4.0에서 가장 간단한 일입니다.
— Paul Turner

1
이것이 정상에 있었으면 좋겠다 ... 거의 많은화물이 코드를 작성했습니다!
— akatakritos

2
좋은 답변 :-) 후자의 SEO 부분은 HTTP 모듈에 잘 맞습니다.
— David Kirkland

1
@Aaron Sherman Application_BeginRequest 부분은 어디로 가야합니까? 내부 공용 클래스 RouteConfig 및 if 외부에있을 때 오류가 발생합니다.
— Richard Mišenčík 2016 년

1
@ richard-mišenčík Global.asax 파일에 추가
— ITmeze 2016 년

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

9
GONeale 링크가 변경되었습니다. URL은 이제 goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc
— Daniel Liuzzi

4
@Derek-아닙니다. 영역을 사용할 때 튜토리얼이 고장납니다. 3 일 동안 모든 것을 시도한 후 ... 더 나은 해결책을 찾았습니다. 속성 라우팅이라는 라이브러리가 있습니다. 문제를 해결하고 인생을 훨씬 쉽게 만듭니다. philliphaydon.com/2011/08/…
— Phill

6
mvc 4의 경우 속성 라우트를 사용하는 더 나은 솔루션이 있습니다 .LowercaseUrls = true; dhuvelle.com/2012/11/tips-for-aspnet-mvc-4-lowercase-urls.html에
— Marc Cals

4
@GONeale URL은 어떻게 되었습니까? 두 번째 링크는 이제 죽었습니다! 제목은 " 인터넷에서 최고의 사라 에일 사이트"입니다
— 누가

2
@ chteuchteu 그 링크는 저에게 효과가 없었지만 이것은 효과 가있었습니다.
— chue x


21

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

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

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


16
중앙 위치에서이 작업을 수행하는 것이 가장 쉽고 가장 표준적인 솔루션이라고 생각합니다. 이것은 인라인 CSS만큼 나쁩니다. (명백히 15 명은 인라인 CSS를 사용합니다).
— 머핀 남자

Linux 서버에서도 마찬가지입니까?
— QMaster

15

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를 사용하는 방법을 알고 싶습니다.


GONeale의 기사는 쓸 수 있도록 확장 방법을 제공한다 routes.MapRouteLowercase(...: 상기 이외 좋네요있는 goneale.wordpress.com/2008/12/19/...
— 드류 녹스

1
GONeale의 전체 블로그가 사라졌습니다. 다음은 유사한 내용 (및 동일한 확장 방법)을 가진 다른 블로그 항목 입니다. 중복 컨텐츠를 줄이기 위해 이러한 상황을 해결합니다.
— patridge

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

이제 "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
        );
    }

사람이 읽기를 들어, LowercaseRoute이 나타납니다 위의 첫 번째 코드에서 클래스에서 와서 이 다른 대답
— chue가 X

6

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

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

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


2

ActionName 속성을 사용할 수 있습니까?

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

 }

나는 사건이 중요하다고 생각하지 않습니다. URL의 More_Details, more_DETAILS, mOrE_DeTaIL은 모두 동일한 컨트롤러 작업으로 연결됩니다.


나는 그것을 시도하지 않았다-당신이 어느 쪽을 사용하게 할 것인가? ( "moredetails"또는 "more_details")
— GalacticCowboy

후속 조치를 시도했지만 지정된 이름을 사용해야하므로 아니오, 어떤 식 으로든 처리 할 수 ​​없습니다. 또한 제어기 조치 및보기를 구성한 방법에 따라보기 이름을 명시 적으로 지정해야 할 수도 있습니다.
— GalacticCowboy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.