for example you have custom route like this:
CustomerOrder/{action}/{id}/customerid={customerid}
the url became like this:
CustomerOrder/Create/customerid=1
how can you get the customerid and use it in the view?
<%= Html.MenuItem("Back to List", "Index", new { customerID = ???????? })%>
The equals sign is going to confuse url parsers since it has special meaning.
If you were to change your route to:
routes.MapRoute("CustomerOrder", "CustomerOrder/{action}/{id}",
new { controller = "Order", id = "" });
Then the following view code
<%= Html.MenuItem("Back to List", "Index", new { customerID = 5 })%>
Would create a link to:
CustomerOrder/Index/?customerid=5
which would work just fine.
Note
Given your current routing configuration, you would get the exact same results by deleting your CustomerOrder route since it is broken and you get the desired results from the default route.
Heres the code in Global.ASAX
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("CustomerOrders", "CustomerOrder/{action}/{id}/customerid={customerid}",
new { customerid= "{customerid}", controller = "CustomerOrder", action = "Index", id = "" });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" });
}
I'm new to MVC but I'm thinking the controller gets a customerid parameter and that could be passed to the View (via ViewData), no?
Related
Maybe I don't understand real purpose of asp mvc routing.
I created an application and now I need to fix my url's a to be more understandable.
For example I have area Cities with controller Home and action Index.
So here I need url like: localhost/London but with current routing I get localhost/cityPage/Home.
My question is can I somehow pass parameter like city name and make URL like I want?
This is my current default routing in Global.asax
routes.MapRoute(
"Default",
"{area}/{controller}/{action}/{id}",
new { area = "CityPage", controller = "Home", action = "Index", id = "" },
new string[] { "MyProject.Areas.Cities.Controllers" }).DataTokens.Add("area", "Cities");
New routing:
routes.MapRoute(null,
"CityPage/{cityName}",
new
{
area = "CityPage",
controller = "Home",
action = "Index"
}
);
routes.MapRoute(
"Default",
"{area}/{controller}/{action}/{id}",
new { area = "CityPage", controller = "Home", action = "Index", id = "" },
new string[] { "MyProject.WebUI.Areas.CityPage.Controllers" }).DataTokens.Add("area", "CityPage");
Example of link that I click
#Html.ActionLink("City London", "Index", "Home", new { cityName = "London" }, null)
In order to route the URL localhost/London to the Index action on the HomeController of the Cities area, you need a route like this:
routes.MapRoute(null,
"{id}",
new
{
area = "Cities", controller = "Home", action = "Index"
}
);
Be sure this route is declared before the "Default" route in your CitiesAreaRegistration.cs class.
However if you have a lot of other routes in your application, adding a general route like this can play havoc with other routes in the app. I suggest adding a URL prefix to separate this route from others in your application:
routes.MapRoute(null,
"cities/{id}",
new
{
area = "Cities", controller = "Home", action = "Index"
}
);
This will make your URL look like localhost/cities/London. Is that acceptable?
Update 1
Unless you completely remove your "Default" route definition, you will actually have multiple INBOUND routes that map to this action. You would have localhost/cities/London, localhost/cityPage/Home, localhost/cityPage/Home/Index, and localhost/cityPage/Home/Index/London all resolving to that action. However when MVC chooses to generate an OUTBOUND route, it will choose the first one -- localhost/cities/London.
Update 2
If you want your route parameter to be cityName, you would do this:
routes.MapRoute(null,
"cities/{cityName}",
new
{
area = "Cities", controller = "Home", action = "Index"
}
);
However you would then have to change the Index action on your Cities area's HomeController to have this signature:
public ActionResult Index(string cityName)
By changing the argument from id to cityName, you are telling MVC to pass this URL paramter / route segment to the action method.
Update 3
Is the name of your area "Cities" or "CityPage"? From previous code it looked like the name of your area was Cities.
If it is CitiesPage, try this for your action method:
#Html.ActionLink("City London", "Index", "Home",
new { area = "CityPage", cityName = "London" })
Final Answer
I just reproduced this in an MVC3 project, and it is working as expected:
Created a new area named "CityPage"
Added a HomeController with an Index action to the CityPage area
Added an Index view to the CityPage/Views/Home folder.
CityPageAreaRegistration.cs:
public class CityPageAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "CityPage";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(null,
"CityPage/{cityName}",
new { area = "CityPage", controller = "Home", action = "Index" }
);
//context.MapRoute(
// "CityPage_default",
// "CityPage/{controller}/{action}/{id}",
// new { action = "Index", id = UrlParameter.Optional }
//);
}
}
HomeController.cs:
public class HomeController : Controller
{
//
// GET: /CityPage/Home/
public ActionResult Index(string cityName)
{
return View();
}
}
Index.cshtml:
#{
ViewBag.Title = "Index";
}
<h2>
Index</h2>
#Html.ActionLink("City London", "Index", "Home",
new { area = "CityPage", cityName = "London" }, null)
Finally, here is the link generated by the action link:
City London
yes you can do this way but you have to do following thing
Make sure your route must register before generic route.
Get Information about RouteConstraint
http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-a-route-constraint-cs
http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-a-custom-route-constraint-cs
Just for example Try this way check your required url localhost/London
routes.MapRoute(
"Default",
"{id}",
new { area = "CityPage", controller = "Home", action = "Index", id = "" },
new string[] { "MyProject.Areas.Cities.Controllers" }).DataTokens.Add("area", "Cities");
I have simple question about MVC routing. How i can construct Html.ActionLink thhat generates following link http://mysite.com/phones/samsung
Now it's generates as http://mysite.com/phones/brand?brand=samsung
Also i want to avoid mentioning action name in URL
There is my code:
Route:
routes.MapRoute(null, "Phones/{brand}",
new { controller = "Phones", action = "Index", brand = UrlParameter.Optional });
Controller:
MySyteDBEntities ms = new MySyteDBEntities();
public ActionResult Index()
{
ViewBag.Brand = ms.Phones.Select(x => x.Brand).Distinct();
return View();
}
public ActionResult Brand(string brand)
{
ViewBag.Standard = ms.Phones.Where(x => x.Brand == brand).Select(x => x.Standard).Distinct();
return View();
}
Index View code:
#foreach (string item in ViewBag.Brand)
{
<div>#Html.ActionLink(item, "Brand", new { brand = item })</div>
}
In your MapRoute you have no space for an action, so asp.net will always use the default action "Index".
By default your routing would look like this:
routes.MapRoute(" Default", "{controller}"/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
You're missing the action part.
Routevalues in you actionlink which don't match parameters in your route, will be querystring parameters. So you need to change "category" to " brand" in your route.
Try this:
routes.MapRoute(null, "Phones/{brand}",
new { controller = "Phones", action = "Index", brand = UrlParameter.Optional });
and
#foreach (string item in ViewBag.Brand)
{
<div>#Html.ActionLink(item, "Index", "Phones", new { brand = item }, null)</div>
}
Be sure to call the controller explicit in your ActionLink, if the current view is mapped through another route, otherwise it doesn't recognize the brand parameter.
Try (this route should be registered before the default route, if you have one)
routes.MapRoute(
"Phones", // Route name
"Phones/{[^(Index)]brand}", // URL with parameters
new { controller = "Phones", action = "Brand", brand = "" } // Parameter defaults
);
With this, http://mysite.com/phones/ --> should go to Index Action and
http://mysite.com/phones/samsung --> should go to the Brand Action.
i'm found source of problem. I just need to remove last piece (brand optional parameter) in MapRoute. Hare is code:
routes.MapRoute(null, "Phones/{brand}", new { controller = "Phones", action = "Brand" });
routes.MapRoute(null, "Phones/{id}",
new { controller = "Phones", action = "Index", id= UrlParameter.Optional })
public ActionResult Brand(string id)
{
ViewBag.Standard = ms.Phones.Where(x => x.Brand == brand).Select(x => x.Standard).Distinct();
return View();
}
By using id as the parameter name, it will prevent the routing from using the querystring key value pairs.
Your parameterless GET and View code should still work without any changes.
If I remember correctly, the {brand} part needs to be included as is as part of your parameters:
routes.MapRoute(null, "Phones/{brand}",
new { controller = "Phones", action = "Index", brand = UrlParameter.Optional });
Just remember, it needs to go before any default routes.
I have an ASP.Net MVC 3 application. With 2 Areas:
Auth - handles all the authentication etc
Management - area for property management
In the Management Area I have a ManagementController and a PropertyController. The ManagementController does nothing, it only has a simple Index ActionResult than return a view.
The PropertyController has an Index ActionResult that returns a view with a list of properties as well as an Edit ActionResult that takes a propertyId as parameter. In the Property Index view i have a grid with the list of properties and an option to edit the property with the following code:
#Html.ActionLink("Edit", "Edit","Property", new { id = item.PropertyId })
In theory this should redirect to the Edit ActionResult of my Property Controller,however it redirects to the Index ActionResult of my ManagementController. My ManagementAreaRegistration file looks like this:
context.MapRoute(null, "management", new { controller = "management", action = "Index" });
context.MapRoute(null, "management/properties", new { controller = "Property", action = "Index" });
context.MapRoute(null, "management/properties/Edit/{propertyId}", new { controller = "Property", action = "Edit" });
And my global.asax's RegisterRoutes like this:
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
);
What am I missing, why would it redirect to the wrong controller and action?
Thanks in Advance!
You might need to specify the area in your route values parameter:
#Html.ActionLink("Edit", "Edit", "Property", new { id = item.PropertyID, area = "Management" }, new { })
Based on the constructor used for this call, you need to specify the last parameter, htmlAttributes, which, for your purposes, would be empty.
In your route you defined a parameter called propertyId not id:
context.MapRoute(null, "management/properties/Edit/{propertyId}", new { controller = "Property", action = "Edit" });
Try this:
#Html.ActionLink("Edit", "Edit","Property", new { propertyId = item.PropertyId })
I'd suggest using constraints.
For example my default route in the Global.asax is as follows:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { typeof(MyProject.Controllers.HomeController).Namespace });
Then in my area registration:
context.MapRoute(
"Search_default",
"Search/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { typeof(MyProject.Areas.Search.Controllers.HomeController).Namespace }
);
This means I get {AppName}/ as well as {AppName}/Search/Home and both work a treat.
From any Area to Home do following
Url.Action("Details", "User", new { #id = entityId, area = "" })
From Home to any Area
Url.Action("Details", "Order", new { #id = entityId, area = "Admin" })
My current Routing rules are
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(
"Admin", // Route name
"Admin/{controller}/{action}/{id}", // URL with parameters
new { controller = "Admin", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
I have several controllers that can only be accessed by the Admin. Currently I have a menu at:
/Admin/Index
Which lists a bunch of action links. Right now clicking any of those links redirects like this example:
/News/Index
But I need it to be like:
/Admin/News/Index
This current setup sort of works, but links on my homepage are being caught by the wrong rule and are going to, for example /Admin/Article/1 when they should be just /Article/1
I've searched StackOverflow for the answer, and found some that come close - but I still don't understand routing well enough to make use of their answers. Any assistance is appreciated.
EDIT
Here are a collection of links from the homepage that are being caught by the routing rules incorrectly
<div id="menucontainer">
<ul id="menu">
<li><%: Html.ActionLink(" ", "About", "Home", null, new { ID = "AboutMHN" })%></li>
<li><%: Html.ActionLink(" ", "Products", "Home", null, new { ID = "Products" })%></li>
<li><%: Html.ActionLink(" ", "HubLocator", "Home", null, new { ID = "HubLocator" })%></li>
<li><%: Html.ActionLink(" ", "ResellerProgram", "Home", null, new { ID = "ResellerProgram" })%></li>
<li><%: Html.ActionLink(" ", "ResellerLogin", "Home", null, new { ID = "ResellerLogin" })%></li>
<li><%: Html.ActionLink(" ", "ContactUs", "Home", null, new { ID = "ContactUs" })%></li>
</ul>
</div>
Also, my Admin controller just has an index action. I have controllers for all of the other 'Admin' pages, for example my NewsController has actions for index, create, edit, delete, for listing all the news articles, and performing crud operations. Am I structuring this incorrectly?
My AdminController.cs
[Authorize(Roles = "Administrator")]
public class AdminController : Controller
{
//
// GET: /Admin/
public ActionResult Index()
{
return View();
}
}
The Admin/Index this returns contains a menu with ActionLinks just like
<li><%: Html.ActionLink("News Articles", "Index", "News") %></li>
My NewsController.cs has Actions for performing CRUD operations. I would like the url to be
Admin/News/Edit/5
Instead of
News/Edit/5
Flip the two:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Admin", // Route name
"Admin/{controller}/{action}/{id}", // URL with parameters
new { controller = "Admin", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
If that doesn't work, add the code for the News menu links to your question.
The mapping is from top to bottom, the first route that can apply will be used. In your case you have Admin route under Default. Since Default can be used it will, therefore you should place Admin route above Default. The problem with that is that all will use that route. You need to be a bit more specific, perhaps you should remove {controller} so that only Admin actions will use that route. Need more info to better advise.
I needed to use Areas.
See: http://elegantcode.com/2010/03/13/asp-net-mvc-2-areas/
I created a new Area called Admin, renamed my AdminController.cs to MenuController.cs and placed all of the required controllers and views inside of the Admin area folder. Inside the Admin area folder there is a file called AdminAreaRegistration.cs which contains
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Admin";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new { controller= "Menu", action = "Index", id = UrlParameter.Optional }
);
}
}
I had to add in the controller = "Menu" so that when you navigate to /Admin it will take you to /Admin/Menu/Index by default. Now any of my controllers in the area folder are accessible like /Admin/News/Edit/5 and so forth. Thanks for your attempts, I should have been more clear that I am an absolute MVC noob and didn't know about Areas to begin with.
Hoping for some help after reading into MVC routing and not coming up with the answer myself.
I have the following routes registered:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
null,
"YourFeedback/Article/{resourceId}",
new { controller = "YourFeedback", action = "Index", contentTypeId = new Guid(ConfigurationManager.AppSettings["ArticleLibraryId"]) });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
I have the following ActionLink in an aspx view:
<%=Html.ActionLink("Your Feedback", "Article", "YourFeedback", new
{
resourceId = Model.ContentId.ResourceId
}, new { #class = "yourFeedback" })%>
My understanding of MVC routing is that this would render a anchor link with href of "/YourFeedback/Article/101" where 101 comes from Model.ContentId.ResourceId.
Yet the anchor link href is rendered as "YourFeedback/Article/resourceId=101".
Any ideas where I'm going wrong?
Thanks in advance.
This is because your actionlink will match the second route and not the first. The reason is that you have some strange default values in your first route. You have set the controller to "YourFeedback" and the action to "Index". That means that you will have to set that in your actionlink as well if you want to match that route.
To match the route you will have to use this actionlink:
<%=Html.ActionLink("Your Feedback", "Index", "YourFeedback", new
{
resourceId = Model.ContentId.ResourceId
}, new { #class = "yourFeedback" })%>
Or change the route.