154

ASP.NET MVC で、小文字に加えて、可能であればアンダースコアをルートにするにはどうすればよいですか? 私は/dinners/details/2電話DinnersController.Details(2)をかけ、可能であれば/dinners/more_details/2電話をかけDinnersController.MoreDetails(2)ますか?

のようなパターンを使用しながら、これらすべてを行います{controller}/{action}/{id}

4

8 に答える 8

253

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("."))
        {
            //You don't want to modify URL encoded chars (ex.: %C3%8D that's code to Í accented I) to lowercase, than you need do decode the URL
            string urlLowercase = Request.Url.Scheme + "://" + HttpUtility.UrlDecode(HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
            //You want to consider accented chars in uppercase check
            if (Regex.IsMatch(urlLowercase, @"[A-Z]") || Regex.IsMatch(urlLowercase, @"[ÀÈÌÒÙÁÉÍÓÚÂÊÎÔÛÃÕÄËÏÖÜÝÑ]"))
            {
                //You don't want to change casing on query strings
                urlLowercase = urlLowercase.ToLower() + HttpContext.Current.Request.Url.Query;

                Response.Clear();
                Response.Status = "301 Moved Permanently";
                Response.AddHeader("Location", urlLowercase);
                Response.End();
            }
        }
    }
于 2012-07-25T10:02:42.590 に答える
44

以下の 2 つのチュートリアルは、同じことをうまくやりたいと思ったときに役に立ちました。

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);
}
于 2009-05-18T16:39:13.863 に答える
21

UrlHelper を使用してリンクを生成している場合は、アクションとコントローラーの名前を小文字で指定するだけです。

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

結果: /media/photos/delete/64 (コントローラーとアクションはパスカルケースですが)。

于 2009-11-13T20:21:07.777 に答える
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;
    }
}

次にRegisterRoutes、Global.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
    //);
}

ただし、routes.MapRoute を使用する方法を知りたいです...

于 2009-05-31T09:49:01.493 に答える
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
        );
    }
于 2010-06-14T06:46:23.283 に答える
6

これには実際には2つの答えがあります:

  1. これはすでに実行できます。ルート エンジンは大文字と小文字を区別しない比較を行います。小文字のルートを入力すると、適切なコントローラーとアクションにルーティングされます。
  2. ルート リンク (ActionLink、RouteLink など) を生成するコントロールを使用している場合、この既定の動作をオーバーライドしない限り、大文字と小文字が混在するリンクが生成されます。

ただし、アンダースコアについてはあなた自身です...

于 2009-05-18T16:48:14.080 に答える
3

ActionName 属性を使用できますか?

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

 }

大文字小文字は関係ないと思います。URL 内の More_Details、more_DETAILS、mOrE_DeTaILs はすべて、同じコントローラー アクションに移動します。

于 2009-05-18T17:27:56.497 に答える