tags:

views:

2416

answers:

6

I am trying to create a route with a Username...

So the URL would be mydomain.com/abrudtkhul (abrudtkhul being the username)

My application will have public profiles based on usernames (Ex: http://delicious.com/abrudtkuhl). I want to replicate this URL scheme.

How can I structure this in ASP.Net MVC? I am using Membership/Roles Providers too.

A: 

You could have a route that looks like:

{username}

with the defaults of

Controller = "Users"

For the finished product of:

    routes.MapRoute(
                    "Users",
                    "{username}",
                    new { controller = "Users" }

So that the Username is the only url parameter, the MVC assumes it passes it to the users controller.

Jason Whitehorn
Okay I had that ... but it's not working for some reason. What do I do about the View?
I would assume they would all have the same view. Your view can be called whatever you want so long as you call the View(string) overload and the View's aspx is in the Users sub directory under Views.
Jason Whitehorn
You also have to specify the action. change the new part to: new { controller = "Users", action = "Show" }or whatever you want to name it
Carlton Jenke
A: 

Are you trying to pass it as a parameter to a Controller?

Theoretically you could do something like this:

routes.MapRoute("name", "{user}/{controller}/{action}", new { controller = "blah", action = "blah", user = "" })

I'm not too experienced with ASP.NET routing, but I figure that should work.

WillCodeForCoffee
A: 
routes.MapRoute(
             "Users",
              "{username}", 
              new { controller = "Users", action="ShowUser", username=""});

Ok, what this will do is default the username parameter to the value of {username}

so even though you've written username="" it'll know to pass the value of {username} .. by virtue of the strings match.

This would expect

for the url form

http://website.com/username

  • Users Contoller
  • ShowUser Action (method in controller)
  • username parameter on the ShowUser action (method)
danswain
+16  A: 

Here's what you want to do, first define your route map:

routes.MapRoute(
             "Users",
              "{username}", 
              new { controller = "User", action="index", username=""});

What this allows you to do is to setup the following convention:

  • Controller: User (the UserController type)
  • Action: Index (this is mapped to the Index method of UserController)
  • Username: This is the parameter for the Index method

So when you request the url ">http://mydomain.com/javier__ this will be translated to the call for UserController.Index(string username) where username is set to the value of javier.

Now since you're planning on using the MembershipProvider classes, you want to something more like this:

 public ActionResult Index(MembershipUser usr)
 {
    ViewData["Welcome"] = "Viewing " + usr.UserName;

    return View();
 }

In order to do this, you will need to use a ModelBinder to do the work of, well, binding from a username to a MembershipUser type. To do this, you will need to create your own ModelBinder type and apply it to the user parameter of the Index method. Your class can look something like this:

public class UserBinder : IModelBinder
{
   public ModelBinderResult BindModel(ModelBindingContext bindingContext)
   {
      var request = bindingContext.HttpContext.Request;
      var username = request["username"];
      MembershipUser user = Membership.GetUser(username);

      return new ModelBinderResult(user);
   }
}

This allows you to change the declaration of the Index method to be:

public ActionResult Index([ModelBinder(typeof(UserBinder))] 
    MembershipUser usr)
{
    ViewData["Welcome"] = "Viewing " + usr.Username;
    return View();
}

As you can see, we've applied the [ModelBinder(typeof(UserBinder))] attribute to the method's parameter. This means that before your method is called the logic of your UserBinder type will be called so by the time the method gets called you will have a valid instance of your MembershipUser type.

Javier Lozano
This has changed in more recent releases of MVC it should now be: object BindModel( ControllerContext controllerContext, ModelBindingContext bindingContext )
Keith
A: 

Is there a way to restrict access to Routes using Active Directory? If not, how can you use AD groups to control access to certain Controllers in your application?

+5  A: 

You might want to consider not allowing usernames of certain types if you want to have some other functional controllers like Account, Admin, Profile, Settings, etc. Also you might want your static content not to trigger the "username" route. In order to achieve that kind of functionality (similar to how twitter urls are processed) you could use the following Routes:

// do not route the following
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("content/{*pathInfo}"); 
routes.IgnoreRoute("images/{*pathInfo}");

// route the following based on the controller constraints
routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    , new { controller = @"(admin|help|profile|settings)" } // Constraints
);

// this will catch the remaining allowed usernames
routes.MapRoute(
    "Users",
    "{username}",
    new { controller = "Users", action = "View", username = "" }
);

Then you will need to have a controller for each of the tokens in the constraint string (e.g. admin, help, profile, settings), as well as a controller named Users, and of course the default controller of Home in this example.

If you have a lot of usernames you don't want to allow, then you might consider a more dynamic approach by creating a custom route handler.

Steve Tranby