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 }
);
Related
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.
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 }
);
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 }
);
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
I want to remove the controller name from my URL (for one specific controller). For example:
http://mydomain.com/MyController/MyAction
I would want this URL to be changed to:
http://mydomain.com/MyAction
How would I go about doing this in MVC? I am using MVC2 if that helps me in anyway.
You should map new route in the global.asax (add it before the default one), for example:
routes.MapRoute("SpecificRoute", "{action}/{id}", new {controller = "MyController", action = "Index", id = UrlParameter.Optional});
// default route
routes.MapRoute("Default", "{controller}/{action}/{id}", new {controller = "Home", action = "Index", id = UrlParameter.Optional} );
To update this for 2016/17/18 - the best way to do this is to use Attribute Routing.
The problem with doing this in RouteConfig.cs is that the old route will also still work - so you'll have both
http://example.com/MyController/MyAction
AND
http://example.com/MyAction
Having multiple routes to the same page is bad for SEO - can cause path issues, and create zombie pages and errors throughout your app.
With attribute routing you avoid these problems and it's far easier to see what routes where. All you have to do is add this to RouteConfig.cs (probably at the top before other routes may match):
routes.MapMvcAttributeRoutes();
Then add the Route Attribute to each action with the route name, eg
[Route("MyAction")]
public ActionResult MyAction()
{
...
}
Here is the steps for remove controller name from HomeController
Step 1:
Create the route constraint.
public class RootRouteConstraint<T> : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var rootMethodNames = typeof(T).GetMethods().Select(x => x.Name.ToLower());
return rootMethodNames.Contains(values["action"].ToString().ToLower());
}
}
Step 2:
Add a new route mapping above your default mapping that uses the route constraint that we just created. The generic parameter should be the controller class you plan to use as your “Root” controller.
routes.MapRoute(
"Root",
"{action}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { isMethodInHomeController = new RootRouteConstraint<HomeController>() }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Now you should be able to access your home controller methods like so:
example.com/about,
example.com/contact
This will only affects HomeController. All other Controllers will have the default routing functionality.
If you want it to apply to all urls/actions in the controller (https://example.com/action), you could just set the controller Route to empty above ApiController. If this controller going to be your starting controller, you'll also want to remove every launchUrl line in launchSettings.json.
[Route("")]
[ApiController]
You'll have to modify the default routes for MVC. There is a detailed explanation at ScottGu's blog:
http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx
The method you should change is Application_Start. Something like the following might help:
RouteTable.Routes.Add(new Route(
Url="MyAction"
Defaults = { Controller = "MyController", action = "MyAction" },
RouteHandler = typeof(MvcRouteHandler)
}
The ordering of the routes is significant. It will stop on the first match. Thus the default one should be the last.
routes.MapRoute("SpecificRoute", "MyController/{action}/{id}",
new {controller = "MyController", action = "Index",
id = UrlParameter.Optional});
// default route
routes.MapRoute("Default", "{controller}/{action}/{id}",
new {controller = "Home", action = "Index",
id = UrlParameter.Optional} );