Currently I'am working on an MVC project in which I try to get a kind of dynamic routing working. My idea would be that i left the original route in the global.asax.cs, so this one will take care of every controller I make. For example the Contact and Account controllers.
Above controllers will have url's like
/Contact/
/Account/Logoff/ etc.
The second route I want to add is the one that is a kind of default route when there are no controllers found. In that case I assume this will be a route to a page or pagedetails.
Url's for example will be :
/BBQ/
/BBQ/Accesoires/
I have three routes added in the global.asax.cs which I think are correct. (Also in the correct order). Below I have added the routes:
routes.MapRoute(
"DefaultRoute", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Page", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
"DefaultPageRoute",
"{category}",
new { controller = "Page", action = "Index", category = UrlParameter.Optional });
routes.MapRoute(
"SecondLevelPageRoute",
"{category}/{subCategory}",
new { controller = "Page", action = "PageDetails", category = UrlParameter.Optional, subCategory = UrlParameter.Optional });
with this setup the calls to the controllers work fine, but to the pages like /BBQ/ it gives below error:
Server Error in '/' Application.
The resource cannot be found.
If I comment the first route and go the the /BBQ/ url it works like a charm. What am I overseeing in this routetable?
You put the default route first, so it is trying to go to a route defined by {controller = "BBQ", Action = "Index" }
That route should be the very last route. However, you need more detail in your routes. Just having a category route will cause problems.
For example, if this route is first
routes.MapRoute(
"DefaultPageRoute",
"{category}",
new { controller = "Page", action = "Index", category = UrlParameter.Optional });
Then a call to the URL /Contact/ will assume that you want to go to Page/Index/Contact not /Contact/Index/{id}. I would use a more specific route that signifies that you are browsing a category like:
routes.MapRoute(
"DefaultPageRoute",
"Category/{category}",
new { controller = "Page", action = "Index", category = UrlParameter.Optional });
So you will need to use a url www.mysite.com/Category/BBQ to view what you want, but I don't think that's all bad.
Related
Let's say I have only this route:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
We can see that our startup page will be Home/Index.
And let's say I have created an anchor element using this code in the view:
#Html.ActionLink("This targets another controller","Index", "Admin")
When I render the view, you will see the following HTML generated:
This targets another controller
Our request for a URL that targets the Index action method on the Admin controller has been expressed as /Admin by the ActionLink method. The routing system is pretty clever and it knows that the route defined in the application will use the Index action method by default, allowing it to omit unneeded segments.
And the question is:
If I change the route as:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{name}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
name = UrlParameter.Optional
});
or as:
routes.MapRoute("Default", "{controller}/{action}/{id}/{*catchall}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
Then, the following HTML will be generated:
This targets another controller
Could you explain me why?
Both:
routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{name}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
name = UrlParameter.Optional
});
and:
routes.MapRoute("Default", "{controller}/{action}/{id}/{*catchall}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
are invalid route definitions because only the last segment of a route can be optional. Otherwise the routing engine cannot disambiguate your routes.
Now back to your original question as why for those routes the framework doesn't infer the /Index part. This is because the framework, when evaluating your route pattern it sees this:
{controller}/{action}/{id}/{name}
See that {id} portion of your route? When it analyzes this pattern it knows in advance that the {action} part is followed by a non optional segment ({id} in your case) which you must always be present. And since it knows that it, is pretty obvious that it cannot be clever and omit the /Index part and it doesn't even try to. On the other hand you can specify a default value for your last segment and it will be omitted when generating routes with this value.
This is related my question which i asked in this link correct me on url routing in mvc
Now i came with another problem, so i thought i will ask it as new question.
Now i have following routes in my global.asax file
routes.MapRoute(
"Custom", // Route name
"{action}/{id}", // URL with parameters
new { controller = "Authentication", action = "BigClientLogin", id = UrlParameter.Optional } // Parameter defaults
);
and
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Authentication", action = "BigClientLogin", id = UrlParameter.Optional } // Parameter defaults
);
Now what happens is when i run my solution the URL i am getting is http://localhost:65423/Login this is what i need for my Login Page that is OK. But when i login in as user i am getting "The resource cannot be found" error.
when i checked it i can see that my URL is now changed to http://localhost:65423/Admin/Dashboard
So i think this causing the issue. So this looks the problem related to my global.asax routing.
Can anyone help me to find out what i did wrong.
You have 2 routes with completely optional segments. The issue is that there is no way for the routing framework to differentiate between them.
The only way you can make it work with your existing routes is to specify them explicitly by name (such as when using #Html.RouteLink or #Html.RouteUrl).
#Html.RouteLink("Custom Link 1", "Custom", new { action = "BigClientLogin" })
#Html.RouteLink("Custom Link 2", "Custom", new { action = "Action2" })
#Html.RouteLink("Home Page", "Default", new { controller = "Home", action = "Index" })
#Html.RouteLink("About", "Default", new { controller = "Home", action = "About" })
Doing it that way will function, but is not normal. Typically, there is only one route configured with all defaults for the controller, action, and id and the rest have some explicitly declared segments and/or constraints (segments being preferable).
routes.MapRoute(
"Custom", // Route name
"Custom/{action}/{id}", // URL with parameters
new { controller = "Authentication", action = "BigClientLogin", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Authentication", action = "BigClientLogin", id = UrlParameter.Optional } // Parameter defaults
);
The first route will now only match when the URL starts with /Custom/. If it does not start with custom, it will match the default route.
The trick is to ensure that the routes are listed in the right order and that they only match the URL in specific cases, letting them pass on to the next route in the list if the case is not correct.
It happens because of 2 things.
1st the sequence of Your route
2nd your defaults
So if you end up on 'admin/dashboard' that's not a default, guess you've just put it in your studio to start there?
To get to http://localhost:65423/Login you'll need an action on Your AuthenticationController called 'Login' but it looks like the one You have configured is 'BicClientLogin' so You won't be taken to login unless you specify it, and at that time it has to exist.
To Help You further we need to know what controllers You have and what actions there exists, plus if security is part of your solution and if in case, what is is set to use.
I am trying to write a rule to map a URL but so for I did not get the results I want. I have this rule so far:
routes.MapRoute(
"Search", // Route name
"{controller}/{action}/{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", product = UrlParameter.Optional, page = UrlParameter.Optional } // Parameter defaults
);
using this I can achieve this result so far:
localhost:8493/home/search/myproduct
localhost:8493/home/search/myproduct/2
but i want to do something like this:
localhost:8493/myproduct
so this will route to home/search/myproduct
I have tried the following but it didn't work:
routes.MapRoute(
"DirectSearch", // Route name
"{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", } // Parameter defaults
);
Is there a way to do this?
Add:
So Here i added the specific route to map to another action but it doesn't work:
routes.MapRoute(
"Tuna",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Tuna", id = UrlParameter.Optional }
);
You're close I think. This should work;
routes.MapRoute(
"Search", // Route name
"{product}/{page}", // URL with parameters
new { controller = "Home", action = "Search", product = UrlParameter.Optional, page = UrlParameter.Optional } // Parameter defaults
);
Just remember that the framework will read the route data from top to bottom and use the first one it finds that matches. So make sure the more specific routes are listed before the more general ones
Edit
Here's a link to a discussion on custom routing
I have a request controller that is getting out of hand, and I want to divide the actions on several controllers while maintaining a clean URL. I'm trying to experiment with routing, but without success. I've read some examples and tutorials on routing, but, though I understand the examples, nothing seems to apply to my case, and I feel non the wiser. What I want is for the URL Requests/Approval to be handled on my ApprovalController instead of my RequestController, so I wrote the following.
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(
"Approval",
"Request/{controller}/{action}",
new { controller = "Approval", action="Index", id = "" }
);
}
But it's not working. Why? I have a folder in the my Views called Approval, and in there I have a file called Index.cshtml. How should I code the MapRoute?
Edit
I added all the routes I've got
You need to swap the two MapRoute statements, like so:
routes.MapRoute(
"Approval",
"Request/Approval/{action}",
new { controller = "Approval", action="Index", id = "" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
The reason it is currently not working is because the first statement ('Default' route name) is getting matched before the second one is even evaluated.
In addition (as noted in my above example,) you need to remove '{controller}' in the Approval route and replace with 'Approval'... unless you specifically want the URL /Request/{ANY controller}/{action} to go through, which I doubt. From your question it seems you only want /Request/Approval/ to go to your Approval controller.
Don't forget to keep the Default route at the bottom, so as to match your other controllers and actions. It serves as a catch-all should no other matches exist.
The order you map your routes matters. Move the second route before the default route.
You will still have a problem though, as any thing /request/something will look for the SomethingContoller. To fix this, change your route to this:
routes.MapRoute(
"Approval",
"Request/Approval/{action}",
new { controller = "Approval", action="Index", id = "" }
);
How do I generate friendly URLs within the ASP.NET MVC Framework? For example, we've got a URL that looks like this:
http://site/catalogue/BrowseByStyleLevel/1
The 1 is Id of the study level (Higher in this case) to browse, but I'l like to reformat the URL in the same way StackOverflow does it.
For example, these two URLs will take you to the same place:
https://stackoverflow.com/questions/119323/nested-for-loops-in-different-languages
https://stackoverflow.com/questions/119323/
EDIT: The friendly part of the url is referred to as a slug.
There are two steps to solve this problem. First, create a new route or change the default route to accept an additional parameter:
routes.MapRoute( "Default", // Route name
"{controller}/{action}/{id}/{ignoreThisBit}",
new { controller = "Home",
action = "Index",
id = "",
ignoreThisBit = ""} // Parameter defaults )
Now you can type whatever you want to at the end of your URI and the application will ignore it.
When you render the links, you need to add the "friendly" text:
<%= Html.ActionLink("Link text", "ActionName", "ControllerName",
new { id = 1234, ignoreThisBit="friendly-text-here" });
This is how I have implemented the slug URL on my application.
Note: The default Maproute should not be changed and also the routes are processed in the order in which they're added to the route list.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional
} // Parameter defaults
);
routes.MapRoute("Place", "{controller}/{action}/{id}/{slug}", new { controller = "Place", action = "Details", id = UrlParameter.Optional,slug="" });
you have a route on the global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = ""}
// Parameter defaults )
you can define your own route like :
controller is the cs class inside the the controllers folder.
you can define your id - with the name you choose.
the system will pass the value to your actionResult method.
you can read more about this step here : http://www.asp.net/learn/mvc/tutorial-05-cs.aspx