views:

129

answers:

3

I'm building a basic blog application just now, for viewing data I'm just using the default route, i.e. -

routes.MapRoute
(
     "Default", // Route name
     "{controller}/{action}/{id}",
     new { controller = "Blog", action = "Index", id = UrlParameter.Optional } 
);

So that when you go to mysite.com/View/12 it displays the blog with id 12. I want to modify the URLs so that they look as follows: mysite.com/View/2010/06/01/this-is-the-title.

I could have a URL mapping like -

        routes.MapRoute(
            "View",
            "View/{year}/{month}/{day}/{title}",
            new { controller = "Blog", action = "View" }
        );

But then I'm not passing the ID into the Controller action so I would have to search on the date and title which doesn't feel right. On the other hand, if I pass the ID in it will show up in the URL which isn't what I'm aiming for either. Is there any way to redirect to the URL I want in the controller action after passing only the ID in as a paramter, or to pass the ID into the a Map Route but hide it in the URL?

Thanks for your help!

+2  A: 

When you make your Title field in your blog posts, pre-generate the url-safe title and put it in a colunm in the blog table. Then you can select on that, and match the date against the input just to be sure (for duplicates).

Although, Most blogs though are like

/2010/05/31/23343-the-topic-has-the-id-in-it

Aren
This is probably safest. (The date stuff is not necessary, but perhaps you have reasons for that sort of organization.)
Matt Sherman
Some people like descriptive urls.
Aren
Thanks I'll go with this! I'll think about putting the id into the title, though if I was going to do that I might as well just pass the id in as a parameter.
mcfroob
@mcfroob: Yes, a lot of people just do `/23423/id-before-the-topic` I believe this is how wordpress does it.
Aren
+1  A: 

Your URL mapping idea is actually the right thing to do. You can ignore the year/month/day (though make sure you put in URL constraints to match only numbers of the right sizes). So your controller action method might only care about the title, if the title is guaranteed to be unique (via your model constraints). Just make sure that your db indexes the title field for fast searching.

As Aren said, what's common as well is to have a 'slug' field that takes the post title and makes it URL safe and saves it in that state.

If you really want to, you could also use the wildcard mapping (e.g. "blog/{slug*}") which maps will map everything else in the URL as written, not using slashes as delimiters, so blog/2010/02/05/my-title would be passed into an actionmethod as a string parameter that equals "2010/02/05/my-title"

Paul
A: 

I did something like that though I showed IDs in URL. You can check the ID in an action routed from default URL then redirect it to shiny one.

public ActionResult Index(int id)
{
    BlogPost blogPost=blogRepository.GetPost(id);
    TempData["post"]=blogPost;
    //this makes sure post is stored in memory so it doesn't get to database again
    return Redirect("/View/"+blogPost.year+"/"+blogPost.month+"/"+blogPost.day+"/"+blogPost.title);
}

public ActionResult View(int year, int month, int day, string title)
{
    if(TempData["post]"==null)//I assume you will publish links with that URL, so someone can be routed here without redirecting
    {

        BlogPost blogPost=blogRepository.GetPost(title);
        return View(blogPost);
    }
    else 
        return View(TempData["post"]);
}

I think you better publish links with date too, that would make you check date and title for retrieving data but it would look better. Anyway if you just want to go with ID, Redirect and TempData can do the trick.

Ufuk Hacıoğulları