asp.net dropdown navigation menu controller change issue - asp.net

So I created dropdown menu in _Layout.cshtml.
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-expanded="false"><span>Menu</span></a>
<ul class="dropdown-menu" role="menu">
<li>#Html.ActionLink("FirstAction", "Action", "Controller1")</li>
<li>#Html.ActionLink("Second", "second", "Controller2", new { wszystko = true })</li>
<li>#Html.ActionLink("Third", "Third", "Controller3")</li>
</ul>
</li>
</ul>
On every run I can only once choose position from the menu. When I try to pick different action, application didn't see I want to change Controller. When I want to change action, application always searches in controller I'm currently in.
For example: if I am in Controller1/Action and I want to go to Controller2/Second, program always search for Controller1/Second action result.
Before I created that menu, links work fine. Can somebody tell me why is it happening?

The only overload for ActionLink that takes four parameters is:
HtmlHelper.ActionLink(string linkText, string actionName, object routeValues, object htmlAttributes)
Note there is no controller name. You need to use
HtmlHelper.ActionLink(string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
For example
#Html.ActionLink("Second", "second", "Controller2", new { wszystko = true }, null)

You are using Html.ActionLink method overload incorrectly.
Use this overload. The fifth parameter is to specify any html attributes for the element (Ex : css class name etc). If you do not have any, just pass null
#Html.ActionLink("Second", "second", "Controller2", new { wszystko = true },null)

Related

Calling an action with parameter .Net Core

I have a MyMessages model that I put data into when the user logs in. it includes all the data needed.
for every message that they have I do the following in view
for (int i = 0; i < Model.MyMessagesCount; i++)
{
<li class="list-group-item d-flex align-items-center mt-2">
<a>#Model.MessagesTitles[i]</a>
</li>
When the user clicks on each of the <a>, I want to show them that message in more details in a separate view where I pass MessageID to.
How can I achieve that? How can I have all the <a> call the same action but with different MessageID as a parameter? (Something like this /User/Usermessages?MessageID=20)
You can use anchor tag helper
<li>
<a asp-controller="user"
asp-action="messages"
asp-area=""
asp-route-messageId="#Model.MessagesTitles[i].MessageId">
#Model.MessagesTitles[i]
</a>
</li>
asp-route-{parameter}: the parameter there is the name of the parameter you define in your action.
You can read more on https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/built-in/anchor-tag-helper?view=aspnetcore-5.0
In the Index.cshtml page, you could directly set the a tag href attribute.
Code sample as below:
public IActionResult Index()
{
List<MyMessages> messages = new List<MyMessages>()
{
new MyMessages(){ MessageId=1001, MessageTitile="AA"},
new MyMessages(){MessageId =1002, MessageTitile="BB"},
new MyMessages(){MessageId=1003, MessageTitile="CC"}
};
return View(messages);
}
public IActionResult Details(int messageId)
{
return View();
}
Index.cshtml page:
#model List<SignalRChatSample.Models.MyMessages>
<ul>
#for (int i = 0; i < Model.Count(); i++)
{
<li class="list-group-item d-flex align-items-center mt-2">
#Model[i].MessageTitile
</li>
}
</ul>
Then, the result like this (The url: Https://localhost:5001/Home/Details?messageId=1002):
Besides, as David said, you could also send the parameters via the route.

No link to controller/action when using tag helper

I have the following in my _layout.cshtml:
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
</ul>
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="User" asp-action="Index">User</a></li>
</ul>
And I have both controllers and both actions - neither have any attributes. The first link works as expected and I can step into the index action on the home controller when clicked.
Intellisense in the _layout page can see the controllers and actions and I can F12 to both.
But the second link is failing and all I get is localhost:12345/.
I've tried the full asp-route="User/Index" with the same result. I can navigate directly to localhost:12345/User/Index and hit the break point in the controller. This must be something silly, but for the life of me (and two others) we can't see it. Any help much appreciated.
From Startup.cs:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=User}/{action=Index}/{id?}"
);
});

Create dynamic links in the navigation panel

I am trying to dynamically create my top navigation panel in ASP.NET Core MVC 6.
I know it's simple but I cannot figure out how to make it work. Here is what I do (simplified):
My Model:
public class IP_Category
{
public int id { get; set; }
public string DisplayName { get; set; }
}
in my controller:
public IActionResult Index()
{
//This way I dynamically pass data to my View
ViewBag.Categories = _repository.ReturnCategories();
return View();
}
in my cshtml page:
#{
//this info is in the top of the page, here I retrieve data passed from
//controller and save it as a local variable
var categories = (List<IP_Category>)ViewBag.Categories;
}
Then later in the _Layout where I take care of the navigation:
<ul class="nav navbar-nav">
<li><a asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-controller="Home" asp-action="Contact">Contact</a></li>
#foreach (var category in categories)
{
<li><a asp-controller="Home" asp-action="#category.DisplayName">#category.DisplayName</a></li>
}
</ul>
The problem occurs with asp-action="#category.DisplayName" which does not generate appropriate href in my actual page.
So the question is what am I doing wrong? How can I pass category.DisplayName to my asp-action tag so the links work correctly?
Edit 1 - Adding more code:
Here is what was generated (note the missing href tag)
<ul class="nav navbar-nav">
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>Item1</li>
<li>Item2</li>
</ul>
if the controller and action don't match an existing controller and action then no href will be rendered. I suspect that #category.DisplayName does not match any actual action name on your home controller. Seems more likely that you have an action named Category that expects a parameter corresponding to the #category.DisplayName so it should be passed as a route parameter not as the action name
#foreach (var category in categories)
{
<li><a asp-controller="Home"
asp-action="Category"
asp-route-category="#category.DisplayName">#category.DisplayName</a></li>
}

Issue with pagination in PagedList MVC

I am using MVC PagedList to handle pagination in my project. Everything works fine except that in my controller I have to initialize pageNumber parameter with "1" (Default page number). The problem is the blue activated button on page 1 that remains there no matter which page button link you click. Moreover this button is also missing the actionLink.
One last thing I am integrating my search with pagination as you can see in the controller code.
public PartialViewResult List_Items(string keyword, int? page)
{
var newlists = from s in db.TrMs
orderby s.S1
select s;
int pageNumber = (page ?? 1);
int pageSize = 10;
var data = newlists.Where(f => f.S1.ToString().Contains(keyword) && f.S100 == vt).ToPagedList(pageNumber, pageSize);
return PartialView(data);
}
Here is the generated Html for PagedList in my view
<div class="pagination-container">
<ul class="pagination">
<li class="active">
<a>1</a>
</li>
<li>
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#searchResult" href="/TrM/Search_Items?keyword=&page=2">2</a>
</li>
<li>
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#searchResult" href="/TrM/Search_Items?keyword=&page=3">3</a>
</li>
<li>
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#searchResult" href="/TrM/Search_Items?keyword=&page=4">4</a>
</li>
<li class="PagedList-skipToNext">
<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#searchResult" href="/TrM/Search_Items?keyword=&page=2" rel="next">ยป</a>
</li>
</ul>
</div>
Here is how I am using the pagination helper.
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("List_Items", "TrM", new {keyword="", page }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions() { HttpMethod = "GET", UpdateTargetId = "searchResult" }))
Your paging controls are most likely outside of the searchResult container. When you click on a page you're replacing the table but not the paging controls. Move your paging controls inside of your searchResult container!
Hope this helps.

How to create simple userProfile route in Meteor with Iron Router

I am trying to route to the current user's profile page using Iron Router, but the 'pathFor' Spacebars helper is not passing the href attribute for the a tag.
This is my template:
<div class="collapse navbar-collapse" id="navigation">
<ul class="nav navbar-nav">
{{#if currentUser}}
<li>Submit Request</li>
<li>View Profile</li>
{{/if}}
</ul>
<ul class="nav navbar-nav navbar-right">
{{> loginButtons}}
</ul>
</div>
The href for the Submit Request button is passing in just fine, but for some reason the View Profile href is not getting passed in.
My router.js is as follows:
Router.route('/users/:_id', {
name: 'userProfile',
data: function() {
return Meteor.users.findOne(this.params._id);
}
});
In my app, I am routing to single "request" page (I created a collection called requests) by doing
Router.route('/requests/:_id, {
name: 'requestPage',
data: function() {
return Requests.findOne(this.params._id);
}
});
This routes correctly to a single request from the Requests collection, so I am confused why the userProfile route doesn't do the same.
Also, I tried to force this functionality by creating a click event on the template:
Template.header.events({
'click .userProfile': function(e) {
e.preventDefault();
var user = Meteor.user();
Router.go('userProfile', {_id: user._id});
}
});
..and this passed the correct href in to the template.
Any help on this would be greatly appreciated!
The userProfile route needs an id parameter. When you call pathFor in a template with only the route name it will attempt to extract the parameters from the current context. Because the context isn't a user (it's a request?) you will end up with an invalid path.
You can set the context inline:
<li>View Profile</li>
Alternatively, you can set the context outside of the call using with:
{{#with currentUser}}
<li>View Profile</li>
{{/with}}

Resources