HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Custom route for writing friendly URLs in ASP.NET MVC 3

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
routemvcwritingcustomnetforaspfriendlyurls

Problem

I'm trying to build friendly URLs like /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.