I have registered the following SEO friendly route:
A path segment that contains more than one section, such as a literal section or a parameter, cannot contain a catch-all parameter.Parameter name: routeUrl
Anyone an idea how to fix this problem? Returning a 404 is not a nice UX when (in our case) only the id really matters ...
But it is not really a solution for our project. To give you some background see thread:
http://forums.asp.net/p/1535567/3775048.aspx We use T4MVC to create links to our controllers.
We also only like to define the format of the urls in the routes. This combo, T4MVC and mapped routes is very powerfull and causes very less friction in every day programming of our team. No need to remember how urls are assembled or how they will be in the
future.
With Haack's solution we will loose the automatic coupling of T4MVC and the mapped routes ...
Having said that I think its a little bug in the route mapper. Ofcourse I cannot oversee all of the problems it has to deal with, but it seems to use a greedy regex instead of a non-greedy one to match the routes.
See this regex
Match m = Regex.Match(@"/pr-123-this-is-a-slug", @"/pr\-(?<id>.+)\-(?<slug>.+)")
Console.WriteLine("id:{0} slug:{1}", m.Groups["id"], m.Groups["slug"]);
Prints: id:123-this-is-a slug:slug
That is exactly what I see happening when I remove the integer constraint.
When I add the integer constraint to the regex:
Match m = Regex.Match(@"/pr-123-this-is-a-slug", @"/pr\-(?<id>\d+)\-(?<slug>.+?)")
Console.WriteLine("id:{0} slug:{1}", m.Groups["id"], m.Groups["slug"]);
Prints: id:123 slug:this-is-a-slug
It happily can match the url with no problem at all but maybe the constraint is not used for matching the url thus we need a non greedy version:
Match m = Regex.Match(@"/pr-123-this-is-a-slug", @"/pr\-(?<id>.+?)\-(?<slug>.+)")
Console.WriteLine("id:{0} slug:{1}", m.Groups["id"], m.Groups["slug"]);
Prints: id:123 slug:this-is-a-slug
Which is correct to match with the action and its constraints for its parameters.
It works fine, but when {slug} contains a - it will not match this route.
I think Routing will confuse if you use - literal as seprator and as charector in slug.
A quick way to solve this is to replce - in slug with any different charactor before routing come into the action, for example
string A(Match m)
{
return m.Groups["s1"].Value + "pr-" +m.Groups["s"].Value + "-"+m.Groups["slug"].Value.Replace("-","`") +m.Groups["s2"].Value;
}
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
if (app != null)
{
if (app.Request.AppRelativeCurrentExecutionFilePath.Contains("pr-"))
{
string s = Regex.Replace(app.Request.Url.PathAndQuery, "(?<s1>.*?)pr-(?<s>[0-9]+)-(?<slug>[^?]*)(?<s2>.*)", new MatchEvaluator(A));
app.Context.RewritePath(
s
);
}
}
}
this will replace - with ` in slug route
"And whoever is removed away from the Fire and admitted to Paradise, he indeed is successful." (The Holy Quran)
Excellent Windows VPS Hosting Imran Baloch MVP, MVB, MCP, MCTS, MCPD
Qty
Member
135 Points
35 Posts
MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 15, 2010 01:03 PM|LINK
I have registered the following SEO friendly route:
Anyone an idea how to fix this problem? Returning a 404 is not a nice UX when (in our case) only the id really matters ...
MapRoute PathSeparator
ignatandrei
All-Star
135231 Points
21695 Posts
Moderator
MVP
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 15, 2010 03:14 PM|LINK
please see ActionFilter from
Manipulating Action Method Parameters
http://haacked.com/archive/2010/02/21/manipulating-action-method-parameters.aspx
Qty
Member
135 Points
35 Posts
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 15, 2010 03:46 PM|LINK
I have read that article before, but please note, I have both id and slug at the url.
I do not need to convert the slug into an id, since the id is there in the url.
ignatandrei
All-Star
135231 Points
21695 Posts
Moderator
MVP
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 15, 2010 03:59 PM|LINK
Yes, that what he have too
Note that
1. The url has a slug and a ID
2. The action method has the parameter just id
3. The action filter has a method that adds the id from the slug ( Slugs.TryGetValue(slug, out id); )
Qty
Member
135 Points
35 Posts
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 15, 2010 05:29 PM|LINK
Let me restate the problem:
this is the route
When I remove the (integer) constraint, id matches to "123-this-is-a" ...
Hope this clearifies the problem a bit more ...
ignatandrei
All-Star
135231 Points
21695 Posts
Moderator
MVP
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 15, 2010 07:00 PM|LINK
Let me restate the Haack solution :
define
this matches either
/pr-123-this_is_a_slug
either
/pr-123-this-is-a-slug
2. In controller Product define a ActionResult ItemSlug(long id)
3. In order to have id from slug, define the ActionFilter and match the id from
pr-123-this_is_a_slug
or from
pr-123-this-is-a-slug
(regex maybe ?)
Qty
Member
135 Points
35 Posts
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 16, 2010 09:32 AM|LINK
I see what you are aiming at ...
But it is not really a solution for our project. To give you some background see thread: http://forums.asp.net/p/1535567/3775048.aspx We use T4MVC to create links to our controllers.
We also only like to define the format of the urls in the routes. This combo, T4MVC and mapped routes is very powerfull and causes very less friction in every day programming of our team. No need to remember how urls are assembled or how they will be in the future.
With Haack's solution we will loose the automatic coupling of T4MVC and the mapped routes ...
Having said that I think its a little bug in the route mapper. Ofcourse I cannot oversee all of the problems it has to deal with, but it seems to use a greedy regex instead of a non-greedy one to match the routes.
See this regex
Match m = Regex.Match(@"/pr-123-this-is-a-slug", @"/pr\-(?<id>.+)\-(?<slug>.+)") Console.WriteLine("id:{0} slug:{1}", m.Groups["id"], m.Groups["slug"]);Prints: id:123-this-is-a slug:slug
That is exactly what I see happening when I remove the integer constraint.
When I add the integer constraint to the regex:
Match m = Regex.Match(@"/pr-123-this-is-a-slug", @"/pr\-(?<id>\d+)\-(?<slug>.+?)") Console.WriteLine("id:{0} slug:{1}", m.Groups["id"], m.Groups["slug"]);Prints: id:123 slug:this-is-a-slug
It happily can match the url with no problem at all but maybe the constraint is not used for matching the url thus we need a non greedy version:
Match m = Regex.Match(@"/pr-123-this-is-a-slug", @"/pr\-(?<id>.+?)\-(?<slug>.+)") Console.WriteLine("id:{0} slug:{1}", m.Groups["id"], m.Groups["slug"]);Prints: id:123 slug:this-is-a-slug
Which is correct to match with the action and its constraints for its parameters.
<div></div> <div></div>imran_ku07
All-Star
45815 Points
7698 Posts
MVP
Re: MapRoute does not match other '-'s when '-' is used as a 'path separator'
Apr 16, 2010 11:10 AM|LINK
I think Routing will confuse if you use - literal as seprator and as charector in slug.
A quick way to solve this is to replce - in slug with any different charactor before routing come into the action, for example
string A(Match m)
{
return m.Groups["s1"].Value + "pr-" +m.Groups["s"].Value + "-"+m.Groups["slug"].Value.Replace("-","`") +m.Groups["s2"].Value;
}
protected void Application_BeginRequest(Object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
if (app != null)
{
if (app.Request.AppRelativeCurrentExecutionFilePath.Contains("pr-"))
{
string s = Regex.Replace(app.Request.Url.PathAndQuery, "(?<s1>.*?)pr-(?<s>[0-9]+)-(?<slug>[^?]*)(?<s2>.*)", new MatchEvaluator(A));
app.Context.RewritePath(
s
);
}
}
}
this will replace - with ` in slug route
Excellent Windows VPS Hosting
Imran Baloch MVP, MVB, MCP, MCTS, MCPD