12

I need to implement SO like functionality on my asp.net MVC site.

For example when user go to https://stackoverflow.com/questions/xxxxxxxx

after loading the subject line is concatenated with the url and url becomes like this https://stackoverflow.com/questions/xxxxxxxx/rails-sql-search-through-has-one-relationship

Above "/rails-sql-search-through-has-one-relationship " part is added to the url.

In webforms it's simple, I could just use url rewriting. But not sure how to accomplish this in MVC

The following line is from Global.asax file

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Account", action = "LogOn", id = UrlParameter.Optional } // Parameter defaults
);

the string that I need to concatenate is in my database so it fetches from there. How can I accomplish this?

wohlstad
  • 12,661
  • 10
  • 26
  • 39
user786
  • 3,902
  • 4
  • 40
  • 72
  • 6
    This is called a slug. [Refer this blog](http://haacked.com/archive/2010/02/21/manipulating-action-method-parameters.aspx/) for an example of creating one using an action filter –  May 20 '15 at 12:25
  • @StephenMuecke thanks. can you answer it? – user786 May 20 '15 at 12:26
  • 1
    It late - will have to wait until tomorrow :) –  May 20 '15 at 12:40
  • ok,no problem until then I try to figure out. but please don't forget – user786 May 20 '15 at 12:41

2 Answers2

9

This is called a slug route. One way to achieve this is to define a route with an optional slug parameter, and in the controller method check if the parameter has been provided

routes.MapRoute(
    name: "Question",
    url: "Question/{id}/{slug}",
    defaults: new { controller = "Question", action = "Details", slug = UrlParameter.Optional }
);

Then in QuestionController (assumes an id will always be provided)

public ActionResult Details (int id, string slug)
{
    if (string.IsNullOrEmpty(slug))
    {
        // Look up the slug in the database based on the id, but for testing
        slug = "this-is-a-slug";
        return RedirectToAction("Details", new { id = id, slug = slug });
    }
    var model = db.Questions.Find(id);
    return View(model);
}
  • I am passing it this url:http://localhost:58988/question/1/aa-aa and it's giving me resource not found page. do you know why is that? – user786 May 21 '15 at 09:14
  • neither the MapRoute function is getting hit when I initialte the request by setting break point – user786 May 21 '15 at 09:26
  • and when I go to http://localhost:58988/question/0/fawad. it says "The view 'fawad' or its master was not found or no view engine supports the searched locations. The following locations were searched:" – user786 May 21 '15 at 09:31
  • Sounds like a issue with the order of the routes. The route I showed should be the first (before the default route) –  May 21 '15 at 09:33
  • ok it working now. But I am returning view() instead of view(model). if I use view(model) it throws "The view 'fawad' or its master was not found or no view engine supports the searched locations. The following locations were searched:" – user786 May 21 '15 at 09:38
  • That would happen if the value of `model` in my code above was the string "fawad". Are your setting `model = slug;`? Without seeing the actual code your using its a bit hard to be sure –  May 21 '15 at 09:43
  • Also just noticed I had a typo - in the `return RedirectToAction()` line - see edit –  May 21 '15 at 09:44
  • actually fawad is the name of one of the views in my application. do u think it may be causing problem? – user786 May 21 '15 at 09:54
  • Your going to need to ask a new question with the actual code your using. I'm also not sure why you navigating to `../question/0/fawad`? I thought you wanted to navigate to `../question/0` and have it automatically add the slug to it. I don't know what `fawad` is or means, put it could be that you need to replace `Details` with `fawad` in both the route (`action = "fawad"`) and the controller (`public ActionResult fawad (int id, string slug)`? - but that's just a wild guess –  May 21 '15 at 10:04
  • I think its best if you copy my code exactly as it is (add the route as the first route) and create a `QuestionController` and copy the `Details` method into it then create a `Details.cshtml` view to see how it works –  May 21 '15 at 10:07
  • But it's working. All I had to do is to remove model from return view(model). – user786 May 21 '15 at 10:21
  • can you please answer my new question related to mvc client side?http://stackoverflow.com/questions/30391510/how-to-embed-javascript-in-asp-net-mvc-view – user786 May 22 '15 at 08:25
  • I have asked a new question related to MVC. can you please answer it?http://stackoverflow.com/questions/30403386/js-files-are-not-linking-to-asp-net-mvc-view – user786 May 23 '15 at 05:47
  • do you know any good tutorial about mvc 3 and entity framework. I have data in sql server database? – user786 Oct 11 '15 at 10:18
3

You are looking for a custom route. If you look closely, SO doesn't care about the text part of the URL. So:

 http://stackoverflow.com/questions/xxxxxxxx/rails-sql-search-through-has-one-relationship
 AND
 http://stackoverflow.com/questions/xxxxxxxx/

Will both work. You can easily do that with something like:

routes.MapRoute(
    "Question",
    "questions/{id}/{title}",
    new { controller = "Question", action = "Details" });

The trick is add the "slug" at the end when you create links:

@Html.RouteLink(
    "Read more.",
    "Question",
    new { id = question.Id, title = Slugger.ToUrl(question.Title) })
beautifulcoder
  • 10,832
  • 3
  • 19
  • 29
  • what if my application has two type of pages "questions" and "registration". how I can register two different routes in my application? – user786 May 20 '15 at 13:35
  • Not sure I follow, you can register more than one route as long as the names are unique – beautifulcoder May 20 '15 at 15:47