Routing in MVC not finding the new url - asp.net-mvc

I Am not understanding this concept, so after doing a manual and read a few articles I decide to ask you all.
I want to change, just for testing, from:
localhost/Home/List
To:
localhost/Custom/List
So my:
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute("Custom", "Custom/List/",
new
{
Controller = "Home",
Action = "List"
});
}
But is is not working. The first url still working but the second one is not finding anything.
Thanks

Routes are matched in order and your Default route matches any url with between zero to 3 segments, so ../Custom/List calls the List() method of CustomController.
You need to change the order of your routes so that the Custom is before the DefaultRoute. ../Custom/List will then match that route first and go to the List() method of HomeController

Related

Some basic questions about Routing in ASP.NET MVC

I'm trying to learn ASP.NET MVC and have a few questions about routing.
Print is a controller, with a Show action, that takes a parameter and returns it back as string.
Consider the code
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapRoute(
name: "Print",
url: "Print/{action}/{id}",
defaults: new { controller = "Print", action = "Show", id = UrlParameter.Optional });
}
Why do I get a 404 error when I try host:xxxxx/Print/xxx...? Shouldn't it take me to the Show action?
Also if I set url:Print, and try host:xxxxx/Print I get the same error. It should take me to the Show action.
Similarly if I set url:Print/{action}/{id} and try host:xxxxx/Print/Show it gives the same error, even though the parameter is optional, and should return blank?
But if I interchange the two routes such that the Print route is first in precedence and Home/Index in second, I do not get any errors in any cases? host:xxxxx/Print shows blank, host:xxxxx/Print/Show shows blank and host:xxxxx/Print/Show/xxx... returns some value.
Why do I get errors if I set it as the second route?
Change the routes register order to:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Print",
url: "Print/{action}/{id}",
defaults: new { controller = "Print", action = "Show", id = UrlParameter.Optional });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
The routes in the RegisterRoutes() are analyzed in order they are added to the routes. The Default route pattern is universal, therefore the second doesn't work. The MVC trying to find the Show action in the Home controller and does not finding it. Therefore it report the 404 error.
If look at the RouteCollection declaration it is inherited from IList<T>. So, the routes analyzed in order they added to the routes table.
Any your routes should be added before the Default route.

Attribute Routing over Convention-based Routing in MVC, which one would be called first?

I am assuming that the convention routing would be added to the route table first because it is getting registered in the global.asax file like this
RouteConfig.RegisterRoutes(RouteTable.Routes);
Now I have a route like this in the route.config
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapMvcAttributeRoutes();
}
and I have an attribute route like this
[Route("students/{id?}")]
public ActionResult Index(int? id)
{
return View(id);
}
Now when I use the URL
localhost:4200//students
The students route is getting called successfully but when I use the route like this
localhost:4200//students/40
I get error, I don't know the reason why. When I remove the route from RouteConfig class I am able to call it successfully.
Can anyone explain me why and how?
In your original example the URL localhost:4200//students/40 is being matched to the url: "{controller}/{action}/{id}", convention-based route template.
But since there is no action called 40 it will fail.
Now because it has already matched a route, it will not check any further for other matches so you will end up with Not Found error.
In Asp.Net MVC, routes are called in the order they are added to the routing table. First match wins and it does not do any further checks.
Targeted attribute routes are usually added before more general convention based routes to avoid route conflicts like the one experienced in your example.
public static void RegisterRoutes(RouteCollection routes) {
//Attribute routes
routes.MapMvcAttributeRoutes();
//Convention-based routes.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

Custom Routing not working in MVC5

First of all, I am very new to MVC and this is my first ever project.
I am trying to achieve the custom routing URL like the following:
http://mywebsite/MDT/Index/ADC00301SB
Similar to...
http://mywebsite/{Controller}/{Action}/{query}
In my RouteConfig.cs, I put the following
routes.MapRoute(
name: "SearchComputer",
url: "{controller}/{action}/{query}",
defaults: new { controller = "MDT", action = "Index", query = UrlParameter.Optional }
);
In My MDTController.cs, I have the following code
public ActionResult Index(string query)
{
Utils.Debug(query);
if (string.IsNullOrEmpty(query) == false)
{
//Load data and return view
//Remove Codes for clarification
}
return View();
}
But it's not working and I always get NULL value in query if I used http://mywebsite/MDT/Index/ADC00301SB
But if I used http://mywebsite/MDT?query=ADC00301SB, it's working fine and it hits the Controller Index method.
Could you please let me know how I could map the routing correctly?
You should add your MapRoute before default MapRoute, because order in RouteCollection is important
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "SearchComputer",
url: "{controller}/{action}/{query}",
defaults: new { controller = "MDT", action = "Index", query = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
One issue that I have encountered is that placing your route below the default route will cause the default to be hit, not your custom route.
So place it above the default route and it will work.
A detailed explanation from MSDN:
The order in which Route objects appear in the Routes collection is significant. Route matching is tried from the first route to the last route in the collection. When a match occurs, no more routes are evaluated. In general, add routes to the Routes property in order from the most specific route definitions to least specific ones.
Adding Routes to an MVC Application.
You can change it to
routes.MapRoute(
name: "SearchComputer",
url: "MDT/{action}/{query}",
defaults: new { controller = "MDT", action = "Index", query = UrlParameter.Optional }
);

Adding routing in MVC 5

I have a requirement in which I have to map the below url
/amer/us/en/ = Home controller
/amer/us/en/login/index = Home controller
/amer/us/en/confirmation = Confirmation controller
along with the regular default action.
Eg if user goes to
http:\\test.com --> http://test/home/index
http:\\test.com/amer/us/en/login/index --> http://test/home/index
http:\\test.com/amer/us/en/ --> http://test/home/index
I was looking into attribute routing and so I added the below code in HomeController
[RoutePrefix("amer/us/en/")]
[Route("{action=index}")]
public class HomeController : Controller
{
}
and I am getting this error
The route prefix 'amer/us/en/' on the controller named 'Home' cannot begin or end with a forward slash and also the default routing is not working now so http://test.com is not loading anything. Below is my default RouteConfig class.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Very new to MVC. Can someone tell me what I am doing wrong here.
Routing in MVC works either by defining your routes in the RouteConfig class or by attribute routing (or you can use Areas). Routing with RouteConfig works with the order you define the routes with. When a request comes, MVC will try your routes from top to bottom and execute the first one that it can match with the requested url. So the routing need in your example can be achieved by:
routes.MapRoute(
name: "RootLogin",
url: "amer/us/en/login/index/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "DefaultAmer",
url: "amer/us/en/{controller}/{action}{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
this will map login as a special route and all the other /amer/us/en/ routes will go to whatever controller comes after and whatever action of it. The last route, if the request does not start with /amer/us/en will perform the default behavior.
Looks like, however, you want to define /amer/us/en/ as an Area, so you might want to take a look into that as well.

ASP.NET MVC 4 Routing Query - Passing query-string to Index Action

I have a controller with an index action.
public ActionResult Index(int id = 0)
{
return view();
}
I wish to pass id into the index action, however it doesnt appear to work in the same way as the details action.
e.g. if I want to pass id 4 into the index action, I have to visit url:
http://localhost:8765/ControllerName/?id=4
With the details Action... I can do this.
http://localhost:8765/ControllerName/Details/4
What I want to do with Index is something like...
http://localhost:8765/ControllerName/4
When I visit this url, I get an error:
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /fix/1
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.17929
Is this possible? How can I get MVC to automatically treat the index action in the same way as the details one?
Thanks
UPDATE - MY CURRENT ROUTES CONFIG
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
UPDATE NEW RouteConfig Class still doesn't work when I visit localhost:1234/Fix/3
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "FixIndexWithParam",
url: "Fix/{id}",
defaults: new { controller = "Fix", action = "Index", id = UrlParameter.Optional });
}
}
Update It's worth pointing out, /ControllerName/Index/4 should work with the default route.
With the default route there, it expects the second parameter to be the controller name.
So with the Default Route /ControllerName/4 is being interpereted as ControllerNameController Action 4, which of course does not exist.
If you add
routes.MapRoute(
name: "IndexWithParam",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
before the default one it would allow
/Home/4 to be routed to HomeController action Index with id=4
I have't tested this, it may conflict with the default. You may need to specify the controller explicitly in the route, ie:
routes.MapRoute(
name: "HomeIndexWithParam",
url: "Home/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
(Obviously, replace Home with whatever controller you're actually wanting to route to)

Resources