2013-03-13 5 views
14

के साथ रूट पैरामीटर्स में केस को संरक्षित करें मैं अपने एमवीसी 4 एप्लिकेशन में routes.LowercaseUrls = true; का उपयोग कर रहा हूं जो बहुत अच्छा काम कर रहा है। हालांकि, पैरामीटर भी लोवरकेस हो जाएगी, इसलिए यदि मैं की तरहलोअरकेस यूआरएल सक्षम

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

लिंक

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

से बनाए गए मार्ग URL के रूप में अच्छी तरह से लोवरकेस की {hash} भाग होगा, उदाहरण यदि ViewBag.MyHash = "aX3F5U" के लिए तो जेनरेट किया गया लिंक /foo/aX3F5U

क्या एमवीसी को केवल नियंत्रक और क्रिया भागों को कम करने के लिए मजबूर करने का कोई तरीका है?

MVC के पुराने संस्करणों के लिए, जिस तरह से Route के एक कस्टम उपवर्ग लागू करने के लिए लग रहा था जाने के लिए, लेकिन मैं कैसे/जहां यह दृष्टांत है, क्योंकि मार्ग कंस्ट्रक्टर्स के हस्ताक्षर MapRoute को काफी अलग है पता नहीं है और मैं उम्मीद कर रहा हूं कि एक आसान तरीका बनें।

+0

क्या आप अपने मार्गों का एक उदाहरण जोड़ सकते हैं जिन्हें आप प्राप्त करना चाहते हैं? – IamStalker

+0

ने एक उदाहरण जोड़ा – mensi

उत्तर

2

मुझे लगता है कि Route के एक कस्टम उपवर्ग के साथ समाधान के लिए पर्याप्त और सरल एक अच्छा हो जाएगा, लेकिन एक ही समय एक छोटा सा बदसूरत :)

पर आप RouteConfig.cs की RegisterRoute विधि पर एक 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 निम्न कोड जोड़ें इस तरह लग सकता है।

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 कक्षा: एक पूरा उदाहरण यह अधिक से अधिक निकट मूल routes.MapRoute(...) वाक्य रचना करने के लिए रखने के लिए RouteCollection और एक कस्टम Route बच्चे पर एक्सटेंशन के संयोजन का उपयोग कर सकता है

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 इंस्टी का उपयोग कर सकते हैं 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

मैंने अपने समाधान को शामिल करने के लिए अपना जवाब बढ़ाया, जैसा कि [जेफ एटवुड पर मेटा] द्वारा सुझाया गया है (http://meta.stackexchange.com/questions/27254/सर्वोत्तम-मार्ग-से-पुरस्कार-क्रेडिट-कब-समाधान-आधारित-पर-दूसरे-उत्तर) – mensi

-1

यह 1.2.3 के रूप में आसान है, इस उदाहरण

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

यह Nuget के माध्यम से डाउनलोड करने और इसे स्थापित करने में आसान है पर

देखो, मैं इसे का उपयोग करें। PM> Install-Package LowercaseRoutesMVC

http://lowercaseroutesmvc.codeplex.com/

+0

स्रोत कोड को देखते हुए ऐसा लगता है कि यह केवल लोअरकेस के पथ को भी परिवर्तित करता है ... – mensi

+0

हाँप केवल LowerCaseRoutesMvc डाउनलोड करें और बस। – IamStalker

0

आप निजी RouteCollection.NormalizeVirtualPath विधि को देखें, तो आपको लगता है कि यह बस virtualPath.ToLowerInvariant() का उपयोग करता दिखाई देगा। तो इसे संभालने का कोई तरीका नहीं है। भले ही आप अपना रास्ता बनाते हैं, यह कम हो जाएगा।

लेकिन आप क्या कर सकते हैं '#' चिह्न के बाद हैश जोड़ने के लिए i.e. "foo/{action}/#{hash}"। मेरे पास नहीं है, लेकिन इसे काम करना चाहिए। बस NormalizeVirtualPath कार्यान्वयन देखें।

+0

काम नहीं करता है (404 उत्पन्न करता है), आपको 'System.Web.Routing' का स्रोत कोड कहां मिला? – mensi

+0

मैंने इसे रिशेर्पर के साथ देखा। मुझे यकीन नहीं है कि मैं इसे यहां पेस्ट कर सकता हूं। आप जेटब्रेन से डॉटपीक का उपयोग कर सकते हैं - यह मुफ़्त नहीं है। क्वेरी पैरामीटर के रूप में हैश को भी आज़माएं, यानी 'foo /? Myhash = aX3F5U'। मुझे यकीन है कि यह काम करेगा। –

+0

और आपको 404 मिल सकते हैं क्योंकि आपको नए यूआरएल पैटर्न को समझने के लिए अपना रास्ता बदलना चाहिए: '" foo/{action} "' –

2

यहाँ यह करने के लिए एक आसान तरीका,

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 देखें है।

संबंधित मुद्दे