make url shorter of some controllers and actions - asp.net-mvc

I would like to make some urls of my asp.net MVC4 app shorter. For example I have Account controller and such action ForgotPassword. Url looks like this
http://www.mydomain.com/account/forgotpassword
I would like to make the url shorter(example below) without renaming actual controller and action names. What is the best way to do that?
http://www.mydomain.com/a/fp

You could register a simple route:
routes.MapRoute(
name: "ForgottenPassword",
url: "a/fp",
defaults: new { controller = "Account", action = "ForgottenPassword" }
);
...in RouteConfig.cs if you're using MVC4.

If i am not wrong, then your talking about Friendly URL's?
Please have a look # quysnhat.wordpress.com
There was a very nice post in Hanselman's web.
Also, there were few questions related to friendly url's(in case it helps you) :-
How can I create a friendly URL in ASP.NET MVC?
http://www.intrepidstudios.com/blog/2009/2/10/function-to-generate-a-url-friendly-string.aspx

The easiest but not the best way of doing it is to hand-code your custom routes:
routes.MapRoute(
name: "AccountForgotRoute",
url: "a/fp/{id}",
defaults: new { controller = "Account", action = "ForgotPassword", id = UrlParameter.Optional }
);
The downside to that is if you will have tons of controllers and action methods and you like all of them to be "shortened", then you will have to write a lot of routes.
One alternative is to define your custom routes in a database and write it out on a file. So for example you have in a database row an accountcontroller-forgotpassword key with a value of a/fp, you dynamically build the route definition, write it in a file and let your application pick it up. How your application can pick up the route definition can be done like this. That link is still applicable for MVC 4. But this one is really messy, IMO, but is an alternative.

Related

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.

Managing routes/Global.asax maintainability

Is there any best practice for how to best define and organize routes in MVC?
The company I work for runs a very extensive, complex ecommerce site with ~600K unique visitors/day.
Here's the problem: in our Global.asax.cs, we've got this HUGE list of approximately 75 route definitions in our RegisterRoutes():
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Is there a better way to define these routes other than having this gigantic list in the Global.asax.cs?
Because we've got a bunch of developers and half of them are incompetent and I can't go back refactoring these routes, it can take literally a couple minutes to figure out what controller is responsible for delivering a URL's View.
What can I do?
One developer toiled away building a prototype that allows us to do this in our Global.asax.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.Include(new RootController());
routes.Include(new AccountController());
routes.Include(new HelpController());
routes.Include(new SearchController());
// etc., for each controller
}
In this prototype, Include() is an extension method and all Controllers inherit from IRoutedController, which provides Include() an IEnumerable<Route> list of Routes to add to the RouteCollection.
But with this prototype, we have a new problem: instead of looking through a list of route.MapRoute() calls to find which controller a specific URL invokes, we now have to guess which Controller is responsible for a specific URL and check its IRoutedController list of routes to see if the URL actually invokes that Controller we guessed. Not so hard, but sometimes takes just as long as examining our list of 75+ Routes in Global.asax.cs.
Is this a better solution?
Is there any good solution?
Should we just keep adding routes to Global.asax.cs; should we give the prototype the green light; or should we do something else? (Assume that you cannot refactor existing route URLs to make them more logical.)
I'm sorry, but what are you talking about? :P
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This single route entry effectively allows you to call Any action method of Any controller with any parameters.
Is this a better solution?
Probably not.
Is there any good solution?
Yes. But you need to share more of your routes to be sure.
Should we just keep adding routes to Global.asax.cs; should we give the prototype the green light; or should we do something else?
No, No, and Yes. You need to share a decent amount of routes to have a better idea of the situation.
(Assume that you cannot refactor existing route URLs to make them more logical.)
But you can make sure new ones fit in the default route, so the problem doesn't keep growing i.e. {controller}/{action}
I would have stored the route information externally in xml file or database and loaded it in global.asax. I can add extra column/attribute that will have example url being routed so that I can search it quickly. Not to mention, I can update route information w/o rebuilding the project (of course, if there are new controllers, views etc then hey would need to be packaged in a new dll).

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.

ASP.NET MVC Routing Questions

I just started using ASP.NET MVC and I have two routing questions.
How do I set up the following routes
in ASP.NET MVC?
domain.com/about-us/
domain.com/contact-us/
domain.com/staff-bios/
I don't want to have a controller specified in the actual url in order to keep the urls shorter. If the urls looked liked this:
domain.com/company/about-us/
domain.com/company/contact-us/
domain.com/company/staff-bios/
it would make more sense to me as I can add a CompanyController and have ActionResults setup for about-us, contact-us, staff-bios and return appropriate views. What am I missing?
What purpose does the name "Default" name have in the default routing rule in Global.asax? Is it used for anything?
Thank you!
I'll answer your second question first - the "Default" is just a name for the route. This can be used if you ever need to refer to a route by name, such as when you want to do URL generation from a route.
Now, for the URLs that you want to set up, you can bypass the controller parameter as long as you're ok with always specifying the same controller as a default. The route might simply look like this:
{action}/{page}
Make sure that it's declared after your other routes, because this will match a lot of URLs that you don't intend to, so you want the other routes to have a crack at it first. Set it up like so:
routes.MapRoute(null, "{action}/{page}",
new { controller = "CompanyController", action = "Company", page = "contact-us" } );
Of course your action method "Company" in your MyDefault controller would need to have a "string page" parameter, but this should do the trick for you. Your Company method would simply check to see if the View existed for whatever the page parameter was, return a 404 if it didn't, or return the View if it did.
Speaking of setting up routes and Phil Haack, I have found his Route Debugger to be invaluable. It's a great tool for when you don't understand why particular routes are being used in place of others or learning how to set up special routing scenarios (such as the one you've mentioned). It's helped clear up many of the intricacies of route creation for me more than any other resource.
To answer your second question about Global.asax, it an optional file used for responding to application level and session-level events raised by ASP.NET or HTTP modules. The Global.asax file resides in the root directory of the ASP.NET application.If you do not define it assumes you have not defined any application handler or session handler. MVC framework uses the routing engine to which the routing rules are defined in the engine, so as to map incoming URL to the correct controller.
From the controller, you can access the ActionName. If there is no specific controller, it will direct to the default page. The default controller is "Home" with its default action "Index". Refer to MSDN:
http://msdn.microsoft.com/en-us/library/2027ewzw%28v=vs.100%29.aspx
Refer to stackoverflow question
What is global.asax used for?
This is a sample of how a default route should look like
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id =
UrlParameter.Optional }
);

Resources