Why my view action links including current action params in MVC3 - asp.net-mvc

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)

Related

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();
}
}

Using routes.MapPath to accommodate missing URL parameter

I have an MVC website which used to use URLs in the standard format of: Controller/Action.
Recently, I have changed it to: Site/Controller/Action.
The problem is, there are several links to my site out there which follow the old format, and I want to redirect them accordingly.
for example: mydomain.com/Home/CustomerSearch now should go to mydomain.com/Online/Home/CustomerSearch
whereas: mydomain.com/AffiliatesHome/CustomerSearch now should go to mydomain.com/Affiliate/AffiliatesHome/CustomerSearch
How can I get it to handle the redirecting by putting in the extra routing, depending on the link they came in by?
The current routing I am using is:
routes.MapRoute(
"Default", // Route name
"{site}/{controller}/{action}/{id}",
new {site="IS", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Since I do not really see an schema in your old to new URL mapping I would suggest to add routes that match the old Controller/Action Schema and map them to the new Site/Controller/Action route schema.
So you could add the following routes
routes.MapRoute(
"LegacyHome",
"Home/{action}/{id}",
new { site="Online", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"LegacyAffiliates",
"AffiliatesHome/{action}/{id}",
new { site="Affiliate", controller = "AffiliatesHome", action = "Index", id = UrlParameter.Optional }
);
From an SEO standpoint this is not ideal because you have different URLs for the same page. A permanent redirect via status code 301 and the new URL passed in the location is better suited.
You could build a redirect controller and use the legacy routes to map legacy URLs to the redirect controller somehow like this
routes.MapRoute(
"LegacyHome",
"Home/{newAction}/{id}",
new { controller = "Redirect", action = "Redirect", newSite = "Online", newController="Home", newAction = "Index", id = UrlParameter.Optional }
);
Code of the redirect controller
public class RedirectController : Controller
{
public ActionResult Redirect(string newSite, string newController, string newAction)
{
var routeValues = new RouteValueDictionary(
new
{
site = newSite,
controller = newController,
action = newAction
});
if (RouteData.Values["id"] != null)
{
routeValues.Add("id", RouteData.Values["id"]);
}
return RedirectToRoutePermanent(routeValues);
}
}

Generate semantic URL with asp.net mvc4 ActionLink in Razor views

I have a below setup in the controller for Public facing web page
Company -> About -> Partners ( which i want to be accessed as Company/About/Partners )
Action Method
public about(string category)
{
ViewBag.Category = category;
return View();
}
Generation of the link is done as below which is giving me the wrong URL
#Html.ActionLink("Partners & Investors", "About", "Company",new { Category = "Partners" },null)
Wrong Url
Company/About?Category=Partners%20and%20Investors
So the question is how does one generate the correct url that i wanted. What should i do ?
Urls will be generated automatically when you create new route and put it on correct position.
Add
Something like this:
routes.MapRoute(
"Category",
"Company/About/{category}",
new { controller = "Company", action = "About", category = "default" }
);
// default
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Also look at this link: Advanced Routing

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

Resources