MVC 3 keeping short url - asp.net-mvc

I have MVC3 application, where I want to keep short URL. what is the best or clean way to do this?
Lets say I have two controllers Account and Home. I have all the account related tasks Logon, Logoff, Profile, FAQs etc. in Account controller. All the main tasks in home controller like TaskA, TaskB, and TaskC. I am looking for URL as below:
www.mydomain.com/Logon
www.mydomain.com/Logoff
www.mydomain.com/Profile
www.mydomain.com/FAQs
www.mydomain.com/TaskA
www.mydomain.com/TaskB
when user first come to the website they need to redirect to Logon page. At any time user should also able to switch from once controller action to another controller action (from TaskA to Logoff).
what is the clean way to do this?

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

You can set a route for the specific urls that do not match the default route. For example:
routes.MapRoute("Logon", "logon/", new { controller = "account", action = "logon" });
routes.MapRoute("TaskA", "TaskA/", new { controller = "home", action = "taska" });
Your default route can define your start page if all other matches for the url are not found.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}/", // URL with parameters
new { controller = "account", action = "logon", id = UrlParameter.Optional } // Parameter defaults

Related

How to map same routes for two controller?

I have two controller in my MVC application. One is Home controller and other is User controller. I am using following RouteConfig settings.
routes.MapRoute(
"actiononly",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I want abc.com/Blog
abc.com/Login
Instead of abc.com/Home/Blog
abc.com/User/Login.
Above configuration works fine with abc.com/Blog but it is not working with abc.com/Login.
How to remove controller name from the link for both controllers?
Also how can I only show abc.com when website launches instead of abc.com/index? I am using following code in my webpage to access the particular page.
#Html.ActionLink("Home", "Blog", "Home")
#Html.ActionLink("Login", "Login", "User")
Your default route should automatically cater for wanting to nav to abc.com without requiring the index part of the URL
You need to ensure that your main route is specified as the default:
context.MapRoute(
"Site_Default",
"{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
If you want to map short routes you can do exactly what you've done above. I use this helper function in my own project to map short routes:
void ShortRoute(string action, string controller)
{
ShortRoute(action, controller, action);
}
void ShortRoute(string action, string controller, string route)
{
_context.MapRoute(route, route, new { action, controller });
}
With usage:
ShortRoute("About", "Home");
Which allows me to navigate to mywebsite.com/about instead of mywebsite.com/home/about
If it's not working for certain URLs it may be that the route handler is matching a different route - I believe it does depend on the order you register them
There's a good route debugging plugin you can use
https://www.nuget.org/packages/routedebugger/
It gives you a summary of all routes and which ones matched the current URL - very useful
Without bringing in additional packages, you simply need to add an additional route. To create the new route, you first must define what you want your URL to be. In this case, you have said you want to be able to go to /Login which is on the user controller. Ok - let's create a new route. This route should be located ABOVE your default route.
routes.MapRoute(
"UserLogin",
"Login/{id}",
new { controller = "User", action="Login", id = UrlParameter.Optional }
);
The first parameter is simply the route name. The second parameter is the format of the URL that I want this route to match. Given we know what action we want to match to this route, we don't need the {action} or {controller} catchall placeholders that are in the default route. Also note that we can declare what controller this route will hit without having to specify the controller in the URL.
Last note, you don't have to have the {id} be part of the route if you will never be passing an ID parameter to that function. If that is the case, then you can safely remove any references to id in the UserLogin route.
As I re-read your question, you should be able to do this for some of your other examples as well. Let's take the /About URL and demonstrate the removal of the {id} parameter.
routes.MapRoute(
"AboutUsPage",
"About",
new { controller = "Home", action="About"}
);
This is very simple. You just need to create a route for each of your expected URLs.
Keep in mind that if you don't pass the controller or action as a URL placeholder, you will need to do so manually by providing them as default values.
routes.MapRoute(
"Blog",
"Blog/{id}",
new { controller = "Home", action = "Blog", id = UrlParameter.Optional }
);
routes.MapRoute(
"Login",
"Login/{id}",
new { controller = "User", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

how to shorten controller name, and action name in output URL in MVC 4?

I am writing an MVC 4 application which has controllers and many lengthy action names, and they create a lengthy URL which is not easy to remember.
Any idea of how we can implement short URLs (Preferably, without affecting routing) in MVC 4? May be using custom attributes?
Actually, you can specify your routes in RouteConfig.cs. Here is the code from my application:
routes.MapRoute("SignUp", "signup", new { controller = "SignUp", action = "Index" });
routes.MapRoute("SignOut", "signout", new { controller = "Login", action = "SignOut" });
routes.MapRoute("Login", "login", new { controller = "Login", action = "Login" });
Second parameter here (signup, signout, login) are the short urls. If you want something more, you can specify your routes like this:
routes.MapRoute("SetNewPassword", "set-new-password/{userId}/{passwordResetKey}", new { controller = "SetNewPassword", action = "Index" });
The url here is something like /set-new-password/123/blabla
New routes don't affect default routes. Just make sure you have this default line at the end:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Btw, you can use handy route debugger from Phil Haack. It's really easy to set up and use (you just need to comment/uncomment one single line in your Global.asax.cs). It's absolutely must have tool for every Asp.Net MVC developer.
May be a "catchall" routing will help you.
You could set up a catch-all type route, to direct all /something requests to a specific action and controller, something like:
routes.MapRoute(
"ShortUrls",
"{name}",
new {controller = "ShortUrl", action = "Index", name = UrlParameter.Optional}
);
(depending on how the rest of your routing is set up, you probably don't want to do it exactly like this as it will likely cause you some serious routing headaches - but this works here for the sake of simplicity)
Then just have your action redirect to the desired URL, based on the specified value:
public class ShortUrlController : Controller
{
//
// GET: /ShortUrl/
public ActionResult Index(string name)
{
var urls = new Dictionary<string, string>();
urls.Add("disney", "http://..your lengthy url");
urls.Add("scuba", "http://another..lengthy url");
return Redirect(urls[name]);
}
}

asp.net mvc basic routing issue

i have two folder under view folder. one is Home and that has index.aspx file
another folder in view folder called DashBoard and that has MyDash.aspx
my routing code look like in global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"DashBoard", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "DashBoard", action = "MyDash", id = UrlParameter.Optional } // Parameter defaults
);
}
so when i type url like http://localhost:7221/ or http://localhost:7221/Home then index.aspx is being render from Home folder but when i type url like http://localhost:7221/DashBoard then page not found is coming but if i type like http://localhost:7221/DashBoard/MyDash then page is coming.
so what is wrong in my second routing code . why MyDash.aspx is not coming when i type url like http://localhost:7221/DashBoard. what is wrong?
what i need to change in my second routing code??
please have a look.....i am new in MVC. thanks
My UPDATE
when i change route entry in global.asax file then it started working.
can u please explain why....
routes.MapRoute(
"DashBoard",
"DashBoard/{action}/{id}",
new { controller = "DashBoard", action = "MyDash", id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
can i write routing code this way
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "DashBoard", action = "MyDash", id = UrlParameter.Optional }
);
same pattern for two url....please discuss in detail. thanks
The route names (1st parameter) have no impact on what action/controller gets invoked.
Your 2 route patterns, however, (2nd paramters of routes.MapRoute) are identical :
"{controller}/{action}/{id}"
... so anything that would be matched by the 2nd pattern gets caught by the first pattern. Therefore they're all getting mapped by the first map definition.
http://localhost:7221/Home works because it matches the first pattern, and presumably, the Index action exists inside your Home controller.
http://localhost:7221/DashBoard/MyDash works because, even though it's getting matched by the 1st route, it overrides the default action/controller (Home/Index) by the route parameters passed in through the URL (DashBoard/MyDash).
http://localhost:7221/DashBoard doesn't work because it's getting picked up by the first route pattern, but you didn't pass in an action name, so it looks for the default -- Index -- which I'm guessing you haven't set up within the DashBoard controller.
UPDATE (how to fix the problem):
So if you want http://localhost:7221/DashBoard to map to Controller named DashBoard with an action named MyDash, while still allowing other patterns to be picked up by {controller}/{action}/{id} delete your 2nd route, and place this one as the 1st route:
routes.MapRoute(
"DashBoard",
"DashBoard/{action}/{id}",
new { controller = "DashBoard", action = "MyDash", id = UrlParameter.Optional }
);
This is a more specific route, so it needs to go before the catch-all {controller}/{action}/{id}. Nothing that doesn't start with /DashBoard will get picked up by it.

MVC3 URL Routing

I am wanting to create a website that dynamically maps routes in the following fashion:
http://domain/MyCategory1
http://domain/
http://domain/MyCategory1/MySubCategory
So far I've added in a new route to Global.asax
routes.MapRoute(
"IFAMainCategory", // Route name
"{IFACategoryName}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=1} // Parameter defaults
);
But this then messes up the default route that comes as standard.
Is there any way I can control this?
You need to change your routes:
routes.MapRoute("MyCustomRoute", "MyCategory1/{action}/{id}",
new { controller = "MyCategory1", action = "MySubCategory", id = UrlParameter.Optional });
// Then the default route
Basically, since you've just made one giant route catcher, all routes match to that one. You need to go specific if you want to map a specific route to a controller.
You need to include MyCategory1 in the route name
routes.MapRoute( "IFAMainCategory",
// Route name "MyCategory1/{IFACategoryName}",
// URL with parameters new { controller = "Home", action = "GetSubCategories", IFACategoryName=1} // Parameter defaults );
Check out this other post for example, and check out Route Debugger
.NET MVC custom routing
Unfortunately I don't think you're going to achieve what you want directly.
You need some way to separate the routes, like placing your "categories" in a folder:
routes.MapRoute(
"IFAMainCategory", // Route name
"categories/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=1 }
);
The other option is you could register a route for every parent category before the default route on App Start:
routes.MapRoute(
"IFAMainCategory 1", // Route name
"MyCategory1/{subcategory}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=1, subcategory = UrlParameter.Optional }
);
routes.MapRoute(
"IFAMainCategory 2", // Route name
"MyCategory2/{subcategory}", // URL with parameters
new { controller = "Home", action = "GetSubCategories", IFACategoryName=2, subcategory = UrlParameter.Optional }
);

asp mvc RedirectToRoute adding current action to the redirect

I have a controller that has an action called RedirectLogin, it basically sets a TempData var to redirect back to when the login is finished.
After this, it simply calls:
return RedirectToRoute("Login");
However, the when it redirects, it goes to /login/RedirectLogin - it is tacking on the calling action's name for some reason. I think it should just be returning the defaults, not adding actions, especially actions not part of the destination controller.
If I call:
return RedirectToRoute("Login", new { action = "Index" });
Then it properly makes the path /login, but again, shouldnt it be doing that by default, without the extra bit?
I have a slightly non-standard routing setup. Basically I am creating virtual subfolders for my clients, so www.domain.com/clienturl but I still want www.domain.com/join or www.domain.com/about to redirect to non-client data. I do this by adding the name of the controller directly in the path, and add it before the more generic one called Landing. Could this be the problem, or is there a better way to do it :)
// Root paths
routes.MapRoute("About", "about", new { controller = "Home", action = "About" });
routes.MapRoute("Info", "info", new { controller = "Home", action = "Info" });
routes.MapRoute("Privacy", "privacy", new { controller = "Home", action = "Privacy" });
routes.MapRoute("Terms", "terms", new { controller = "Home", action = "Terms" });
// Root controllers
routes.MapRoute("Join", "join/{action}/{id}", new { controller = "join", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Login", "login/{action}/{id}", new { controller = "login", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Account", "account/{action}/{id}", new { controller = "account", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Goodbye", "goodbye/{action}/{id}", new { controller = "goodbye", action = "Index", id = UrlParameter.Optional });
// Organization
routes.MapRoute("Landing", "{organization}/{controller}/{action}/{id}", new { controller = "Landing", action = "Index", id = UrlParameter.Optional });
// Default
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
It's reusing the data from the current request. since you have the optional parameter 'action' it is taking the action parameter from your current request who's action is RedirectLogin and it attaches that to the url. I'd make a specific route entry without the optional parameters to your login page or redirect to action and not used named routes. There is a page in the book Pro ASP.NET MVC 2 that explains what's happening in more detail.
Alternatives you may wish to try are as follows:
RedirectToAction(String, String, RouteValueDictionary);
RedirectToAction(String, RouteValueDictionary);
Redirect("~/login"); // Note, this works but if you move around the urls for your routes you'll need to fix it everytime... not recommended
The MSDN article here shows all of the available Methods on a Controller: http://msdn.microsoft.com/en-us/library/system.web.mvc.controller_methods%28v=VS.98%29.aspx
Don't use the RedirectToActionPermanent or RedirectToRoutePermanent for this purpose though...

Resources