ASP.NET MVC Dash Route

I have a question about ASP.NET MVC routing.

I prepared the following routing table to display such a URL

MyWebSite / mycontroller / MyAction / 14-longandprettyseoname

to parameters:

14 => id (integer)

longandprettyseoname β†’ seo_name (string)

routes.MapRoute( "myname", "mycontroller/myaction/{id}-{seo_name}", new { controller = "mycontroller", action = "myaction", id = 0, seo_name = (string)null }); routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" }); 

It works for the URLs above, but it has problems for the following type of URLs

MyWebSite / mycontroller / MyAction / 14-moon-ugly-seo-name and

Is it possible to do this?


EDIT:

"mycontroller/myaction/{seo_name}-{id}"

seems to work

+4
source share
5 answers

I don’t think that the route will be distinguishable, since it will not be able to determine which "-" should be divided into to indicate {id} and {seo-name} .

How about using underscores for your SEO name? Or you can just use the SEO name as the actual {id} . If the SEO name is something that will be unique, this is a very viable option that you can use as the pseudo primary key for this entry in your db (assuming it is pulling something from the database).

Also, use the Fel Haack route debugger to see what works and doesn't work.

0
source

The most obvious way to do this is to use restrictions.

Since your id is an integer, you can add a constraint that will look for an integer value:

 new { id = @"\d+" } 

and here is the whole route:

 routes.MapRoute("myname","mycontroller/myaction/{id}-{seo_name}", new { controller = "mycontroller", action = "myaction" }, new { id = @"\d+"}); 
+1
source

My solution defines the route as:

 routes.MapRoute("myname","mycontroller/myaction/{id}", new { controller = "mycontroller", action = "myaction"}); 

and the syntax identifier and seoname using Regex in the HTTP handler:

  var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(context)); var match = System.Text.RegularExpressions.Regex.Match((string)routeData.Values["id"], @"^(?<id>\d+)-(?<seoname>[\S\s]*)$"); if (!match.Success) { context.Response.StatusCode = 400; context.Response.StatusDescription = "Bad Request"; return; } int id = Int32.Parse(match.Groups["id"].Value); string seoname = match.Groups["seoname"].Value; 
+1
source

What you can do is create a custom factory controller. So you can have your own code to decide which controller to call when.

 public class CustomControllerFactory : IControllerFactory { #region IControllerFactory Members public IController CreateController(RequestContext requestContext, string controllerName) { if (string.IsNullOrEmpty(controllerName)) throw new ArgumentNullException("controllerName"); //string language = requestContext.HttpContext.Request.Headers["Accept-Language"]; //can be used to translate controller name and get correct controller even when url is in foreign language //format controller name controllerName = String.Format("MyNamespace.Controllers.{0}Controller",controllerName.Replace("-","_")); IController controller = Activator.CreateInstance(Type.GetType(controllerName)) as IController; controller.ActionInvoker = new CustomInvoker(); //only when using custominvoker for actionname rewriting return controller; } public void ReleaseController(IController controller) { if (controller is IDisposable) (controller as IDisposable).Dispose(); else controller = null; } #endregion } 

To use this user controller, you must add it to your global.asax file

 protected void Application_Start() { RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(typeof(CustomControllerFactory)); } 

Please note that this only works for the controller, not for actions ... To enable custom rewriting of actions before starting them, use this code:

 public class CustomInvoker : ControllerActionInvoker { #region IActionInvoker Members public override bool InvokeAction(ControllerContext controllerContext, string actionName) { return base.InvokeAction(controllerContext, actionName.Replace("-", "_")); } #endregion } 

I got most of this code from this blog and adjusted it for my needs. In my case, I want the dash to separate the words in the name of my controller, but you cannot create an action with a dash in the name.

Hope this helps!

0
source

Define a specific route, for example:

  routes.MapRoute( "TandC", // Route controllerName "CommonPath/{controller}/Terms-and-Conditions", // URL with parameters new { controller = "Home", action = "Terms_and_Conditions" } // Parameter defaults ); 

But this route must be registered BEFORE your default route.

0
source

All Articles