#Html.ActionLink not Rendering as Expected - asp.net-mvc

I have this in my Global.asax.cs:
routes.MapRoute(
"User",
"User/{username}/{action}",
new { controller = "User", action = "Index", username = "*" }
);
Then on my _Layout.cshtml I have this code:
<ul id="menu">
#if (!String.IsNullOrEmpty(Context.User.Identity.Name))
{
<li>#Html.ActionLink("Home", "Home", new { controller = "User" }, new { username = Context.User.Identity.Name })</li>
}
</ul>
</div>
</div>
The thing is, it will render the link properly the first time it swings through here. (Link will be /User/rob/Home where "rob" is a username. If I navigate elsewhere on the page and then click back on my link, the link is rendered as /User/*/Home. When I step through the code, Context.User.Identity.Name is correct every time.
Am I missing something really basic here? I'm not sure what to search for.

That's exactly what you should expect given that route. You don't specify username in the route values dictionary but in the HTML attributes, so it takes the default from the route, *. You should be using the signature that allows you to specify both the controller and the action as strings with additional route values in the dictionary.
#if (!String.IsNullOrEmpty(Context.User.Identity.Name))
{
<li>#Html.ActionLink("Home", "Home", "User" new { username = Context.User.Identity.Name }, null )</li>
}

Related

Routing with multiple parameters in ASP.NET MVC

I'm new to ASP.NET and I'm struggling to understand how routing works. In my project I've managed to create routing for; login, logout, create new user and delete user.
I've created cards containing dates and a stretched-link with the purpose to act as a booking-table (click on a card to book the said time).
View code:
When I click on the link I want to pass forward the user as a string and the time as DateTime(or string). If I replace the url.action argument "TimeSlot.ToString()" with null my routing "works", but of course with the exception that only the user is passed forward to my controller.
#model MyProject.Models.BookingSchedule
...
<div class="row" style="padding-top: 50px; border:solid">
#{ foreach (var TimeSlot in Model.GetAllAvailableTimes())
{
<div class="col-sm-1" style="padding:10px">
<div class="card text-md-center">
<a class="stretched-link" href="#Url.Action("BookTime","Booking",new { user = Model.UserName }, TimeSlot.ToString())">#TimeSlot.ToString()</a>
</div>
</div>
}
}
</div>
Controller:
So far I've just created a mockup code for my controller, its only purpose is to reload my view and redisplay available times together with the time I've booked. For now, I just want to see if my routing passes all parameters to my controller (which it doesn't):
public ActionResult BookTime(string user, string Time)
{
return View("BookingPage", bookingSchedule(user));
}
Routing:
routes.MapRoute(
"BookTime",
"Booking/{Action}/{user}/{time}",
new { controller = "Booking", action = "BookTime", user = UrlParameter.Optional, time = UrlParameter.Optional }
);
When I run my code I get the following error:
How do I create a routing with two or more parameters and what are the key aspects that I need to keep in mind?
I've tried to get knowledge from the Microsoft-docs but as I've not yet managed to overcome this issue I'm hoping someone here could explain it.
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-6.0#attribute-routing
If I set my href to "href="#Url.Action("BookTime","Booking",new { user = Model.UserName }, TimeSlot.ToString())" then I get the error message above.
If I set href to href="#Url.Action("BookTime","Booking",new { user = Model.UserName }, null)" it will route correctly but of course it doesn't pass my parameters (see photo below):
(in the picture/code above I changed the name of the controller to BookingPage as is the name of my viewpage. I did this to rule out any routing issues)
just add an attribute route
[Route("~/Booking/BookTime/{user?}/{time?}",
public ActionResult BookTime(string user, string Time)
{
return View("BookingPage", bookingSchedule(user));
}
and fix your link
href= ( "Book Time",
"BookTime",
"Booking",
new { user = Model.UserName, time = TimeSlot.ToString() },
null )

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

working with bootstrap scrollspy in MVC 5

I am using Bootstrap ScrollSpy in MVC 5 application.
ScrollSpy works fine with plain html and jquery but I want to implement the same thing in MVC 5.
<li>About</li>
<li>Contact</li>
the above code works fine, but when I tried to implement the same thing in MVC I somehow get confused.
<li> #Html.ActionLink("About", null, null, null, new { #class = "hidden-xs" })</li>
<li> #Html.ActionLink("Contact", null,null, null, new { #class = "hidden-xs" })</li>
This is not working as expected as its trying to redirect to specified actionname or I may be doing something wrong.
Suggest something.
Requirement for Bootstrap scrollspy to work, the scrollable elements must match the ID of the links.
Here <li>Contact</li> should match div with id <div id="contact">
Using Mvc:
<li> #Html.ActionLink("Contact", "Index", "Home", null, null, "contact", null, null)</li>
<li> Contact</li>
Check difference between HTML.ActionLink vs Url.Action here.
So finally in server side both generates url with trailing slash before hash(#) as shown below:
Contact
And thus above link doesn't match div with id <div id="contact"> because of / before #
Solution Using Mvc:
Create Custom UrlHelper
Create a folder named Helpers and add a class named UrlExtensions finally add below code:
public static class UrlExtensions
{
public static string HashAnchorLinks(this UrlHelper url, string hashLinkName)
{
string hashAnchorLink = string.Format("#{0}", hashLinkName);
return hashAnchorLink;
}
}
In View:
#using YourProjectName.Helpers;
<li> About</li>
<li> Contact</li>
Note:
Best solution would be using plain html as you did before, instead of using server to return the hash link.
References:
1.
2.
3.
Your not passing the right parameters in into the ActionLink().
#Html.ActionLink("About", "Home", "About", new object { }, new { #class = "hidden-xs"})
#Html.ActionLink("Contact", "Home", "Contact", new object { }, new { #class = "hidden-xs"})
Here is a explanation of the function.

How to use query string in asp.net mvc layout page

I am getting confuse in understanding the query string and routing concept in asp.net mvc, and I will appreciate if some one can please help.
My problem is:
I have a login page where user will enter the Username, password and Id. After successful login I like to take the Id and pass it to my Profile page. Now profile page is part of layout page along with two other links.
<nav class="main">
<ul class="menu" >
<li>#Html.ActionLink("Profile", MVC.Profile.Index(), new { Id = Request.QueryString["Id"].ToString() })</li>
<li>#Html.ActionLink("Configuration", MVC.Configuration.Index(),new { Id = Request.QueryString["Id"].ToString() })</li>
<li>#Html.ActionLink("Transaction", MVC.Transaction.Index(), new { Id = Request.QueryString["Id"].ToString() })</li>
</ul>
</nav>
From my login page I am using the following code to Redirect the user to Profile page.
return RedirectToAction("Index", "Profile", new { Id =
viewModel.Id });
Now how can i pass the same value to configuration and transaction page, they are just action links on layout page.I thought of using Request.QueryString like below:
new { Id = Request.QueryString["Id"].ToString()
but this is throwing object reference exception.
my routing look like this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional });
Thanks in advance.
So after you are redirecting to the Index action of your Profile controller, make sure your action takes in a int parameter like below and return it to the Profile view:
public ActionResult Index(int id)
{
return View(id);
}
Render your links in the Profile's Index view like below:
#model int
<nav class="main">
<ul class="menu" >
<li>#Html.ActionLink("Profile", "Index", new { Id = #Model })</li>
<li>#Html.ActionLink("Configuration", "Index",new { Id = #Model })</li>
<li>#Html.ActionLink("Transaction", "Index", new { Id = #Model })</li>
</ul>
</nav>
Let me know if you need more clarification.

Routing issue with MVC

I'm working with MVC 3 and have an issue. Instead of giving mydomain/mydirectory/item like I expected I get this:
mydomain/mydirectory/list?animal=quack.
Here's the route in the global
//Default route mapping
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = #"[^\.]*", action = #"[^\.]*" }
);
Code showing how I'm building the link:
<div id="main-content" title="AnimalBox" style="float:none;">
<% Html.DataList(Model.PriceListAnimals).Columns(7).Item(item =>
{
item.Template(galleryImage =>
{%>
<div style="margin-left:20px; line-height:150%;">
<span><%= Html.ActionLink(galleryImage.AnimalName,"List",new { #animal = galleryImage.AnimalName }) %></span>
</div>
<% });
}).Render(); %>
</div>
Any ideas?
You have to define a route for special case routing like your instance. Since you are passing 'animal' as a parameter, you should create a route to handle that instance. In your global.aspx (above the default route), create something like below:
routes.MapRoute(
"Animal", // A distinct Route name
"{controller}/{action}/{animal}", // URL with parameters
new { controller = "MyDirectory", action = "List"}
);
This will define a route to the MyDirectory controller on the action list which has an animal parameter which is NOT OPTIONAL. Defining routes is what enables you to generate clean URLs from the html helpers and other methods (redirect to action, etc).
The overload for Html.ActionLink is:
Html.ActionLink("linkText", "actionName", "controller", object routeValues, object HtmlAttributes)
From what you've said, mydirectory = controller, and List = action, correct? If so, try:
<%= Html.ActionLink(galleryImage.AnimalName, "List", "mydirectory", new { #id = galleryImage.AnimalName }, null) %>
this should produce:
quack

Resources