ASP.NET MVC global redirect - asp.net-mvc

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

Related

How do I tell what is part of a route is the controller and what is just a sub folder?

When looking at an MVC page and looking at the form action I can see it is set to:
/admin/WikiAdmin/edit/
So I spent my time looking for a controller called admin. I looked in the routes in the global and nothing was there.
Eventually I found that this url actually maps to the WikiAdmin controller which is confusing. Do does this mean you can have controllers in sub-folders? How does the app know not to forward the request to the admin controller and to actually send it to the WikiAdmin controller?
The admin part of the url is called area. You could read more about areas in this article. And a video here. Basically areas allow you to group multiple controllers sharing some common functionality on the site.
Yes, you can have controllers in sub-folders. With routing it could be a lot of possible URLs.
For example, if you have a route registered as below:
routes.MapRoute(
"admin1",
"admin/{controller}/{action}/",
new { controller = "WikiAdmin", action = "Index"}
);
The url can be /admin/WikiAdmin/Index/ or /admin/WikiAdmin/Edit/ or something else that matches the route. (Assume that there is an Edit action in WikiAdmin controller)
More example, if you have a route registered as below:
routes.MapRoute(
"admin2",
"account/{action}/", //no controller specified in url
new { controller = "WikiAdmin", action = "Index"}
);
Then the url can be /account/Index/ or /account/Edit/ or even /account/. (Because default controller is WikiAdmin and default action is Index)

How can I achieve clean URL routing with custom user ID?

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
);

ASP.NET MVC: Many routes -> always only one controller

I have very simple question. My site, based on ASP.NET MVC, can have many urls, but all of them should bring to the one controller. How to do that?
I suppose I need some magic in Global.asax but I don't know how to create route that will redirect any url to the specific controller.
For example I have url /about, /product/id etc. but all of them should be really bring to the content/show where the parts of url will be recognized and the decision what information to show will be make. It's some like CMS when you cannot define routes in advance. Is this information enough?
Thanks
This sounds like a horrible idea, but, well, if you must;
routes.MapRoute(
"ReallyBadIdea",
"{*url}",
new { controller = "MyFatController", action = "MySingleAction" }
);
This routes everything to a single action in a single controller. There's also {*path} and other URL patterns should you want slightly more flexibility.
Ideally you should try and specific with your routes, for example if you have a URL that is /products/42 and you want it to go to a generic controller you should specify it explicitly like
routes.MapRoute(
"Poducts",
"products/{id}",
new { controller = "Content", action = "Show", id = UrlParameter.Optional }
);
then you would specify another route for something else like /customers/42
routes.MapRoute(
"Customers",
"customers/{id}",
new { controller = "Content", action = "Show", id = UrlParameter.Optional }
);
this may seem a little verbose, and creating a single route might seem cleaner, but the issue a single route is you will never get a 404 and will have to handle such things in code.

Twitter like url routing in asp.net mvc?

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.

Avoiding the Controller with Routing Rules in ASP.NET MVC

I've created a website with ASP.NET MVC. I have a number of static pages that I am currently serving through a single controller called Home. This creates some rather ugly URLs.
example.com/Home/About
example.com/Home/ContactUs
example.com/Home/Features
You get the idea. I'd rather not have to create a controller for each one of these as the actions simply call the View with no model being passed in.
Is there a way to write a routing rule that will remove the controller from the URL? I'd like it to look like:
example.com/About
example.com/ContactUs
example.com/Features
If not, how is this situation normally handled? I imagine I'm not the first person to run in to this.
Here's what I've done previously, using a constraint to make sure the shortcuts don't conflict with other routing rules:
routes.MapRoute(
"HomeShortcuts",
"{action}",
new { controller = "Home", action = "Index" },
new { action = "Index|About|ContactUs|Features" }
);
Add defaults for the controller names in the new statement. You don't have to have {controller} in the url.

Resources