I ve seen in twitter, i can get a user view page by just typing in the url say http://twitter.com/pandiyachendur. How to do the same with asp.net mvc? I dont know how twitter does it?
You need to be careful about the order in which you declare your routes. Since there is no common element to a /{username} URL, you need to declare it as the last 'catch-all' route, after all of your specific routes.
RouteTable.Routes.MapRoute(null, "LogIn", new { controller = "Account", action = "LogIn" });
RouteTable.Routes.MapRoute(null, "LogOut", new { controller = "Account", action = "LogOut" });
// ... other routes go here ...
// Final catch-all route to map /{username} to the Account.Details action.
RouteTable.Routes.MapRoute(null, "{id}", new { controller = "Account", action = "Details" });
It's also worth remembering that you need to extend your validation on usernames to prevent people from choosing names that conflict with the specific routes (e.g. LogIn).
I imagine that they have some regular exception that checks the request to see if it matches something that could be a user's profile and then push that request to an appropriate controller action.
They'd likely might list first all of the exceptions are static routes, like "/invitations", and then pass everything else to a default controller action that attempts to display a user's page.
Related
My ASP.NET MVC site allows users to register and give themselves user names, which will be unique and allow others to browse their pages with a clean URL that includes their name, like Twitter, Facebook, LinkedIn etc. do.
For example:
mysite.com/michael.guthrie
mysite.com/john
mysite.com/john/images
mysite.com/john/blog
etc.
The problem is that the first URL segment might be used for other "regular" controllers/actions, like:
mysite.com/about
mysite.com/register
So basically I seek for a routing scheme that says something like: If the first URL segment is a known controller, treat it as a controller (and parse the relevant action and parameters as usual), but if not - treat it as a user name, and pass it to a dedicated controller+action which will parse it and continue accordingly.
I don't want a solution that will enforce me to add routes for every specific controller that I have, such that after the routing module will go over all of them and won't find a match, it will get to the last one which defines a route for this special user name segment. The reason is primarily maintenance (I must remember to add a route every time I code a new controller, for example.)
I assume I can implement my own MvcRouteHandler / IRouteHandler but I feel there must be simpler solution that won't have me tweak MVC's out-of-the-box routing mechanism.
Note: I've read How to achieve nice litle USER page url like facebook or twitter? and it doesn't answer my question, it's just says that there is a URL rewriting module.
Do you know any good, elegant, clean way to achieve that?
You should have your first route be your Usesr route, with a route constraint along the lines of what I described in this answer: MVC routing question.
If your route is in the form {username}/{controller}/{id}, this route should cover all contingencies.
in the global.asax file you can map your routes
in the registerRoutes() method you can do something like this:
routes.MapRoute(
"ToonStudenten", // Route name
"{controller}/{action}/{userID}, // URL with parameters
new { controller = "Docent", action = "ToonStudenten", userID = UrlParameter.Optional} // Parameter defaults
);
I believe you can change the way your views look with this mapRouting, not entirely sure how though.. will try and search it up
You may want to take a look at this post:
MVC 3 keeping short url
You don't need to set a route for each URL. With a little help from route constraints you can do something like this:
routes.MapRoute(
"Home", // Route name
"{action}", // URL with parameters
new { controller = "Home", action = "Index" }, // Parameter defaults
new { action = "TaskA|TaskB|TaskC|etc" } //Route constraints
);
routes.MapRoute(
"Account", // Route name
"{action}", // URL with parameters
new { controller = "Account", action = "Logon" }, // Parameter defaults
new { action = "Logon|Logoff|Profile|FAQs|etc" } //Route constraints
);
I have a route setting for Profile controller
In order to view the profile page like http://localhost/Profile/MyUserName
routes.MapRoute("Profile", "Profile/{userName}", new { controller = "Profile", action = "Index", userName = "" });
These works fine.
My problem is that because the profile controller has many actions
Like... Profile/Edit,
Profile/Save,
Profile/Updates,
Profile/etc.... so on..
All of these actions got hit in the route "Profile/{userName}".
In order to fix it i have to map all of these actions in the route table which is very ugly bec. i only want to map the route "Profile/{username}"
Is there a way that i can map only 1 route to profile controller and the rest i dont care about their url format?
im using mvc 1
Instead Profile/{userName} I'm using Profile/View/{userName}. In this way I avoid case, when username is Edit or Save.
I am still very new to routing with asp.net mvc, so perhaps this is obvious and I am just missing the answer...
I have a controller named 'pages', and it has several action results, 'Information', 'History' etc. Each action result takes a string, and from that, it returns a View based on the name of the string. So...
Pages/Information/About
Pages/Information/Products
Pages/History/Employees
etc. The Controller is named 'Pages', of course. I'm wondering if I can use Routing to remove the 'Pages' part of the URL on the user side, just for a more user-friendly approach?
Yep you can do that:
context.MapRoute(
"Pages_History_Employees",
"History/Employees", // URL with parameters
new { controller = "Pages", action = "History" }
);
Just specify the controller as Pages and specify whatever url you want as the second parameter. What this is saying is I want to route the History/Employees URI to the Pages controller and use the History action to handle this route.
Just be careful that if you have the default MVC route in there that it appears at the end of your routes or it will match this route first. Then you will get an error since it will be looking for the History controller with the Employees action.
I have my default route defined like this
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
However if the user is logged in when they visit the site (This can happen if they ticked the remember me button last time the logged in) I want them to take a different default route and go straight to the logged in page.
Is this possible in global.asax or will I need to put some logic in my home controller to redirect if logged in?
Best to put this in the home controller. A check if authenticated and return the appropriate view.
I want them to take a different default routeRouting in ASP.NET MVC is about routing URLs to action methods on controllers, not about routing users to places in your web site depending on the current circumstances. (Think of routing as a static thing, whereas the rest (authorization, redirection, etc) is only applicable to the current session.)
It is possible to use Routing Constraints to achieve what you want, but I don't think that's what you want.
Most of our projects are short term and of a promotional nature. As a result, our clients often want to put up some sort of "end of program" or "expired" page when the promotion is over. How do I do a blanket redirect of all controller actions to one specific controller action without modifying each controller and its methods? Is this even possible?
Ideally, in pseudocode, I'd like to be able to do something like this:
// somewhere in global.asax
if (current_action_url != desired_action_url)
redirect to desired_action_url
I tried doing simple string matching on the URL:
if (!Request.Url.AbsolutePath.ToLower().EndsWith("path/to/desired/page"))
Response.Redirect("path/to/desired/page");
However, since I'm still using IE 6 and have to use the wildcard hack, IE was redirecting all requests to the page (even images and stylesheets) which messes things up pretty badly.
How about using routes? Define routes that are for valid promos, the catch all can go to the generic "promo expired" page
routes.MapRoute(
"PromoStillGoing",
"path/to/PromoStillGoing/{action}",
new { controller = "PromoStillGoing", action = "Index" });
routes.MapRoute("Catch All", "{*path}", new { controller = "ExpiredPromos", action = "Index" });
The above will do one page for all expired promos, not sure by your question if that is what you want.
If you want to have one expired page per promo, then in the routes you can "ignore" the action in the requested url like
routes.MapRoute(
"ExpiredPromoName",
"path/to/PromoName/",
new { controller = "PromoName", action = "Index" });
Now anything under /path/to/PromoName will use the Index action of the PromoNameController