My goal is to remove "home" from any actions in that controller (see bold).
site.com/home/about
site.com/about
site.com/home/contact
site.com/contact
I created the following custom route that sits above the generic base route:
// Used to hide 'home' in the url
routes.MapRoute(
"Home", // Route name
"{action}", // URL with parameters
new { controller = "home", action= "index"} // Parameter defaults
);
This almost does what I want. I now get site.com/about, site.com/contact, etc. However, I cannot use index for my other controllers.
site.com/person/create -> works like a charm.
site.com/person/ -> no good.
How can I fix this? Thanks.
These two routes should work as expected:
routes.MapRoute(
"NoHomeRoute", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Person", action= "Index"}, // Parameter defaults
new { controller = #"person|admin|..." } // Parameter constraints
);
routes.MapRoute(
"HomeRoute", // Route name
"{action}", // URL with parameters
new { controller = "home", action= "index"} // Parameter defaults
);
Since every application has a predefined set of controllers you can put all except home in the upper constraint and it will work. But if you create a new controller, remember to put it in as well. I've put in person for PersonController which you obviously have and also added admin for AdminController you probably don't have, but I needed to put in something to show you the pattern of adding your controllers.
If you're willing to play around with regular expressions, then you could maybe come up with a solution that excludes home instead of includes all except home the way that upper route definitions suggest.
A revised negative constraint
I've checked MVC code and indeed you can define a future proof constraint on the first route definition this way:
routes.MapRoute(
"NoHomeRoute", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Person", action= "Index"}, // Parameter defaults
new { controller = #"(?!home).*" } // Parameter constraints
);
Why should this work? Because the line on ProcessConstraint method has these two lines at the end:
string pattern = "^(" + str + ")$";
return Regex.IsMatch(input, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
// Used to hide 'home' in the url
routes.MapRoute(
"Home", // Route name
"{action}", // URL with parameters
new { controller = "home", action= "index"} // Parameter defaults);
should be the last route you register, otherwise site.com/person is interpreted as an action, since it will match that route first.
Related
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 }
);
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.
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 }
);
simple question. I want something like:
http:/ /www.mywebsite.com/microsoft or http:/ /www .mywebsite.com/apple
so microsoft and apple should be like id but i use it just like controller in the default
this is the default route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "index", id = UrlParameter.Optional } // Parameter defaults
);
This produce something like http:/ /www.mywebsite .com/home/aboutus or http: //www.mywebsite .com/products/detail/10
I added another route
routes.MapRoute(
"Partner", // Route name
"{id}", // URL with parameters
new { controller = "Home", action = "Partners"}, // Parameter defaults
new { id = #"\d+" }
);
but this has constraint that only allow numeric id.
how do I accomplish what I wanted.
thanks
If the expression can contain only letters and digits you could modify the constraint:
routes.MapRoute(
"Partner", // Route name
"{id}", // URL with parameters
new { controller = "Home", action = "Partners"}, // Parameter defaults
new { id = #"^[a-zA-Z0-9]+$" }
);
Not sure exactly what you are trying to achieve but it looks like you need a custom route constraint. Take a look here for an example:
http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Custom-route-constraint-to-validate-against-a-list.aspx
Remember to register the route constraint first
If you don't want to provide a numeric constraint, just delete the 4th parameter, ie
routes.MapRoute("Partner", "{id}", new { controller = "Home", action = "Partners"});
The 4th parameter is an anonymous object that provides constraints for the route parameters that you have defined. The names of the anonymous object members correspond to the route parameters - in this case "controller" or "action" or "id", and the values of these members are regular expressions that constrain the values that the parameters must have in order to match the route. "\d+" means that the id value must consist of one or more digits (only).
What is the problem below?
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "test" } // Parameter defaults
);
routes.MapRoute(
"Default1", // Route name
"{controller}/{action}/{name}", // URL with parameters
new { controller = "Home", action = "Report", name = "" } // Parameter defaults
);
When I navigate to /home/index "id" parameter takes the default value of "test" but when I navigate to home/report the name parameter is null.
In short, if the route definition is the first in the route table, then the parameter takes its default value. But the others below don't.
These two routes {controller}/{action}/{id} and {controller}/{action}/{name} are ambiguous. It cannot distinguish between /home/index/id and /home/report/abc, it is always the first route in the route definition which will be caught because in the second case it thinks that id = "abc".
Use Phil Haack Routes debugger.. to get more clear view how your routes are reacting on diferent paths.
download