patterncsharpMinor
Custom route for writing friendly URLs in ASP.NET MVC 3
Viewed 0 times
routemvcwritingcustomnetforaspfriendlyurls
Problem
I'm trying to build friendly URLs like
which were processed by this route:
When I create my view model, I would give it an
Then I felt like I didn't want to manage
```
public class NiceNameRoute : RouteBase
{
private IUrlNiceNames UrlNiceNames { get; set; }
private string UrlPrefix { get { return "post/"; } }
public NiceNameRoute(IUrlNiceNames urlNiceNames)
{
UrlNiceNames = urlNiceNames;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
//match e.g. post/1 or post/1/my-first-post
Regex regex = new Regex(UrlPrefix + "[0-9]+($|/)");
if (regex.Match(requestedURL).Success)
{
//get the start of the post id
int prefixPos = requestedURL.IndexOf(UrlPrefix, StringComparison.OrdinalIgnoreCase);
int startIdPos = prefixPos + UrlPrefix.Length;
//get the end of the post id
int endIdPos = requestedURL.IndexOf("/", startIdPos, StringComparison.OrdinalIgnoreCase);
endIdPos = endIdPos == -1 ? requestedURL.Length : endIdPos;
//get post id
string id = requestedURL.Substring(startIdPos, endIdPos - startIdPos
/post/1/my-first-post. I started out with building my links like this: @Html.ActionLink(Model.BlogPost.Title, "Index", "Post", new
{
id = Model.BlogPost.Id,
title = Model.FriendlyUrl
},
new { })which were processed by this route:
routes.MapRoute(
"Post", // Route name
"posts/{id}/{title}", // URL with parameters
new { controller = "Post", action = "Index" }, // Parameter defaults
new { id = "^[0-9]+$" }
);When I create my view model, I would give it an
IUrlNiceName which it used to create the output of FriendlyUrl:public string FriendlyUrl
{
get{ return UrlNiceName.ConvertToNiceName(BlogPost.Title); }
}Then I felt like I didn't want to manage
UrlNiceName-ing on the controller level so then I build a custom Route to do this for me:```
public class NiceNameRoute : RouteBase
{
private IUrlNiceNames UrlNiceNames { get; set; }
private string UrlPrefix { get { return "post/"; } }
public NiceNameRoute(IUrlNiceNames urlNiceNames)
{
UrlNiceNames = urlNiceNames;
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;
//match e.g. post/1 or post/1/my-first-post
Regex regex = new Regex(UrlPrefix + "[0-9]+($|/)");
if (regex.Match(requestedURL).Success)
{
//get the start of the post id
int prefixPos = requestedURL.IndexOf(UrlPrefix, StringComparison.OrdinalIgnoreCase);
int startIdPos = prefixPos + UrlPrefix.Length;
//get the end of the post id
int endIdPos = requestedURL.IndexOf("/", startIdPos, StringComparison.OrdinalIgnoreCase);
endIdPos = endIdPos == -1 ? requestedURL.Length : endIdPos;
//get post id
string id = requestedURL.Substring(startIdPos, endIdPos - startIdPos
Solution
Personally I think you are over thinking it. Why not just create a string extension method called FriendlyString or PrepareForUrl and then use the original route
@Html.ActionLink(Model.BlogPost.Title, "Index", "Post", new
{
id = Model.BlogPost.Id,
title = Model.BlogPost.Title.FriendlyString()
}, null)Code Snippets
@Html.ActionLink(Model.BlogPost.Title, "Index", "Post", new
{
id = Model.BlogPost.Id,
title = Model.BlogPost.Title.FriendlyString()
}, null)Context
StackExchange Code Review Q#6543, answer score: 8
Revisions (0)
No revisions yet.