Enforce Hyphens in .NET MVC 4.0 URL Structure

I’m looking specifically for a way to automatically transfer CamelCase actions and views. That is, I hope that I do not really need to rename my views or add decorators to each ActionResult on the site.

So far I have used routes.MapRouteLowercase , as shown here . This works well for lowercase URL structures, but not for hyphens. So I recently started playing with Canonicalize (install via NuGet), but it also has nothing for hyphens.

I have tried...

routes.Canonicalize().NoWww().Pattern("([a-z0-9])([AZ])", "$1-$2").Lowercase().NoTrailingSlash();

My regex definitely works the way I want to rebuild the url correctly, but these urls are not identified, of course. The file is still ChangePassword.cshtml , for example, so /account/change-password will not indicate this.

By the way, I'm still a little rusty with .NET MVC. I have not used it for a couple of years, and not with version 2.0.

+4
source share
4 answers

This may be a little messy, but if you created a custom HttpHandler and RouteHandler , then this should prevent you from renaming all your views and actions. Your handler can remove the hyphen from the requested action, which will change "change-password" to changepassword, will have the ChangePassword action.

The code is short for brevity, but there are important bits.

 public void ProcessRequest(HttpContext context) { string controllerId = this.requestContext.RouteData.GetRequiredString("controller"); string view = this.requestContext.RouteData.GetRequiredString("action"); view = view.Replace("-", ""); this.requestContext.RouteData.Values["action"] = view; IController controller = null; IControllerFactory factory = null; try { factory = ControllerBuilder.Current.GetControllerFactory(); controller = factory.CreateController(this.requestContext, controllerId); if (controller != null) { controller.Execute(this.requestContext); } } finally { factory.ReleaseController(controller); } } 

I do not know if I performed it in the best way or not, which is more or less taken from the first sample that I came across, I tested the code myself, so it does the right action / presentation and should do the trick.

+3
source

I developed the NuGet open source library for this problem, which implicitly converts EveryMvc / Url to every-mvc / url.

Upper URLs are problematic because cookie paths are case sensitive, most of the Internet is actually case sensitive, while Microsoft technologies handle case-insensitive URLs. ( More on my blog post )

NuGet Package: https://www.nuget.org/packages/LowercaseDashedRoute/

To install it, simply open the NuGet window in Visual Studio by right-clicking Project and choosing NuGet Package Manager, and on the Online tab, enter “String Shaded Route” and it should appear.

Alternatively, you can run this code in the package manager console:

Install-Package LowercaseDashedRoute

After that, you should open App_Start / RouteConfig.cs and comment on the existing route.MapRoute (...) and add instead:

 routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}", new RouteValueDictionary( new { controller = "Home", action = "Index", id = UrlParameter.Optional }), new DashedRouteHandler() ) ); 

What is it. All URLs are lowercase, dotted, and converted implicitly if you do nothing.

Open Source Project Url: https://github.com/AtaS/lowercase-dashed-route

+3
source

Have you tried working with the Rewrite URL package? I think this is pretty much what you are looking for.

http://www.iis.net/download/urlrewrite

Hanselman has a great example of herE:

http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx

Also , why don't you download something like ReSharper or CodeRush and use it to reorganize the Action and Route names? It is REALLY easy and safe.

It would be well spent and much less time to fix the route naming conventions and actions with refactoring hours than all the hours you have already spent to change the routing rules to suit your needs.

Just a thought.

0
source

I tried the solution in the accepted answer above: using the Canonicalize Pattern url strategy, and then adding a custom IRouteHandler, which then returns a custom IHttpHandler. It basically worked. Here is one warning:

With a typical default route {controller}/{action}/{id} , a controller named CatalogController and the action method inside it are as follows:

 ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ } 

I noticed that the requests for "/ catalog / quick-select / 1234" worked fine, but the requests / catalog / quick -select? id = 1234 were 500'ing, because as soon as the action method was called as a result of controller.Execute() , the id parameter was null inside the action method.

I don’t know exactly why this is, but the behavior was as if MVC were not looking for the query string for the values ​​during model binding. So, something in the implementation of ProcessRequest in the accepted answer was twisting the normal model binding process, or at least the query string value provider.

This is a transaction breaker, so I took a look at the standard MVC IHttpHandler (yay open source!): Http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs

I will not pretend that I fully appreciated it, but obviously it does more in its implementation of ProcessRequest than what happens in the accepted answer.

So, if all we really need to do is defish the data from the incoming route data so that MVC can find our controllers / actions, why do we need to implement a whole smelly version of IHttpHandler? We do not do this! Just snatch a dash in the GetHttpHandler DashedRouteHandler method and pass the requestContext into the MvcHandler frame MvcHandler that it can do its 252 lines of magic, and your route handler should not return the second speed of IHttpHandler.

TL: dr; - Here is what I did:

 public class DashedRouteHandler : IRouteHandler { public IHttpHandler GetHttpHandler(RequestContext requestContext) { requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", ""); requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", ""); return new MvcHandler(requestContext); } } 
0
source

Source: https://habr.com/ru/post/1385732/


All Articles