I have Created a new Controller called Consultants. Then I create action method Index()..
I gave route like the following,
routes.MapRouteLowercase(
"consultants",
"consultants/index",
new { controller = "Consultants", action = "Index" }
);
In view, ActionLink method is,
<%: Html.ActionLink("Consultant Home", "Index", "Consultants", null, new { title = "Back home" })%>
But it is not routing. It is showing Resource cannot be find
Please correct my issues...
It looks like you've created a custom RouteCollectionExtensions called MapRouteLowercase (or at least I'm not familiar with it). I'd test that to make sure it's working as you expect by changing your route to this:
routes.MapRoute(
"consultants",
"consultants/index",
new { controller = "Consultants", action = "Index" }
);
Otherwise, you may have another route map causing issues, so make sure that route config is at the very top of your routing. Order plays an important role in how the route engine determines the correct url when searching for patterns. So order from specific to general.
For example, if you did something like this, it would cause issues with your current route:
routes.MapRoute(
"dateRoute",
"consultants/{date}",
new { controller = "Consultants", action = "Dates", date = UrlParameter.Optional }
);
Related
I've been trying to get a couple of custom routes working with no luck. I have two pages for my automotive app. The first page shows a list of vehicles. When the user clicks the links generated on this page it takes them to the product list page. The problem is this page doesn't generate the links properly.
Here is the routes:
routes.MapRoute(
"Select_Vehicle",
"Select_Vehicle/{id}/{make}",
new { controller = "Select_Vehicle", action = "Index", id = UrlParameter.Optional, make = UrlParameter.Optional });
routes.MapRoute(
"Products",
"Products/{id}/{make}/{model}",
new { controller = "Products", action = "Index", id = UrlParameter.Optional, make = UrlParameter.Optional, model = UrlParameter.Optional });
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
The Select_Vehicle page should generate links like this:
/products/horns/dodge/dakota
but what I get is this:
/Products/Index/horns?make=dodge&model=Dakota
It just doesn't work properly. Also, I don't understand why "Index" also shows since it is the default.
I've tried both ActionLink and RouteLink:
#Html.RouteLink(model, new { Controller = "Products", id = Model.CategoryName, make = Model.CurrentMake, model = model })
#Html.ActionLink(model, "Index", "Products", new { id = Model.CategoryName, make = Model.CurrentMake, model = model }, null)
This is driving me crazy.
ASP.NET MVC only supports a single optional parameter. Update your routes to give make and model a default rather than making them optional. You might also need to use the overload on RouteLink that takes the route name so that it chooses the correct route.
#Html.RouteLink(model, "Products", new
{
id = Model.CategoryName,
make = Model.CurrentMake,
model = model
})
Your code should work. I've tested your routes with a fresh project and this is what I got. Do you have anything else in your route configuration?
http://localhost:60599/Products/horns/dodge/dakota
I am using asp.net MVC 3
Well, I figured out the problem. You can have more than one UrlParameter.Optional, but there is an issue. It is a bug or feature depending on how Microsoft wants to position it.
The issue is the the make was empty which caused a problem when it was building the URL. You can find more information here:
http://haacked.com/archive/2011/02/20/routing-regression-with-two-consecutive-optional-url-parameters.aspx
Thanks for all the suggestions and help.
I have a controller called TaskListsController with an action called Edit.
The Edit action accepts a nullable int parameter. If it receives null, it adds a TaskList. If it receives an int, it edits the TaskList with the same ID. The logic is almost identical in each case.
I would like to configure my routing in such a way that the URL 'TaskLists/Add' maps to the Edit action with null as the parameter, and the URL 'TaskLists/Edit/{id}' maps to Edit and passes it the ID in the URL.
I can get this to work from the point of view of entering URLs in the browser and having them routed to the action correctly, but where it's falling down is where the system generates URLs from Html.ActionLink.
I am generating 'Add' links using:
Html.ActionLink("Add task list", "Edit", "TaskLists")
And I'm generating 'Edit' links using:
Html.ActionLink(taskList.Name, "Edit", new { Id = taskList.Id })
..where taskList is an instance of the TaskList class.
If I use this routing:
routes.MapRoute(
"TaskLists/Add", // Route name
"TaskLists/Add", // URL with parameters
new { controller = "TaskLists", action = "Edit" });
routes.MapRoute(
"TaskLists/Edit/{id}", // Route name
"TaskLists/Edit/{id}", // URL with parameters
new { controller = "TaskLists", action = "Edit", id = UrlParameter.Optional });
...the 'Add' link is generated correctly ('TaskLists/Add') but the 'Edit' link comes out 'TaskLists/Add?Id=1'.
If I put the routing commands the other way around:
routes.MapRoute(
"TaskLists/Edit/{id}", // Route name
"TaskLists/Edit/{id}", // URL with parameters
new { controller = "TaskLists", action = "Edit", id = UrlParameter.Optional });
routes.MapRoute(
"TaskLists/Add", // Route name
"TaskLists/Add", // URL with parameters
new { controller = "TaskLists", action = "Edit" });
...then the 'Edit' links are generated correctly ('TaskLists/Edit/x'), but the 'Add' links comes out 'TaskLists/Edit'.
Is there a way I can have my cake and eat it?
Using named routes (Html.RouteLink("linkText", "routeName")) could be a cleaner way of defining this, as then you're dealing with a clean route in the view also. This would also mean that you will hit the correct route every time without worry.
Update the Name parameter on your routes accordingly, then add the following to your view:
Html.RouteLink("Add task list", "NewTaskList")
and
Html.RouteLink(taskList.Name, "EditTaskList", new { Id = taskList.Id })
I've created a new ASP.NET MVC 3 internet application in Visual Web Developer 2010 Express, and I have noticed that with this default template, the path localhost:port/Home shows the same content as localhost:port/
Is there a way to remove the /Home? I would only like localhost:port/ to be the landing page.
Both urls work because that's how the default route has been defined in Global.asax:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This means that all of /, /Home and /Home/Index will land to the HomeController/Index action. So in fact when you are request / it is the exact same action being executed.
You can modify it like so:
routes.MapRoute(
"Default",
"{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Of course by doing this the only controller and action you will ever be able to run in your application will be the HomeController and Index action. No other action or controller will be ever accessible as you don't provide any means in the url to specify them. So I would leave the default routes as is because they allow to handle 99% of the cases unless you have some specific requirements.
The other guys are correct. However they dont really tell you a way around it. One way to get better control of the routes is as follows
Do something like below in the Register routes method
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
var controllers = typeof(MvcApplication).Assembly.GetTypes().Where(t => !t.IsAbstract && t.Navigate(_ => _.BaseType).Any(_ => _ == typeof(Controller)));
foreach (var controller in controllers)
{
var actions = controller.GetMethods().Where(m => m.HasAttribute<RouteAttribute>()).Select(m => new { Method = m, Attribute = m.GetAttribute<RouteAttribute>() }).ToArray();
foreach (var action in actions.OrderBy(m => m.Attribute.Path.Count(c => c == '{')))
routes.MapRoute(string.Format("{0}.{1}", controller.Name, action.Method.Name), action.Attribute.Path.TrimStart('/'), new { controller = controller.Name.Replace("Controller", ""), action = action.Method.Name });
}
and then decorate your controller methods with a route attribute that defines exactly what the route should be. You have to make the route attribute yourself, it cna be pretty simple just an attribute with a string parameter . In this fashion you can set any controller method to have any route you like.
I'm having problems when using this route:
routes.MapRoute("ProductIndex", "pr-{key}", new { controller = "Home", action = "Product" });
When the key contains 'pr-', the route doesn't work.
Example: http://.../pr-my-product-key-with-pr-key
Routes don't work the way you want them to work, but it's easily converted
change your route to:
routes.MapRoute(
"ProductIndex",
"pr/{key}",
new { controller = "Home", action = "Product" });
and use:
http://.../pr/my-product-key-with-pr-key
or, if you really want to use that "way" you need to override the Initialization method of your main controller are check the link with StartWith() and redirect to the proper Controller.
In my routing I would like to have something like not found route handler.
For example I have created one mapping like
routes.MapRoute(
"default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id="" }
);
routes.MapRoute(
"Catchall",
"{*catchall}",
new { controller = "Home", action = "Lost" }
);
but when user inserts address something like /one/two/three/four/bla/bla it will be cached with the Catchall mapping.
But when user inserts something that should match with default mapping,
(like /one/two/ ,but this controller or action is not implemented)
I would want that Catchall mapping would accept this request,
because all other mappings failed. But instead of this I get an error.
Should I override some mapping handlers to catch the exception if controller or action getting an exception?
The issue here is that it's not the Route's responsibility to make sure that "one/two" maps to a file. That responsibility falls to the ViewEngine. Since "one/two" is a valid route, it will be chosen.
If you want to handle the error of an invalid route, what I would recommend you do is simply use the built in ErrorHandling "page" to display whatever message you would have done in the Catchall.
I don't think this is the best solution, but you could always be more specific on your routes:
routes.MapRoute(
"home and action",
"home/index/{id}",
new { controller = "Home", action = "Index", id="" }
);
... repeat for the rest of your actions ...
routes.MapRoute(
"article catch all",
"home/{article}",
new { controller = "Home", action = "ArticleSearcher", article="" }
);
This would attempt to match a direct action, and if no action is found, pass what would normally be the {action} part of the default route to the 'ArticleSearcher' action as an article string parameter.
The downside is having to explicitly create each controller/action route.