ASP.NET MVC 3 - Area URL Routing Problem - asp.net-mvc

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

Related

MVC Route with condition checking

I have routes below in my MVC4...
routes.MapRoute("Account", "Account/{action}", new { controller = "Account", action = "Index" });
routes.MapRoute("Admin", "Admin/{action}", new { controller = "Admin", action = "Index" });
routes.MapRoute("Custom", "{action}", new { controller = "Home", action = "Index" });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
...and need to find a way to route all url which has 2 symbol(www.domain.com/word2pdf) in url to action Index and pass url path(word2pdf) as api parameter.
public ActionResult Index(string api)
{
}
Any ideas how to do that?
As #Murali said, the proper way is to use Attribute Routing, but that's a new feature for mvc5 only.
If you want or have to stay on mvc4:
routes.MapRoute(name: "SomeRoutingName",
url: "{api}",
defaults: new { controller = "SomeControllerName", action = "Index"},
constraints: new { api= ".+2.+"});
Also just for some lol's, this should also work:
routes.MapRoute(name: "SomeRoutingName",
url: "{partA}2{partB}",
defaults: new { controller = "SomeControllerName", action = "Index" });
In Controller:
public ActionResult Index(string partA, string partB)
{
var api = string.Concat(partA,"2",partB);
}

Why my view action links including current action params in MVC3

I am working on a MVC3 application.
In my view I am using #Html.ActionLink for anchor links. Every thing working fine.
But those links are including the current url's params in the link.
If my current link is http://localhost:25466/Blog/all/2
Action link being generated are http://localhost:25466/Blog/Blog/shoes/2
In the above link actually I am not doing any thing to include '2' in the url. But still it is being added.
My route config are
routes.MapRoute(
"Blog", "Blog/Blog/{tag}/{id}",
new { controller = "Blog", action = "Blog", tag = UrlParameter.Optional,id="1" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = "1" },
constraints: new { id = #"\d+" }
);
And my actions are
public ActionResult All(int id)
{
var context = new BlogCore.DbContext.BlogContext();
var list = context.Get(id,20);
return View(list);
}
public ActionResult Blog(string tag,int id)
{
var context = new BlogCore.DbContext.BlogContext();
var list = context.Get(HttpUtility.UrlEncode(tag), id, 20);
return View("All", list);
}
And this is how I am using actionlink to generate anchor link
#Html.ActionLink(blog.PostTitle, "Blog", "Blog", new { tag = blog.PostRewriteName }, null)
How can I avoid 2 in the action link.
Thanks in advance.
I think you have to explicitly set that parameter, like:
#Html.ActionLink(blog.PostTitle, "Blog", "Blog", new { tag = blog.PostRewriteName, id = 1 }, null)
I believe the actual view dictionary is taken into account when creating a link with ActionLink.
MVC will use any variables from the current querystring when finding a route to generate a url. So your variable id will be included. To avoid this, you need to explicitly set id to null in the routedata you pass to the ActionLink helper:
#Html.ActionLink(blog.PostTitle, "Blog", "Blog", new { tag = blog.PostRewriteName, id = null }, null)

Adding another route in Asp.net mvc3 not working

I have this route map defined.
routes.MapRoute("default", // route name
"{controller}/{action}/{id}", // url with parameters
new { controller = "home", action = "index", id = UrlParameter.Optional }, // parameter defaults
new string[] { "mobilesurveys.mt.controllers" }
);
This will work perfectly. now I want to add another routemap
routes.MapRoute("couponreedem", // route name
"{controller}/{action}/{clientname}", // url with parameters
new { controller = "Rc", action = "index", id = UrlParameter.Optional }, // parameter defaults
new string[] { "mobilesurveys.mt.controllers" }
);
i have defined like this. Here Rc is my controller. and I am giving the url as
.com /Rc/Rc/sammy
and method in the controller defined as
public ActionResult Rc(string clientname)
{
viewModel =dataRc.ProductCategoryGet();
return View(viewModel);
}
clientname will be always null. How to add another route while the existing route not be disturbed.
Thanks.
It actually looks identical. But in case you want a new one you can try something like this, and it should be above the default one.
routes.MapRoute("couponreedem", // route name
"RC/{action}/{clientname}", // url with parameters
new { controller = "Rc", action = "index", clientname = UrlParameter.Optional }, // parameter defaults
new string[] { "mobilesurveys.mt.controllers" }
);
That will fix the route with RC/...
Also your action should be named Index
public ActionResult Index (string clientname)
{
viewModel =dataRc.ProductCategoryGet();
return View(viewModel);
}

How to control routing values

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

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.

Resources