2013-03-13 10 views
14

私はMVC 4アプリケーションでroutes.LowercaseUrls = true;を使用しています。しかし、私はLowercaseUrlsを有効にしてルートパラメータの大文字小文字を維持する

routes.MapRoute(
    name: "MyController", 
    url: "foo/{hash}/{action}", 
    defaults: new { controller = "MyController", action = "Details" } 
); 

のようなルートを持っている場合ViewBag.MyHash = "aX3F5U"場合

@Html.ActionLink("my link", "Details", new { hash=ViewBag.MyHash }) 

で生成されたリンクは、例えば、同様に小文字URLの{hash} -partを持つことになりますので、パラメータはまた、小文字れます生成されたリンクは/foo/aX3F5Uの代わりに/foo/ax3f5uになります

MVCにコントローラとアクションの部分のみを強制的に割り当てる方法はありますか?

古いバージョンのMVCの場合、Routeのカスタムサブクラスを実装するように見えましたが、ルートコンストラクタのシグニチャがMapRouteとはかなり異なるため、どのように/インスタンス化するのかわかりませんもっと簡単な方法があることを願っています。

+0

入手したいルートの例を追加できますか? – IamStalker

+0

例を追加しました – mensi

答えて

2

私はRouteのカスタムサブクラスを持つソリューションが十分に良いとシンプルですが、同時に少し醜いになると思う:)

あなたはRouteConfig.csRegisterRoute方法でCustomRouteを追加することができます。それが最適なインプリメンテーションではありませんしかし

public class CustomRoute : RouteBase 
{ 
    private readonly RouteBase route; 

    public CustomRoute(RouteBase route) 
    { 
    this.route = route; 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
    values = new RouteValueDictionary(values.Select(v => 
    { 
     return v.Key.Equals("action") || v.Key.Equals("controller") 
     ? new KeyValuePair<String, Object>(v.Key, (v.Value as String).ToLower()) 
     : v; 
    }).ToDictionary(v => v.Key, v => v.Value)); 

    return route.GetVirtualPath(requestContext, values); 
    } 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
    return route.GetRouteData(httpContext); 
    } 
} 

CustomRoute特定の代わりのroutes.MapRoute

var route = new CustomRoute(new Route(
    url: "{controller}/{action}/{id}", 
    defaults: new RouteValueDictionary() { 
    { "controller", "Home" }, 
    { "action", "Index" }, 
    { "id", UrlParameter.Optional } 
    }, 
    routeHandler: new MvcRouteHandler() 
)); 
routes.Add(route); 

Implementaionはこのように見えるかもしれ次のコードを追加します。完全な例は、元routes.MapRoute(...)構文にできるだけ近いそれを維持するためにRouteCollectionとカスタムRoute子に拡張子の組み合わせを使用することができます:

LowercaseRouteクラス:

public class LowercaseRoute : Route 
{ 
    public LowercaseRoute(string url, IRouteHandler routeHandler) : base(url, routeHandler) { } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     values = new RouteValueDictionary(values.Select(v => 
     { 
      return v.Key.Equals("action") || v.Key.Equals("controller") 
       ? new KeyValuePair<String, Object>(v.Key, (v.Value as String).ToLower()) 
       : v; 
     }).ToDictionary(v => v.Key, v => v.Value)); 

     return base.GetVirtualPath(requestContext, values); 
    } 
} 

RouteCollectionExtensionsクラス:

public static class RouteCollectionExtensions 
{ 
    [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] 
    public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url) 
    { 
     return MapLowercaseRoute(routes, name, url, null /* defaults */, (object)null /* constraints */); 
    } 

    [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] 
    public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults) 
    { 
     return MapLowercaseRoute(routes, name, url, defaults, (object)null /* constraints */); 
    } 

    [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] 
    public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults, object constraints) 
    { 
     return MapLowercaseRoute(routes, name, url, defaults, constraints, null /* namespaces */); 
    } 

    [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] 
    public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, string[] namespaces) 
    { 
     return MapLowercaseRoute(routes, name, url, null /* defaults */, null /* constraints */, namespaces); 
    } 

    [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] 
    public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces) 
    { 
     return MapLowercaseRoute(routes, name, url, defaults, null /* constraints */, namespaces); 
    } 

    [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "2#", Justification = "This is not a regular URL as it may contain special routing characters.")] 
    public static Route MapLowercaseRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) 
    { 
     if (routes == null) 
     { 
      throw new ArgumentNullException("routes"); 
     } 
     if (url == null) 
     { 
      throw new ArgumentNullException("url"); 
     } 

     Route route = new LowercaseRoute(url, new MvcRouteHandler()) 
     { 
      Defaults = CreateRouteValueDictionary(defaults), 
      Constraints = CreateRouteValueDictionary(constraints), 
      DataTokens = new RouteValueDictionary() 
     }; 

     if ((namespaces != null) && (namespaces.Length > 0)) 
     { 
      route.DataTokens["Namespaces"] = namespaces; 
     } 

     routes.Add(name, route); 

     return route; 
    } 

    private static RouteValueDictionary CreateRouteValueDictionary(object values) 
    { 
     var dictionary = values as IDictionary<string, object>; 
     if (dictionary != null) 
     { 
      return new RouteValueDictionary(dictionary); 
     } 

     return new RouteValueDictionary(values); 
    } 
} 

MapLowercaseRoute inste MapRouteの広告、そう

routes.MapRoute(
    name: "MyController", 
    url: "foo/{hash}/{action}", 
    defaults: new { controller = "MyController", action = "Details" } 
); 

は、単に、所望の動作を露出

routes.MapLowercaseRoute(
    name: "MyController", 
    url: "foo/{hash}/{action}", 
    defaults: new { controller = "MyController", action = "Details" } 
); 

なります。

+0

継承の代わりに合成を使用する特別な理由はありますか? – mensi

+0

私はこの特定のケースではないと思います。しかし、私は構成が高い柔軟性を与えると信じていますが、それはやや主観的です:) – user20140268

+1

[Jeff Atwood on meta](http://meta.stackexchange.com/questions/27254 /ベスト・ウェイ・ツー・ポイント・クレジット - 解決策は別の答えに基づいて) – mensi

-1

それは私がそれを使用し、Nuget経由でダウンロードしてインストールするのは簡単です。この例を見

routes.MapRouteLowercase(// changed from routes.MapRoute 
     "Default", 
     "{controller}/{action}/{id}", 
     new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
    ); 

、1.2.3とそれは簡単です。 PM> Install-Package LowercaseRoutesMVC

http://lowercaseroutesmvc.codeplex.com/

+0

ソースコードを見ると、パスを小文字に変換するように見えます... – mensi

+0

YepperはただLowerCaseRoutesMvc以上です。 – IamStalker

0

あなたはプライベートRouteCollection.NormalizeVirtualPath方法を見れば、あなたはそれが単にvirtualPath.ToLowerInvariant()を使用していることがわかります。だから、それを処理する方法はありません。独自のルートを作成しても、小文字になります。

しかし、「#」記号の後にハッシュを追加すると、"foo/{action}/#{hash}"となります。私は しようとしていないが、それは動作するはずです。ちょうどNormalizeVirtualPathの実装を見てください。ここで

+0

'System.Web.Routing'のソースコードはどこで見つけましたか? – mensi

+0

私はResharperとそれを見ました。ここに貼り付けることができるかどうかはわかりません。 JetBrainsのdotPeekを使うことができます。無料です。クエリのパラメータとして 'foo /?myhash = aX3F5U'というハッシュも試してください。私はこれが動作すると確信しています。 –

+0

また、新しいURLパターンを理解するために経路を変更する必要があるので、404が得られるかもしれません: '' foo/{action} '' –

2

は、これを行うための1つの簡単な方法で、

public class MyRoute : Route 
{ 
    public MyRoute(string url, object defaults): base(url, new RouteValueDictionary(defaults), new MvcRouteHandler()) 
    { 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     if (values["action"] != null) 
      values["action"] = values["action"].ToString().ToLowerInvariant(); 
     if (values["controller"] != null) 
      values["controller"] = values["controller"].ToString().ToLowerInvariant(); 
     return base.GetVirtualPath(requestContext, values); 
    } 
} 

routes.Add("Default",new MyRoute("{controller}/{action}/{id}", 
       new { controller = "Home", action = "Index", id = MyUrlParameter.Optional })); 

は、詳細はthis blog postを参照してください。

関連する問題