.NET MVC. I am having some problems defining and using custom routes.
I have a controller with just 2 actions. These action methods receive 2 parameters each. I have added a custom route in RouteConfig.cs (before the default route), like this
routes.MapRoute(
name: "customRoute",
url: "MyController/{action}/{entityType}/{id}",
defaults: new { controller = "MyController", action = "Index", entityType = UrlParameter.Optional, id = UrlParameter.Optional }
);
this works if MyController does contain an Index method (and corresponding view).
the problem is, MyController does not contain an Index method (only the 2 action methods refered before), and I want the route.default to be something like Home/Index instead. but if I change the route to this:
routes.MapRoute(
name: "customRoute",
url: "MyController/{action}/{entityType}/{id}",
defaults: new { controller = "Home", action = "Index", entityType = UrlParameter.Optional, id = UrlParameter.Optional }
);
it does not work. Apparently, the controller in route.url must be the same as the one in route.defaults...
CORRECTION: the route works for a correct url, but for an incorrect one (for example adding another parameter at the end) it shows 404 error (makes sense, because MyController.Index does not exists)
so, how can this be achieved?
url: "MyController/{action}/{entityType}/{id}"
Here, what you are saying is the URL pattern for your custom route should start with MyController(My/).
If the url pattern does not match with the configured routes(including the default one) you will have 404 Error.
I can suggest 2 ways of achieving what you want...
Either create a third method in your MyController that will act as the default one and its task would be to redirect to Home/Index.
Or
Create a new method in Home controller having parameters for entityType and Id.
You can't create an overload for Home/Index because you can only have a maximum of 2 action methods with the same name on a controller.
See this.
Routing: The current request for action [...] is ambiguous between the following action methods
Related
I am in the process of setting up a Single Page Application (SPA) and would like to setup, currently two routes. For instance:
Route 1: http://localhost - this is the default route which requires authentication (Admin area)
Route 2: http://localhost/<client>/<clients project name>/ - this does not require authentication (view only)
In the admin area, they setup the <client> and <clients project name>, therefore I know I need to setup this configuration in MVC4 Routes, but it is unclear to me how I would approach this.
Another caveat would be, if the <clients project name> was not entered into the URL, it would present a search page for that client.
One of the great things about routing in MVC is the ability to route anything to anywhere, regardless of whether the url matches the naming of controllers and action methods. The RouteConfig allows us to register specific routes to cater for this. Let me show you how you can achieve this.
Route 1:
This is handled by the default route in the route config.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index",
id = UrlParameter.Optional });
Hitting http://localhost will take you to the Home controller and the Index action method.
Route 2:
We can set up one route that will cater for http://localhost/<client> and http://localhost/<client>/<clients project name>
routes.MapRoute(
"Client",
"{client}/{title}",
new { controller = "Home",
action = "Client",
title = UrlParameter.Optional });
Hitting either http://localhost/bacon or http://localhost/bacon/smokey will take you to the Home controller and the Client action method. Notice the title is an optional parameter this is how we can get both urls to work with the same route.
For this to work on the controller end our action method Client would need to look like this.
public ActionResult Client(string client, string title = null)
{
if(title != null)
{
// Do something here.
}
}
I am quite new to MVC. I am facing a problem with routing right now. My project URL is /account/Create. I can access controller and do my stuff for Create, but
I need to access /account controller because I need to write code in that level.
/account/create - I can access the code this level
/account - dont know how to access this controller
Project Stucture:
Sample Project
Controler
Model
View
What am I supposed to change in the following code?
//global.asax.cs
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
);
}
/account/create is accessing code in the Account controller. Create has to be a method on the Account controller (unless you modify the default routes). Any public method you define on the account controller is accessible via /account/method URL. Based on the route you posted, going to /account URL is going to call the account controller Index method:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
**new { controller = "Home", action = "Index", id = UrlParameter.Optional }** // Parameter defaults
);
That action = "Index" part above is defining what the default method on the account controller is, so going to /account URL is equivalent in this case to /account/index URL
And I just noticed that you spelled account wrong in the question, not sure if that may be your issue ;)
Update
Not sure if this is what you're after, but if you need to write code at the /Account level you can do this in the constructor of the controller.
Unless you substantially customize MVC, then controllers correspond to classes derived from Controller in mvc, and actions correspond to methods on those controllers.
What are you trying to achieve when you say you can't access the controller /Account?
The controller is only a container for Actions so you need to specify an Action. Of course, you can have a default Action in case an action isn't specified. That is specified in default the route above. It's called Index
I have default routing set for my mvc application like:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
I have Home controller with Index() and About(). Tell me please how to modify routing to get both domain.com/Index and domain.com/About urls?
Thank you
Add this before your default route. By adding it before the default route, if it matches it will be used to set the RouteDictionary values. Untested, but it should map urls that only have a single component that is either index or about. Note, that this assumes you don't have an index or about controller. The routing constraint is important as it keeps it from matching on each controller's index action, e.g., controller/.
routes.MapRoute(
"IndexOrAbout",
"{action}",
new { controller = "home", action = "index", id = "" },
new
{
action = "(index)|(about)"
}
);
Note, if you need to expand this to more top-level routes or make it more dynamic you could use a custom routing constraint that could draw the top-level values from a database or configuration. At that point, you'd probably want to change it from using the action parameter to the id parameter and have a single action that use the id to determine what to show rather than have an action per value.
Suppose I have the following routing
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
Now, when you generate an url using Url.Action("Index","MyController") you will get as expected : /MyController
But in one exceptional case, I would like to get the full url /MyController/Index
(without changing the routing)... does anyone know if this is possible?
It is possible. But you need to modify the routing.
Create an own routing class that derives Route
Override the GetVirtualPath() method to include /index for the pages that needs it.
Configure the default route using your routing class instead.
I am afraid this is not possible. And it shouldn't matter as both urls will resolve to the same controller action.
I am trying to define dynamic sections of my site with the root url of the site. I am having some trouble defining the right MVC Route for it. Can someone please help.
My desired url will look like this: http://website.com/[dynamic-string]
But I have other standard pages like: http://website.com/about or http://website.com/faq or even just http://website.com.
My routes don't work correctly with that dynamic string. As shown below.
This is the route for the dynamic-string.
routes.MapRoute(
"CommunityName", // Route name
"{communityName}", // URL with parameters
new { controller = "Community", action = "Community", communityName = UrlParameter.Optional }
);
This is the route for all other STANDARD PAGES
routes.MapRoute(
"Default", // Route name
"{action}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
My routes just don't match up. Everything either gets diverted to one or the other route depending on which route is declared first.
There is no difference between the two routes you mention. How can MVC know which url should be mapped to communityName and which to action? Any url can match both.
You can define your standard pages as a route (before the CommunityName route) or you can catch them in your Community action, see if the name matches a function in your Home controller and then call the right action function.
I've never done this before but you might be able to create a more intelligent routehandler that looks at your controller actions, checks if the action really exists and if true selects that route.
this is beacuse the routes are effectively the same. When you declare the action route you do not state any constraints to the route, for this reason anything will be assumed to be a the action name.
If you want two routes to capture at the same level then you must constrain the action names to those that exist on your controller, this way if it does not match it will pass to the next route.
You can see an example of and advanced constraint here:
http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Custom-route-constraint-to-validate-against-a-list.aspx