why the second route.MapRoute of the same controller get a Null id - asp.net-mvc-4

I am beginner in ASP.NET MVC.
I have these routes
www.site.com/Afficher/Livre/1
www.site.com/Afficher/Auteur/2
I wrote a One controller with 2 actions. always the second action in the route.MapRoute always get a null in the id
the controller File : AfficherController
public string Auteurs()
{
return "liste des auteurs";
}
public string Auteur(int? idAuteur)
{
return "liste des livres de l'auteur "+idAuteur+" sont :";
}
public string Livre(int idlivre)
{
return "details du livre " + idlivre + " est : ";
}
the routing file
routes.MapRoute(
name: "afficherLivre",
url: "{controller}/{action}/{idlivre}",
defaults: new { controller = "Afficher", action = "Livre", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "AfficherAuteur",
url: "{controller}/{action}/{idAuteur}",
defaults: new { controller = "Afficher", action = "Auteur", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Afficher", action = "Auteurs", id = UrlParameter.Optional }
);

If you want to pass a parameter through the url, its name should be the same in three places in your ASP.NET code: in url and defaults parameters of MapRoute and also in action parameter. You changed url and action parameter, but forgot to replace id with idAuteur in defaults parameter. Your code should work if you'll do so.
But what is more important, it looks like you are creating own MapRoute for every action. You don't have to. Just leave MapRoute with name Default and change parameter names to id in actions Auteur and Livre.
Good luck!

Related

ASP.Net Routing: Customer ID not passing to action

see my url localhost:55831/Customers/Edit/1/ALFKI which i generate using #Html.RouteLink
#Html.RouteLink("Edit", "PageWithId",
new
{
controller = "Customers",
action = "Edit",
id = item.CustomerID,
page = ViewBag.CurrentPage
})
here is my routing code for PageWithId i tried two routing one after one but none work
routes.MapRoute(
name: "PageWithId",
url: "{controller}/{action}/{page}/{id}"
);
AND
routes.MapRoute(
name: "CustomerEditWithId",
url: "Customers/Edit/{page}/{id}",
defaults: new { controller = "Customers", action = "Edit" }
);
my all routing code
routes.MapRoute(
name: "PageWithSort",
url: "{controller}/{action}/{page}/{SortColumn}/{CurrentSort}",
defaults: new { action = "Index", page = UrlParameter.Optional, SortColumn = UrlParameter.Optional, CurrentSort = UrlParameter.Optional }
);
routes.MapRoute(
name: "PageWithId",
url: "{controller}/{action}/{page}/{id}"
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
please some one help because when i am clicking ob this link localhost:55831/Customers/Edit/1/ALFKI then customer id ALFKI is not passing to edit action. i debug the edit action code and found id is getting null always. i tried few routing for edit action but no luck still.
The order of routes matters. Routes are checked in order and the first matching route wins.
Because your first (PageWithSort) route matches any route with between 1 and 5 segments, then /Customers/Edit/1/ALFKI, which contains 4 segments matches, and no further routes are checked. And since ALFKI is being passed to the 4th segment named SortColumn, then it will only be bound to a parameter named SortColumn in your Edit() method (not to something named id)
As it stands, your PageWithId and Default routes are pointless since they can never be hit.
In additional, only the last parameter in a route definition can be marked with UrlParameter.Optional.
You need to create specific routes, and locate them in the correct order. Change your route definitions to (note I have omitted the PageWithSort route because its not clear what you want to do with that and it contains errors anyway)
routes.MapRoute(
name: "CustomerEditWithId",
url: "Customers/Edit/{page}/{id}",
defaults: new { controller = "Customers", action = "Edit" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Now any url that begins with /Customers/Edit and contains 2 additional segments will match the CustomerEditWithId route, and the 3rd segment will be bound to a parameter named page and the 4th segment will be bound to a parameter named id. Therefore your method in CustomersController should be
public ActionResult Edit(int page, string id)

How switch Route when using method Url.Action in UrlHelper MVC4

I have following define route ,
routes.MapRoute(
name: "sp",
url: "sp/{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "pm",
url: "pm/{controller}/{action}/{id}",
defaults: new { controller = "Account", action = "Login", id = UrlParameter.Optional }
);
when running, url of my project like to "http://example.com:7549/nhj/pm" and "http://example.com:7549/nhj/sp"
But, when using method Url.Action("Edit", "Product"), the Url has been generated by method Url.Action is always "http://example.com:7549/nhj/sp/Product/Edit".
How can I use the method Url.Action("Edit", "Product") to generate two different urls that are "http://example.com:7549/nhj/pm/Product/Edit" and "http://example.com:7549/nhj/sp/Product/Edit" match with 2 routes above.
Anyone can you help me??? Thanks
Use Url.RouteLink() that is using the route name when generating the Url:
// for SP route
Url.RouteUrl("sp", new { action = "Edit", controller = "Product" });
// for PM route
Url.RouteUrl("pm", new { action = "Edit", controller = "Product" });
When you're using the returned Url to redirect from action, use:
// for SP route
return RedirectToRoute("sp", new { action = "Edit", controller = "Product" });
// for PM route
return RedirectToRoute("pm", new { action = "Edit", controller = "Product" });
See MSDN.

MVC 4: Custom Routes

I see a lot of problems with MVC routes and I'm having a similar problem getting a route to match a URL.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute("Beer", "Beer/{beerid}", new { controller = "Beer", action = "Id", beerid = 0});
routes.MapRoute("Beer", "Beer/{beername}", new { controller = "Beer", action = "Name" });
BeerController Methods
public ActionResult Id(int beerid)
public ActionResult Name(string beername)
If I change the methods to the following,
public ActionResult Id(int? id)
public ActionResult Name(string id)
the default routing works with the following URLs:
http://localhost/Beer/Id/100
http://localhost/Beer/Name/Coors
But what I'm going for is just
http://localhost/Beer/100
http://localhost/Beer/Coors
Any ideas?
So a couple things here.
More specific routes should be placed before more general routes, because the first route that is matched will be used and routes are inspected in the order they are added.
If you plan on not providing the name of the action in your URL then you will need to do something to ensure the correct route is targeted so the correct default value will be used. In your case you could use a route constraint to distinguish between the two. Try changing your beer id route to this:
routes.MapRoute(
name: "Beer",
url: "Beer/{beerid}",
defaults: new { controller = "Beer", action = "Id", beerid = 0},
constraints: new { beerid = #"\d+" }
);
The constraint will ensure that the route only matches two-segment URLs where the second segment is composed of one or more digits. This route as well as your route for beer name should be placed before the default route.
UPDATE
My configuration seems to be yielding the results you want. The entirety of my RegisterRoutes method is as follows:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Id",
url: "Beer/{beerid}",
defaults: new { controller = "Beer", action = "Id", beerid = 0 },
constraints: new { beerid = #"\d+" }
);
routes.MapRoute(
name: "Name",
url: "Beer/{beername}",
defaults: new { controller = "Beer", action = "Name" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

ASP.NET MVC 4: One controller routing is not like the others

I have added a new controller, "LoggingController" to an MVC 4 application that already has several controllers.
Now I noticed that the routing behaviour for this controller is different from those that already existed.
For example, the following two urls work properly, as expected, and hit the "Index" method in BlogController.
http://localhost:56933/Blog/
http://localhost:56933/Blog/Index
So do all other controllers except the one I added:
http://localhost:56933/Logging/Index - works properly, hits the "Index" method in LoggingController
http://localhost:56933/Logging/ - returns "Server Error in '/' Application. The resource cannot be found."
Where should I start looking, beyond the obvious things?
Here is the Index signature from LoggingController
public ActionResult Index(int? page, string Period, string LoggerProviderName, string LogLevel, int? PageSize)
There is nothing specific to a certain controller in the MapRoute. Here is the full RouteConfig for reference:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
routes.MapRoute(
name: "Display",
url: "Post/{id}/{seofriendly}",
defaults: new { controller = "Post", action = "Display", id = UrlParameter.Optional, seofriendly = ""}
);
routes.MapRoute(
name: "SEOFriendly",
url: "{controller}/{action}/{id}/{seofriendly}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, seofriendly = "" }
);
routes.MapRoute(
name: "SEOFriendlyNoId",
url: "{controller}/{action}/{seofriendly}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, seofriendly = "" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Your Index method doesn't actually have a signature matched by any of your available routes. You'll have to either provide defaults to your Index action or add an additional route to the beginning of your route table to specify those defaults. For Example:
routes.MapRoute(
name: "LoggingDefaults",
url: "Logging/{Period}/{LoggerProviderName}/{LogLevel}/{page}/{PageSize}",
defaults: new {controller = "Logging",
action = "Index",
page = UrlParameter.Optional,
PageSize = UrlParameter.Optional,
LoggerProviderName = "SomeProvider",
Period = "SomePeriod",
LogLevel = "SomeLevel"}

MVC4 Route with Id and Index Action

I'm trying to accomplish the following and receiving the "resource not found" error for #2. Assuming because the routing is not configured correctly.
Desired URLs:
1) domain.com/Customer
2) domain.com/Customer/1 *Does Not Work
3) domain.com/Customer/All
public ActionResult Index(int? id)
{
var viewModel = new CustomerViewModel();
if (!id.HasValue)
id = 1; // ToDo: Current Logged In Customer Id
viewModel.Load(id.Value);
return View(viewModel);
}
public ActionResult All()
{
return View(CustomerModel.All());
}
My Route Config has the default route setup and I've tried adding an additional route to no avail.
routes.MapRoute(
name: "Customer",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Customer", action = "Index", id = UrlParameter.Optional }
);
I've excluded my attempts at setting up a new route since it doesn't work.
Your route would normalize out to domain.com/Customer/Index/1. When you have subsequent parts of the route, you can't eliminate an earlier component just because its value will be the default. In this case, it's looking for an action named "1" which it can't find.
Edit:
If your desired route is domain.com/Customer/ID, then you can add such a route to your route table:
routes.MapRoute(
name: "CustomerAll",
url: "Customer/All",
defaults: new { controller = "Customer", action = "All" }
);
routes.MapRoute(
name: "CustomerByID",
url: "Customer/{id}",
defaults: new { controller = "Customer", action = "Index" }
);
These more-specific routes should come before your default route.
try to add this route before the default one
routes.MapRoute(
name: "Customer",
url: "Customers/{id}",
defaults: new { controller = "Customer", action = "Index", id = UrlParameter.Optional }
);
and note that the url starts with Customers not Customer.
and your desired URL will be : domain.com/Customers/1 instead of domain.com/Customer/1