MVC Routes - Avoid multiple URLs for the same location - asp.net-mvc

The default route in ASP.net MVC is the following:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This means that I can reach the HomeController / Index action method in multiple ways:
http://localhost/home/index
http://localhost/home/
http://localhost/
How can I avoid having three URL's for the same action?

If you want only:
http://localhost/
then:
routes.MapRoute(
"Default",
"",
new { controller = "Home", action = "Index" }
);
If you want only:
http://localhost/home/
then:
routes.MapRoute(
"Default",
"home",
new { controller = "Home", action = "Index" }
);
and if you want only:
http://localhost/home/index
then:
routes.MapRoute(
"Default",
"home/index",
new { controller = "Home", action = "Index" }
);

You are seeing the default values kick in.
Get rid of the default values for controller and action.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {id = UrlParameter.Optional } // Parameter defaults
);
This will make a user type in the controller & action.

I don't suppose you are doing this for SEO? Google penalises you for duplicate content so it is worthy of some thought.
If this is the case routing is not the best way to approach your problem. You should add a canonical link in the <head> of your homepage. So put <link href="http://www.mysite.com" ref="canonical" /> in the head of your Views/Home/Index.aspx page and whatever url search engines access your homepage from, all SEO value will be attributed to the url referenced in the canonical link.
More info: about the canonical tag
I wrote an article last year about SEO concerns from a developer perspective too if you are looking at this kind of stuff

Related

ASP.NET MVC route to page with or without a route data

I'm trying to develop a 2 language site and I have the requirement that if the language route value is not specified, it must go to the page with the default language.
Example:
www.mysite.com/home/products?query=phone
www.mysite.com/en/home/products?query=phone
Both routes should respond with the result page in english.
I have this 2 routes in the RegisterRoute():
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default2",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
When i browse for the second route (www.mysite.com/en/home/products?query=phone) I get a 404 Error.
Where am I wrong?
Thanks
Your url www.mysite.com/en/home/products?query=phone is not working because website engine counts en as a controller, home as action and product s as id.
If you make some research here or using google you will find a lot of solutions of your problem, but each of them has tonns of code to analyze route values, create a new url and redirect. So if your website is quite big with hundreds controllers you can wrote some code. Otherwise if you have only several controllers this coud be the easiest way
[Route("fr/[controller]/[action]")]
[Route("en/[controller]/[action]")]
[Route("[controller]/[action]")]
public class HomeController : Controller
Instead of fr you have to use the letters of your another language. And you don't need to use it for all controllers, it needs only for controllers where you can use an url that doesn't contain any language
And leave only one default route in your config and add MapMvcAttributeRoutes after IgnoreRoutes
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "default",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional }
);

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

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.

MVC Routing Html.ActionLink creates URLs with ?id=1 instead of /id

When I use Html.ActionLink() the URL created is not in the desired format:
Html.ActionLink(Model.ProductCode, "Update", new { id = Model.ProductId })
Makes this URL
/Update?id=1
When I want to have this URL:
/Update/1
What routing options create the 2nd URL? This is our preferred URL style.
Both URLs work and the correct page is displayed - however we want to only use /id
In Global.asax the MVC default route handles both URLs
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" }); // Parameter defaults
I can replicate the issue by having a route about my default route that still matches the general pattern. Example:
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index"} // Parameter defaults
);
When places above my default route, I get the ?id=1 in my URL. Can you confirm that this ActionLink is not matching any routes above the route that you are expecting it to match?
EDIT: The below does not impact the URL
However, it could still be advantageous to use the UrlParameter.Optional in other scenarios. Leaving for prosperity unless mob rule says otherwise.
new UrlParameter.Optional value. If you set the default value for a
URL parameter to this special value, MVC makes sure to remove that key
from the route value dictionary so that it doesn’t exist.
I think you need to adjust your route slightly. Change id = "" to id = UrlParameter.Optional
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
This is what we use for the default route and the behavior that you are looking for is how our applications behave.
See This question/answer.
Which version of MVC are you using? If you're in MVC3, you'll need to add a fourth parameter to your call to Html.ActionLink(), passing in a null.
I've just stumbled upon this and decided to answer. It turned out that both Url.Action() and Html.ActionLink() use the first route in the route collection to format the resulted URL. So, the first mapped route in the RegisterRoutes() shoild be:
routes.MapRoute(
name: "Default",
url: "{controller}/{id}/{action}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
instead of "{controller}/{action}/{id}". The route name (i.e. "Default") does not matter, only the order does matter
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Html ActionLink Route problem

i have defined the following Routes:
routes.MapRoute("Blog",
"Blog/{controller}/{action}",
new { controller = "Test", action = "Index" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
When i call http://localhost/ all Links are wrong and go to the Blog:
#Html.ActionLink("About", "About", "Home") creates the following URL:
localhost/Blog/About
but it should create
localhost/About
Why does HtmlActionLink always prefix the urls with the "Blog"?
ActionLink will the first route that matches the parameters you passed to it.
Since your Blog route contains the controller and action parameters, it will use that route.
You should change your Blog route to be more specific.

Resources