How to control routing values - asp.net-mvc

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");

Related

Visual Studio MVC URL Rewrite

When I route to an address in MVC routing-config file, it works. But the URL in the bar doesn't update accordingly, it remains the same though contents are routed.
routes.MapRoute(
"User",
"Profile{id}",
new { controller = "Home", action = "Details" }
);
It re-routes localhost/profile4 to localhost/home/details, but the URL in the bar doesn't update.
You can create two actions in your controller with two routes and make redirect.
routes.MapRoute(
"User",
"Profile{id}",
new { controller = "Home", action = "ProfileRedirect" }
);
routes.MapRoute(
"Details",
"Details",
new { controller = "Home", action = "Details" }
);
public class HomeController: Controller
{
public ActionResult ProfileRedirect(int id)
{
return RedirectToAction("Details");
}
}
Another solution is make some HttpHandler and redirect requests on global level.

MVC Action has the same name, but diffrent controller

Routemap structure:
routes.MapRoute(
name: "NaturalStonesDetails",
url: "{lang}/natural-stones/{title}-{id}",
defaults: new { lang = "en", controller = "NaturalStones", action = "Details" }
);
routes.MapRoute(
name: "ProductCategorieList",
url: "{lang}/products/{title}-{id}",
defaults: new { lang = "en", controller = "Product", action = "Index" }
);
Link structure:
<a href="#Url.Action("Index", "Product", new { title = stoneguide.com.Models.DealerProduct.GetTitleUrlFormat(items.CategoryName), id = Convert.ToInt32(items.ID) })" style="padding:2px;">
Problem:
When I click on the link, go to the product page, which should go to NaturalStones page. I can not solve this problem, a kind.
Please help!
Your routing is quite neat and should work just fine with the code provided. I think you just got confused by which controller to use. So
#Url.Action("Index", "Product", new { title = "mytitle", id = "myid" })
returns /en/products/mytitle-myid which the routing correctly recognises as the request to Product controller, Index action with two parameters.
On the other hand
#Url.Action("Details", "NaturalStones", new { title = "mytitle", id = "myid" });
generates /en/natural-stones/mytitle-myid which is interpreted as request to NaturalStones, Details action with two parameters, and that's probably the one you want to use.
On the side note, providing title and id for Product, Index action is a bit awkward. By convention Index action usually returns a list of items, hence a reference to a specific id seems to be out of place. You might consider changing your routing to:
routes.MapRoute(
name: "NaturalStonesDetails",
url: "{lang}/natural-stones/{title}-{id}",
defaults: new { lang = "en", controller = "NaturalStones", action = "Details" }
);
routes.MapRoute(
name: "ProductCategorieList",
url: "{lang}/products",
defaults: new { lang = "en", controller = "Product", action = "Index" }
);
and then have controllers as follow:
public class ProductController : Controller
{
public ActionResult Index()
{
return View();
}
}
public class NaturalStonesController : Controller
{
public ActionResult Details(string title, string id)
{
return View();
}
}

ASP.NET MVC Routing question

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.

ASP.NET MVC 3 - Area URL Routing Problem

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" })

ASP.NET MVC Routing, Need help creating route

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.

Resources