views:

594

answers:

3

My goal is to have the url routing as following:

http://www.abc.com/this-is-peter-page

http://www.abc.com/this-is-john-page

What is the simplest way to achieve this without placing controller name an function name in the url above? If page above not found, I should redirect to 404 page.

Addon 1: this-is-peter-page and this-is-john-page is not static content, but is from database.

+4  A: 

I personally wouldn't suggest a route like that but if it meets your needs you need to do something like:

Have the following route in your Global.asax file:

    routes.MapRoute(
       "NameRouting",
       "{name}",
       new { controller = "PersonalPage", action = "routeByName" });

Then, in your "PersonalPageController", have the following method:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult routeByName(string name)
    {
         switch (name)
         {
             case "this-is-peter-page": return View("PeterView");
             case "this-is-john-page": return View("JohnView");
             case Default: return View("NotFound");
         }
    }

Make sure you have the appropriate views: "PeterView", "JohnView" and "NotFound" in your Views/PersonalPage/.

KingNestor
You could combine that with a route constraint to prevent 'unwanted' requests to go to that controller. (I assume that you still need some other controller)
chris166
how to prevent 'unwanted' request?
Ervin Ter
@Ervin Ter, you can provide route constraints that constrain this route to a particular regular expression.
Simucal
@Simucal, I see. Never know that we can plant regular expression on route.
Ervin Ter
+1  A: 

I don't think this can be done. AFAIK ASP.NET MVC recognizes routing parameters via the character "/".

Your format, on the other hand, goes by "{controller}-is-{id}-{action}" -- so there is no way the controller can be distinguished from the id and the action.

I think using "/" characters doesn't affect or degrade SEO; it only affects human readability and retention of the URL.

Anyway, the following URL is possible: http://www.abc.com/this-is-the-page-of/Peter by adding another route in the Global.asax RegisterRoutes method:

        routes.MapRoute(
            "AnotherRoute",
            "this-is-the-page-of/{id}",
            new { controller = "PersonalPage", action = "Details", id = "" }
        );

...assuming that PersonalPageController implements a Details ActionResult method that points to the desired page.

Jon Limjap
+7  A: 

Similar to KingNestor's implementation, you can also do the followings which will ease your work:

1) Write Your Model

public class MyUser{public String UserName{get; set;}}

2) add route to global asax

routes.MapRoute(
   "NameRouting",
   "{name}",
   new { controller = "PersonalPage", action = "Index", username="name" });

3) Roll your own custom model binder derived from IModelBinder

public class CustomBinder : IModelBinder
    {
       public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
       {
          var request = controllerContext.HttpContext.Request;
          var username = getUserNameFromDashedString(request["username"]);
          MyUser user = new MyUser(username);

          return user;
       }
    }

4) in your action:

public ActionResult Index([ModelBinder(typeof(CustomBinder))] MyUser usr)
{
    ViewData["Welcome"] = "Viewing " + usr.Username;
    return View();
}
ercu
yes, thanks for this addon to KingNestor's implementation
Ervin Ter
Thanks to Zhaph for re-arrange step 3 and step 4
Ervin Ter
I found bindingContext doesn't containing HttpContext
Ervin Ter
updated the code to get HttpContext.
ercu
that is great. Thanks.
Ervin Ter