ASP.NET MVC'de nasıl küçük harfli yollara sahip olabilirim?


146

ASP.NET MVC 'de nasıl küçük harf ve artı mümkünse alt çizgi yollarına sahip olabilirim? Böylece /dinners/details/2arayabilirim DinnersController.Details(2)ve mümkünse /dinners/more_details/2arayabilirim DinnersController.MoreDetails(2)?

Bütün bunlar hala gibi kalıpları kullanırken {controller}/{action}/{id}.


Zaten çeşitli nedenlerle tüm rotalarımı manuel olarak yazdım ve bunu sadece CRUD dışında bir şeyle yapmaktan kaçınmanın zor olduğunu düşünüyorum. Ben de onları küçük harflerle yazdım.
pupeno

Web Formlarını mı Kullanıyorsunuz ? Buraya gidin: msdn.microsoft.com/en-us/library/… . (Projemi yavaş yavaş web formlarından MVC'ye dönüştürüyorum ve her ikisine de projede sahip oluyorum)
Jess

Bunu varsayılan olarak yapabileceğinizden oldukça eminim

Güzergahları küçük veya büyük harflerle yazmanın önemli olduğunu sanmıyorum.

Yanıtlar:


243

System.Web.Routing 4.5 ile, RouteCollection'ın LowercaseUrls özelliğini ayarlayarak bu doğrudan uygulayabilirsiniz:

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

Ayrıca, bunu SEO nedenleriyle yaptığınızı varsayarsak, gelen URL'leri küçük harfe yönlendirmek istiyorsunuz (bu makaledeki bağlantıların çoğunda söylendiği gibi).

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
Bu, 4.0'da yapılacak en basit şeydir.
Paul Turner

1
Keşke bu en üstte olsaydı ... Neredeyse kargoyla çok fazla kod kültive etti!
akatakritos

2
Harika cevap :-) İkinci SEO kısmı bir HTTP modülüne güzelce uyuyor.
David Kirkland

1
@Aaron Sherman Application_BeginRequest kısmının nereye gitmesi bekleniyor? RouteConfig sınıfının içindeyken ve ayrıca if dışında olduğunda bana hatalar veriyor.
Richard Mišenčík

1
@ richard-mišenčík bunu Global.asax dosyasına ekle
ITmeze

44

Bu iki öğretici, aynı şeyi yapmak ve iyi çalışmak istediğimde yardımcı oldu:

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

DÜZENLE: Alanlara sahip projeler için GetVirtualPath () yöntemini değiştirmeniz gerekir:

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 bağlantısı değişti; URL artık gittiale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc
Daniel Liuzzi

4
@Derek - Hayır, Area's kullanılırken öğreticiler bozuluyor. HER ŞEYİ denedikten 3 gün sonra ... Daha iyi bir çözüm buldum, burada Attribute Routing adlı bir kitaplık var. Problemi çözer ve hayatı çok daha kolaylaştırır. philliphaydon.com/2011/08/…
Phill

6
Mvc 4 için özellik yollarını kullanan daha iyi bir çözüm vardır.LowercaseUrls = true; Dhuvelle.com/2012/11/tips-for-aspnet-mvc-4-lowercase-urls.html hakkında
Marc Cals

4
@GONeale URL'nize ne oldu? İkinci halka artık öldü! Yine de güldürdü, başlık " İnternetteki En İyi Gitmiş Ali Sitesi"
Luke

2
@chteuchteu bu bağlantı benim için işe yaramadı, ama bu işe yaradı.
chue x


21

Bağlantıyı oluşturmak için UrlHelper kullanıyorsanız, eylemin ve denetleyicinin adını küçük harf olarak belirtebilirsiniz:

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

Sonuç: / media / photos / delete / 64 (denetleyicim ve eylemim pascal durumda olsa bile).


16
Bu işi tek bir merkezi konumda yapmanın en kolay ve en standart çözüm olduğunu düşünüyorum. Bu, satır içi CSS kadar kötüdür. (Görünüşe göre 15 kişi satır içi CSS kullanıyor).
The Muffin Man

Linux sunucuları için de doğru mu?
QMaster

15

Bunu Nick Berardi'nin Coder Journal'da buldum , ancak LowercaseRoutesınıfın nasıl uygulanacağına dair bilgi yoktu . Bu nedenle ek bilgilerle burada yeniden yayınlama.

Önce Routesınıfı genişletinLowercaseRoute

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

Ardından RegisterRoutesGlobal.asax.cs yöntemini değiştirin

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

Ancak rotaları kullanmanın bir yolunu öğrenmek istiyorum.MapRoute ...


GONeale'nin makalesi routes.MapRouteLowercase(..., yukarıdakinden daha güzel yazabilmeniz için bir uzatma yöntemi sağlar : goneale.wordpress.com/2008/12/19/…
Drew Noakes

1
GONeale'nin tüm blogu kayboldu. İşte benzer içeriğe (ve aynı uzantı yöntemine) sahip başka bir blog girişi . Yinelenen içeriği azaltma bağlamında bu durumu ele alır.
patridge

11

Bu sınıfı RouteCollection'a bir uzantı olarak ekleyerek MapRoute sözdizimini kullanmaya devam edebilirsiniz:

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

Artık uygulamanızın başlangıcında "MapRoute" yerine "MapRouteLowerCase" kullanabilirsiniz:

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

Bunu okuyan herkes için, LowercaseRouteyukarıdaki ilk kod parçacığındaki sınıf bu diğer cevaptan
chue x

6

Bunun aslında iki cevabı var:

  1. Bunu zaten yapabilirsiniz: rota motoru büyük / küçük harfe duyarlı olmayan karşılaştırma yapar. Küçük harfli bir yol yazarsanız, uygun denetleyiciye ve eyleme yönlendirilir.
  2. Rota bağlantıları (ActionLink, RouteLink, vb.) Oluşturan kontroller kullanıyorsanız, bu varsayılan davranışı geçersiz kılmadığınız sürece bunlar karışık durumlu bağlantılar oluşturur.

Yine de alt çizgiler için tek başınasın ...


2

ActionName özniteliğini kullanabilir misiniz?

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

 }

Davanın önemli olduğunu sanmıyorum. URL'deki More_Details, more_DETAILS, mOrE_DeTaIL'lerin tümü sizi aynı Controller Action'a götürür.


Bunu denemedim - ikisini de kullanmana izin verecek mi? ("moredetails" veya "more_details")
GalacticCowboy

Takip etmek için denedim ve belirtilen adı kullanmanızı gerektiriyor, bu yüzden hayır, her iki şekilde de halletmenize izin vermeyecek. Ayrıca, denetleyici eyleminizi ve görünümünüzü nasıl oluşturduğunuza bağlı olarak, görünümün adını açıkça belirtmeniz gerekebilir.
GalacticCowboy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.