MVC PagedList first page with no querystring - c#

I m using the TroyGoode MVC PagedList https://github.com/TroyGoode/PagedList
Working great except that i have duplicated content on the first page
#Html.PagedListPager((IPagedList)ViewData.Model.EnumerableAds, page => Url.Action("MyPage", "Home", new { page }))
Which gave me the HTML output :
<div class="pagination-container">
<ul class="pagination">
<li class="PagedList-skipToPrevious">«</li>
<li>1</li>
<li class="active"><a>2</a></li>
<li>3</li>
<li class="PagedList-skipToNext">»</li>
</ul>
</div>
I want to remplace :
<li class="PagedList-skipToPrevious">«</li>
<li>1</li>
by
<li class="PagedList-skipToPrevious">«</li>
<li>1</li>
Is it possible?

Like #Br4d suggested, here is the code that would accomplish this
public ActionResult MyPage(int? page=1)
{
your code here
}
Now you can send a null for the first page and it will default to page 1.

Related

Change color of navbar list item text in _Layout.cshtml when page is selected by user

I am using a bootstrap navbar in my _Layout.cshtml.
On my Index page, the list item "Home" shows as color: rgba(255, 140, 0, 0.781) and the "Features" list item shows as color: green
Desired Result: When I click the "Features" link and navigate to the Features.cshtml page, I want the "Features" list item to change color to color: rgba(255, 140, 0, 0.781) and the Home item to change to color: green.
This is easy to do if I put the navbar markup into every cshtml page. But I would like to just have my bootstrap navbar once in my _Layout.cshtml page.
_Layout.cshtml
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" style="color: rgba(255, 140, 0, 0.781)" asp-page="Index")>#_loc["Home"]</a>
</li>
<li class="nav-item active">
<a class="nav-link" style="color: green" asp-page="Features" localize-content>#_loc["Features"]</a>
</li>
<partial name="_LoginPartial" />
</ul>
</div>
</div>
</nav>
I have this working fine by putting the HTML for the menu bar in every page, but that is not a good solution as I will have to separately maintain a number of instances of my menu bar.
I tried a number of stackoverflow items but didn't find one that worked for this case. Such as set Different colors in asp:DropDownList Items
I tried following the MSDocs for the ForeColor property but couldn't achieve this either.
I have also tried using [ViewData] set in my Index.cshtml.cs but still couldn't figure out how to change the color on page load or when navigating to the Features page.
I have also tried adding # code directly to my _Layout page, such as #if(this.Page = "Index") and #if(System.IO.Directory.GetCurrentDirectory = "Index") but no joy.
Change colour of the navbar element corresponding to the active page
I've had success using a custom tag helper for this, using some code inspirited from here.
The Microsoft doc on creating tag helpers is available here. Third party tutorial available here.
The tag helper will let us specify the action that corresponds to each navbar item, then when the page is being built on the server we will add the active class to the corresponding item.
<ul class="navbar-nav flex-grow-1">
<li navigation-active-for="/Index" class="nav-item">
<a class="nav-link" asp-area="" asp-page="/Index">Home</a>
</li>
<li navigation-active-for="/Privacy" class="nav-item">
<a class="nav-link" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
<li navigation-active-for="/Movies/Index" class="nav-item">
<a class="nav-link" asp-area="" asp-page="/Movies/Index">Movies</a>
</li>
</ul>
In this case, the navigation-active-for attribute will be used.
The tag helper will be as follows
(in my case, the project is called Emotify)
using System;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Routing;
namespace Emotify.TagHelpers
{
[HtmlTargetElement("li", Attributes = _for)]
public class ActiveItemTagHelper : TagHelper
{
private readonly IUrlHelper _urlHelper;
private readonly IHttpContextAccessor _httpAccess;
private readonly LinkGenerator _linkGenerator;
private const string _for = "navigation-active-for";
public ActiveItemTagHelper(
IActionContextAccessor actionAccess,
IUrlHelperFactory factory,
IHttpContextAccessor httpAccess,
LinkGenerator generator
)
{
_urlHelper = factory.GetUrlHelper(actionAccess.ActionContext);
_httpAccess = httpAccess;
_linkGenerator = generator;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
// grab attribute value
var targetPage = output.Attributes[_for].Value.ToString();
// remove from html so user doesn't see it
output.Attributes.Remove(output.Attributes[_for]);
// get the URI that corresponds to the attribute value
var targetUri = _linkGenerator.GetUriByPage(_httpAccess.HttpContext, page: targetPage);
// get the URI that corresponds to the current page's action
var currentUri = _urlHelper.ActionLink();
// if they match, then add the "active" CSS class
if (targetUri == currentUri) {
output.AddClass("active", HtmlEncoder.Default);
}
}
}
}
The services used in the constructor from dependency injection must be registered in Startup.cs::ConfigureServices.
ref ref
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
Important: in order to work the tag helper must be registered, like in _ViewImports.cshtml.
#using Emotify
#addTagHelper *, Emotify
Note that this ISNT #addTagHelper *, Emotify.TagHelpers since that's wrong apparently, doesn't work. I'm not sure how namespace nesting works in C#.
Additional notes
dependency injection
I'm very new to C# and Razor, so this may not follow best practices
Desired Result: When I click the "Features" link and navigate to the Features.cshtml page, I want the "Features" list item to change color to color: rgba(255, 140, 0, 0.781) and the Home item to change to color: green.
If you'd like to dynamically set color for active item, you can store active page name in localStorage, then you can retrieve the stored data and dynamically set custom class for specific element to apply expected color to it in _Layout page, like below.
Html
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active" onclick="changeactive('Home')">
<a class="nav-link" asp-page="Index" )>#_loc["Home"]</a>
</li>
<li class="nav-item active" onclick="changeactive('Features')">
<a class="nav-link" asp-page="Features" localize-content>#_loc["Features"]</a>
</li>
<partial name="_LoginPartial" />
</ul>
</div>
JS code
<script>
function changeactive(pname) {
//console.log(pname);
localStorage.setItem("activepage", pname);
}
$(function () {
var pname = localStorage.getItem("activepage");
if (pname == "Home" || pname == "" || pname == null) {
$("ul.navbar-nav li.nav-item:nth-child(1) a").addClass("active-item");
$("ul.navbar-nav li.nav-item:nth-child(2) a").addClass("normal-item");
} else {
$("ul.navbar-nav li.nav-item:nth-child(1) a").addClass("normal-item");
$("ul.navbar-nav li.nav-item:nth-child(2) a").addClass("active-item");
}
})
</script>
CSS class
<style>
.active-item {
color: green !important;
}
.normal-item {
color: rgba(255, 140, 0, 0.781) !important;
}
</style>
Test Result

Razor Page, How to routing with tag helper asp.net core

I don't know how to get this string ?CurrentPage=2
this is my code
#page "/Category/{IdCategory}"
#using RN.Sieuthibamien.com.Data.Models
#model RN.Sieuthibamien.com.Pages.IndexModel
#{
ViewData["Title"] = "Category";
var id = Model.IdCategory;
}
<div>
<ul class="pagination">
<li class="page-item #(!Model.ShowFirst ? "disabled" : "")">
<a asp-page="./Category/#Model.IdCategory" asp-route-CurrentPage="1" class="page-link"><i class="fa fa-fast-backward"></i></a>
</li>
<li class="page-item #(!Model.ShowPrevious ? "disabled":"")">
<a asp-page="./Category/#Model.IdCategory" asp-route-CurrentPage="#(Model.CurrentPage -1)" class="page-link"><i class="fa fa-step-backward"></i></a>
</li>
<li class="page-item #(!Model.ShowNext ? "disabled":"")">
<a asp-page="./Category/#Model.IdCategory" asp-route-CurrentPage="#(Model.CurrentPage + 1)" class="page-link"><i class="fa fa-step-forward"></i></a>
</li>
<li class="page-item #(!Model.ShowLast ? "disabled":"")">
<a asp-page="./Category/#Model.IdCategory" asp-route-CurrentPage="#Model.TotalPages" class="page-link"><i class="fa fa-fast-forward"></i></a>
</li>
</ul>
</div>
when I click on next link then route that I want is ./Category/{IdCategory}?CurrentPage=2, but not and result is ./Category/{IdCategory}, Sorry with my English, Please help me
Change your tag helper to this:
<a asp-page="./Category" asp-route-IdCategory="#Model.IdCategory" asp-route-CurrentPage="1" class="page-link"><i class="fa fa-fast-backward"></i></a>
If you are on the same page you should change this from a asp-
page="./Category/#Model.IdCategory" to
<a asp-page="./Category"
and in order to navigate to your data based on what you click, just passed the currentpage to your OnGetAsync
OnGetAsync(int Currentpage){
CurrentPage = Currentpage == 0 ? 1 : Currentpage;
/// rest of the code here
}

Displaying dropdown of links with query builder

I am trying to create a dropdown in Umbraco 7, using the query builder. The dropdown is part of a navbar, which contains links to other pages as well. The page contains HTML with Razor code.
#{
var selection = Model.Content.Site().FirstChild("Sprog").Children()
.Where(x => x.IsVisible());
}
<ul class="sf-menu well" data-type="navbar">
#foreach(var item in selection){
if(item.Name == "Sommerhuse") {
<li>
Sommerhuse
#{
var selection2 = Umbraco.TypedContent(1090).Children()
.Where(x => x.IsVisible());
}
<ul>
#foreach(var sommerhus in selection2){
<li>
#sommerhus.Name
</li>
}
</ul>
</li>
} else {
<li>
#item.Name
</li>
}
}
</ul>
I tried nesting another query builder with the content I need for the dropdown into my navbar query builder and iterating through that
But this still doesn't create the dropdown. Instead it just returns a static link, where the dropdown should be shown. In my HTML prototype, the dropdown works fine using this code.
<nav class="nav pull-right">
<ul class="sf-menu well" data-type="navbar">
<li class="active">
Forside
</li>
<li>
Lejebetingelser
</li>
<li>
Sommerhuse
<ul>
<li>
Blokhus
</li>
<li>
Hvide Sande
</li>
<li>
Langeland
</li>
<li>
Marielyst
</li>
<li>
Ebeltoft
</li>
<li>
Rørvig
</li>
<li>
Bogense
</li>
</ul>
</li>
<li class="">
Kontakt
</li>
<li>
</li>
</ul>
</nav>
Apologies for the bad formatting, for some reason Visual Studio refuses to auto-format .cshtml files.
You don't have the <nav class="nav pull-right"> in your razor script.
Tip: do not compare on the name of a page because this will break your dropdown if the content editor changes the node name.
if(item.Name == "Sommerhuse") { // BAD IDEA
rather use the documentTypeAlias (if it is another document type)
if(item.DocumentTypeAlias == "aliasOfTheDocumentType") { // much safer
That will only work if the page has a special document type of course.

How to display a specific MVC Partial View when clicking a corresponding link?

I'm using MVC 5 and Visual Studio 2015. I have a very simple thing I want to do...
I have a page with a controller and NO MODEL. I don't believe I need a model, I'm not accessing or capturing any data; I simply want to display different information (views) based on what a user clicks.
I have an icon bar on the top of the page (which is its own partial) and when you click on an icon, it corresponds to a specific partial view. Click another icon, the previous info disappears and the new info displays. Easy peasy right? I'm not having any luck.
I've found at least a gazillion articles explaining how to do it for ONE partial. but what if I want to conditionally display info that isn't in a list and isn't in a database, but is simply a partial view connected to a link?
Here's some of the code...
My Controller
public class MyController : Controller {
public ActionResult Index() {
return View();
}
public ActionResult _about() {
return View();
}
public ActionResult _business() {
return View();
}
public ActionResult _finance() {
return View();
}
public ActionResult _jobs() {
return View();
}
public ActionResult _locations() {
return View();
}
public ActionResult _marketing() {
return View();
}
public ActionResult _programming() {
return View();
}
}
}
My Markup for the Index View (the main view for this page):
#using System.Configuration
#{ViewBag.Title = "Index";}
#Html.Partial("_cteIconBar") <!-- This is the row of icons -->
<div class="padding-top-50" id="partial">
#Html.Partial("_about") <!-- I do want to display the "about" partial when a user first lands on the page.-->
</div>
<div class="padding-top-50" id="partial" style="display: none"> <!-- this is not working... *sigh* -->
#{Html.RenderAction("_business"); }
#{Html.RenderAction("_programming"); }
#{Html.RenderAction("_finance"); }
#{Html.RenderAction("_marketing"); }
</div>
My Markup for the icon bar:
<div class="row">
<div class="col-lg-12 col-xs-12">
<div class="text-center margin-bottom icon-container">
<ul>
<li class="icon-bar-cte" id="about">
<a role="button" href="#Url.Action("_about", "CTE")">
<i class="icon-aboutInfo cte-icon"></i>
</a>
</li>
<li class="icon-bar-cte" id="business">
<a role="button" class="cte-icon" href="#Url.Action("_business", "CTE")">
<i class="icon-business cte-icon"></i>
</a>
</li>
<li class="icon-bar-cte">
<a role="button" href="#Url.Action("_finance", "CTE")">
<i class="icon-finance cte-icon"></i>
</a>
</li>
<li class="icon-bar-cte">
<a role="button" href="#Url.Action("_marketing", "CTE")">
<i class="icon-marketing cte-icon"></i>
</a>
</li>
<li class="icon-bar-cte">
<a role="button" href="#Url.Action("_programming", "CTE")">
<i class="icon-programming cte-icon"></i>
</a>
</li>
<li class="icon-bar-cte">
<a role="button" href="#Url.Action("_jobs", "CTE")">
<i class="icon-jobs cte-icon"></i>
</a>
</li>
<li class="icon-bar-cte">
<a role="button" href="#Url.Action("_locations", "CTE")">
<i class="icon-location-marker cte-icon"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
My markup for one of the partials (they're all the same with different words). I substituted a little "Hippie Ipsum" for your pleasure.
<div class="container collapse in" id="about" aria-expanded="true">
<div class="row padding-bottom-50">
<div class="col-lg-8 col-lg-offset-2 col-md-8 col-md-offset-2 col-sm-12">
<h2 class="green">Some Hippie Ipsum for You!</h2>
<p><strong>What is Career Technical Education?</strong></p>
<p>Equinox plant consciousness midwifery embracing and moving towards djembe craniosacral, dolphin Hafiz ecstatic dance higher cosmic force spoken word. Prayer flags fair trade what quantum theory says, healing tonic non-profit co-create impermanent hemp seed.</p>
<br />
<p><strong>Why is Hippie Ipsum important?</strong></p>
<p>Closing circle himalayan sea salt multi-dimensional honoring your truth, forest birth name. Tofurkey native american ancestry diva cup human potential yoni, bioneers the buddha sunset. Animal totem deep cleansing emotional release one taste life coach compostable toilet, be the change astrological mercury retrograde holistic.</p>
</div>
</div>
</div>
.padding-top-50{
padding-top:50px;
}
The easiest solution for what you'd like to achieve is to use AJAX so you can inject the views into the container.
So let's start from the beginning:
1) You have to return PartialView() instead of regular View()
public ActionResult _about() {
return PartialView();
}
2) Not needed, but I'd change some things in your menu markup. Note the data-url instead of href.
<li class="icon-bar-cte" id="business">
<a href="#" role="button" class="cte-icon" data-url="#Url.Action("_business", "CTE")">
<i class="icon-business cte-icon"></i>
</a>
</li>
3) Most important part is the following jQuery. Depending of what you need you can use append instead of html when injecting the view.
$(document).on('click','.cte-icon',function(e){
e.preventDefault();
var url = $(this).data('url');
$.ajax({
url: url,
type: 'GET'
}).done(function(response){
$('#partial').html(response);
});
});
Yet another way, if you wanna go more "vanilla" .NET MVC is to use actionlinks and return partial views from your controller actions.
Something like this:
public ActionResult _programming()
{
PartialView("~/Views/YourPartialsPath/_programming.cshtml");
}
And in your views put this:
#Html.ActionLink("Html element text",
"_programming",
"MyController",
new { controller = "MyController" },
new { #class = "MaybeYouWantAClassOnTheHtmlElement" })
And if you want you could structure your site to be a single page app by initially loading a single view to be your "base structure" container. This page would then load a set of partials consisting of maybe side/top menu bars and maybe a "main page" container.
This main page could also be in charge of loading of some javascripts you want to run across all of your later loaded partials (maybe a function showing/hiding an ajax.gif image)
Lets say you put this in your initial page load.
Maybe you put this in your: \Views\Home\index.cshtml
Or even your: \Views_Layout.cshtml
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-left">
#{ Html.RenderAction("TopMenuRenderer", "Menu");}
</ul>
<ul class="nav navbar-nav navbar-right">
#{ Html.RenderAction("UserMenuRenderer", "Menu");}
</ul>
</div>
Then you create a controller called Menu
namespace WebPortal.Web.Controllers
{
public class MenuController : Controller
{
[ChildActionOnly] //for ajax call to controller remove this annotation
public ActionResult TopMenuRenderer()
{
//return PartialView();
if (User.IsInRole(Role.Admin.ToString()) ||
User.IsInRole(Role.SuperAdmin.ToString()))
{
return PartialView("~/Views/Menu/_TopMenu.cshtml");
}
return null;
}
[ChildActionOnly]
public ActionResult UserMenuRenderer()
{
if (User.Identity.IsAuthenticated)
return PartialView("~/Views/Menu/_UserMenuAuthenticated.cshtml");
else
return PartialView("~/Views/Menu/_UserMenuNotAuthenticated.cshtml");
}
[ChildActionOnly]
public ActionResult SideMenuRenderer()
{
//you could put some user checks here if you want to limit some of the loaded meny options depending on the user type.
if (User.IsInRole(Role.Admin.ToString()) ||
User.IsInRole(Role.SuperAdmin.ToString()))
{
return PartialView("~/Views/Menu/_SideMenu.cshtml");
}
return null;
}
}
}

setting active class in c#.net masterpage

<div id="navigation">
<ul class="nav nav-pills">
<li role="presentation">Home</li>
<li role="presentation">Open Account</li>
<li role="presentation">ATM</li>
<li role="presentation">Branch Locator</li>
<li role="presentation">Contact US</li>
</ul>
</div>
I want to set active class in li tag based on the visited link, I have tried several answers from Stackoverflow but none seems to me working.
For your information, I am using Bootstrap, C#, Visual Studio for my development.
Your elements should look like (in master.page):
<li role="presentation" id="liDefault" runat="server">Home</li>
public String linkDefault
{
get
{
return "not_active";
}
set
{
liDefault.Attributes.Add("class", "" + value + "");
}
}
Then add following to your head part of content page:
<%# MasterType VirtualPath="~/MasterPage.master" %>
And code behind of your content page:
this.Master.linkDefault = "active";
You can achieve it using Jquery.
First set single class on all anchor tags in you li tags i.e:
<div id="navigation">
<ul class="nav nav-pills">
<li role="presentation">Home</li>
<li role="presentation">Open Account</li>
<li role="presentation">ATM</li>
<li role="presentation">Branch Locator</li>
<li role="presentation">Contact US</li>
</ul>
</div>
Now in jquery you have to check if any anchor tag is clicked so an "active" class will be set to its parent li tag. i.e.:
$(".link").click(function(){
$(this).parent().addClass("active");
})
Hope its works.

Categories

Resources