HtmlHelper ActionLink omits area (asp.net mvc 4) - asp.net-mvc

I have problem with generation of links
I have an Area named "Administration", it also has a HomeController as a root,
In the masterpage
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("Admin", "Index", "Home", new {area = "Administration"})</li>
Also I inherited From Route, and the method GetVirtualPath accepts the parameter values
which omits area key, and passes only controller and action.
Where did I go wrong?

You use incorrect overload. You should be using LinkExtensions.ActionLink Method (HtmlHelper, String, String, String, Object, Object) (note the last parameter at the end)
#Html.ActionLink("Admin", "Index", "Home", new {area = "Administration"}, null)

<li>#Html.ActionLink("Home", "Index", "Home", new {area = ""}, null)</li>
<li>#Html.ActionLink("Admin", "Index", "Home", new {area = "Administration"}, null)</li>

The problem solved, and was in DataTokens. I was defining area only for areas, but not for controllers in the root.
Now it works. Thanks!

Related

ASP.NET MVC - keep links to the root folder

I am trying to link inside the same folder, I have the following structure
/Home/Index
/Home/About
/Home/Contact
When I start the webpage, I link to the Index, so I get the webpage on the screen: www.example.com.
Now I would like to link to another page so I get: www.example.com/Contact.html (or even better I would like to get www.example.com/Contact) however I get www.example.com/Home/Contact.
I use this as an action link:
<li class="pure-menu-item pure-menu-selected">#Html.ActionLink("Contact us", "Contact", "Home")</li>
This is my route:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
What could I change to get the desired result?
Decorate you Contact action with a RouteAttribute and pass it the desired route as parameter (i.e. "Contact")
Edit
Here's an example HomeController using the RouteAttribute:
public class HomeController
: Controller
{
public IActionResult Home()
{
return this.View();
}
[Route("Contact")]
public IActionResult Contact()
{
return this.View();
}
}
Note that you can use the RouteAttribute on Controllers, too. For instance, if I added a Route("Test") attribute on the HomeController, all of my controllers actions would look like: "/Test/[ActionRoute]".
In your views, you can use the following syntax, instead of using the old #Html.ActionLink tag helper:
<li class="pure-menu-item pure-menu-selected">
<a asp-controller="Home" asp-action="Contact">Contact Us</a>
</li>
In my opinion, those attribute tag helpers are way cleaner and html friendly ;)
i was able to fix it with some good reading and searching and this is what i came up with:
i added this to the routeConfig for each link to a html page:
routes.MapRoute("Index", "Index", new { controller = "Home", action = "Index" });
routes.MapRoute("About", "About", new { controller = "Home", action = "About" });
routes.MapRoute("Contact", "Contact", new { controller = "Home", action = "Contact" });
and instead of using an action link i use a route link:
<li class="pure-menu-item">#Html.RouteLink("About us", "About")</li>
this gives the desired result: www.example.com/About

Wrong parameter in Query ActionLink MVC [duplicate]

I'm VERY confused as to why this code
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" })
results in this link:
<a hidefocus="hidefocus" href="/Home/About?Length=4">About</a>
The hidefocus part is what I was aiming to achieve, but where does the ?Length=4 come from?
The Length=4 is coming from an attempt to serialize a string object. Your code is running this ActionLink method:
public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)
This takes a string object "Home" for routeValues, which the MVC plumbing searches for public properties turning them into route values. In the case of a string object, the only public property is Length, and since there will be no routes defined with a Length parameter it appends the property name and value as a query string parameter. You'll probably find if you run this from a page not on HomeController it will throw an error about a missing About action method. Try using the following:
Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
The way I solved this is was adding a null to the fourth parameter before the anonymous declaration (new {}) so that it uses the following method overload: (linkText, actionName, controllerName, routeValues, htmlAttributes):
Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
You forgot to add the HTMLAttributes parm.
This will work without any changes:
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
The parameters to ActionLink are not correct, it's attempting to use the "Home" value as a route value, instead of the anonymous type.
I believe you just need to add new { } or null as the last parameter.
EDIT: Just re-read the post and realized you'll likely want to specify null as the second last parameter, not the last.
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })
This will take the overload:
string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes
Just remove "Home" (name of the controller) so that the code would be:
Html.ActionLink("About", "About", new { hidefocus = "hidefocus" })
Kindly use right overloaded method with five (5) parameters. Example:
#using (#Ajax.BeginForm("Register", "Account", null,
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "OnSuccess",
OnFailure = "OnFailure",
OnBegin = "OnBegin",
OnComplete = "OnComplete"
}, new { #class = "form-login" }))
This worked fine
#Html.ActionLink("Informationen", "About", "Home", new { area = "" }, new { #class = "nav-link" })
added new { area = "" }.
As Jonathon Watney pointed out in a comment, this also goes for
Html.BeginForm()
methods. In my case, I was in a Create.cshtml targeting the post request of the corresponding controller + Create action and had
using (Html.BeginForm("Create")) {
#Html.AntiForgeryToken()
...
}
which was adding the querystring "?Length=6" to the form action when rendered. Hinted by roryf's approved answer and realizing the string length of "Create" is 6, I finally solved this by removing the explicit action specification:
using (Html.BeginForm()) {
#Html.AntiForgeryToken()
...
}
With attribute names:
#Html.ActionLink(linkText: "SomeText", actionName: "SomeAction", controllerName: "SomeControllerName", routeValues: new { parameterName = parameterValue}, htmlAttributes: null)
Perhaps others had the same issue and need to supply a class value via HTMLAttributes parm.
Here's my solution:
#Html.ActionLink("About", "About", new { controller = "Home", area = "" }, new { hidefocus = "hidefocus", #class = "nav-item nav-link" })
Search for an answer to my question landed me here, basically it's the selection of correct overload of #Html.ActionLink
which matters.
I was selecting an overload which didn't exist, (without the last null), and MVC had no such overload, resulting in a false URL something like the OP mentioned.
A personal note: you can use anonymous types doesn't mean you can use any of the overloads- which do not exist? - make certain: it has to be defined!
- Came here in times of MVC 5.2

wrong url with html.actionlink

I was made paging system. Everything is OK.
After click 2nd page all homepage links changing.
#Html.ActionLink("Home page", "Index", "Home") //This is standard routing without values.
I was added paging links to end of page.
#Html.ActionLink("2", "Index", "Home", New With {.id = 2}, Nothing) //This works good too.
My problem is when I click to 2nd or more page (e.g : www.site.com/Home/Index/2) my all homepage links converting to
Home page
same this.
How I can resolve this problem?
When you click on the 2nd page the {.id = 2} will be part of your RouteData. And because your routing probably looks like this: (in Gloabal.asax)
routes.MapRoute( _
"Default", _
"{controller}/{action}/{id}", _
New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional} _
)
ASP.NET MVC will use this route for the generated links. So it will include Id = 2. To fix this you need to explicitly override it when it's not needed:
#Html.ActionLink("Home page", "Index", "Home", New With {.id = ""}, Nothing)

How to hide the home controller path in action links

Using the out of the box MVC application the action links under the Home controller are rendered as follows
#Html.ActionLink("Home", "Index", "Home") > /
#Html.ActionLink("About", "About", "Home") > /Home/About
How do i make all action links that falls into the HomeController to hide the "Home" in the link paths.
e.g
#Html.ActionLink("About", "About", "Home") > /About
#Html.ActionLink("Contact", "Contact", "Home") > /Contact
#Html.ActionLink("Sitemap", "Sitemap", "Home") > /Sitemap
#Html.ActionLink("Terms", "Terms", "Home") > /Terms
Thanks
You can set the controller in your route part and remove it from the url. Something like this:
routes.MapRoute("", "/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
Look at this answer also.
You can create different routes in the RouteConfig class as followed:
routes.MapRoute(
name: "AboutUs",
url: "about-us",
defaults: new { controller = "Home", action = "AboutUs" }
);
This way, when the URL is /about-us it's going to call the AboutUs action in Home controller.

Why does Html.ActionLink render "?Length=4"

I'm VERY confused as to why this code
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" })
results in this link:
<a hidefocus="hidefocus" href="/Home/About?Length=4">About</a>
The hidefocus part is what I was aiming to achieve, but where does the ?Length=4 come from?
The Length=4 is coming from an attempt to serialize a string object. Your code is running this ActionLink method:
public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)
This takes a string object "Home" for routeValues, which the MVC plumbing searches for public properties turning them into route values. In the case of a string object, the only public property is Length, and since there will be no routes defined with a Length parameter it appends the property name and value as a query string parameter. You'll probably find if you run this from a page not on HomeController it will throw an error about a missing About action method. Try using the following:
Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
The way I solved this is was adding a null to the fourth parameter before the anonymous declaration (new {}) so that it uses the following method overload: (linkText, actionName, controllerName, routeValues, htmlAttributes):
Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
You forgot to add the HTMLAttributes parm.
This will work without any changes:
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
The parameters to ActionLink are not correct, it's attempting to use the "Home" value as a route value, instead of the anonymous type.
I believe you just need to add new { } or null as the last parameter.
EDIT: Just re-read the post and realized you'll likely want to specify null as the second last parameter, not the last.
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })
This will take the overload:
string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes
Just remove "Home" (name of the controller) so that the code would be:
Html.ActionLink("About", "About", new { hidefocus = "hidefocus" })
Kindly use right overloaded method with five (5) parameters. Example:
#using (#Ajax.BeginForm("Register", "Account", null,
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = "OnSuccess",
OnFailure = "OnFailure",
OnBegin = "OnBegin",
OnComplete = "OnComplete"
}, new { #class = "form-login" }))
This worked fine
#Html.ActionLink("Informationen", "About", "Home", new { area = "" }, new { #class = "nav-link" })
added new { area = "" }.
As Jonathon Watney pointed out in a comment, this also goes for
Html.BeginForm()
methods. In my case, I was in a Create.cshtml targeting the post request of the corresponding controller + Create action and had
using (Html.BeginForm("Create")) {
#Html.AntiForgeryToken()
...
}
which was adding the querystring "?Length=6" to the form action when rendered. Hinted by roryf's approved answer and realizing the string length of "Create" is 6, I finally solved this by removing the explicit action specification:
using (Html.BeginForm()) {
#Html.AntiForgeryToken()
...
}
With attribute names:
#Html.ActionLink(linkText: "SomeText", actionName: "SomeAction", controllerName: "SomeControllerName", routeValues: new { parameterName = parameterValue}, htmlAttributes: null)
Perhaps others had the same issue and need to supply a class value via HTMLAttributes parm.
Here's my solution:
#Html.ActionLink("About", "About", new { controller = "Home", area = "" }, new { hidefocus = "hidefocus", #class = "nav-item nav-link" })
Search for an answer to my question landed me here, basically it's the selection of correct overload of #Html.ActionLink
which matters.
I was selecting an overload which didn't exist, (without the last null), and MVC had no such overload, resulting in a false URL something like the OP mentioned.
A personal note: you can use anonymous types doesn't mean you can use any of the overloads- which do not exist? - make certain: it has to be defined!
- Came here in times of MVC 5.2

Resources