Dynamic Menu and Submenu with Cache Memory

Introduction

This blog will explain how to show Dynamic menu and submenu binding in ASP.Net.  For the design part, create a CSS file.

Css Page

/* Start Menu */

nav {
	position: relative;
	width: 360px;
}

nav ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

nav ul li {
	/* Sub Menu */
}

nav ul li a {
	display: block;
	padding: 10px 15px;
	color: #fff;
	text-decoration: none;
	-webkit-transition: 0.2s linear;
	-moz-transition: 0.2s linear;
	-ms-transition: 0.2s linear;
	-o-transition: 0.2s linear;
	transition: 0.2s linear;
	background: #379add;
}

nav ul li a:hover {
	background: #1d4f71;
	color: #fff;
}

nav ul li a .fa {
	width: 16px;
	text-align: center;
	margin-right: 5px;
	float: right;
}

nav ul ul {
	background: rgba(0, 0, 0, 0.2);
}

nav ul li ul li a {
	border-left: 4px solid transparent;
	padding: 10px 20px;
}

nav ul li ul li a:hover {
	border-left: 4px solid #3498db;
}


.chevron-down::before {
	border-style: solid;
	border-width: 0.15em 0.15em 0 0;
	content: '';
	display: inline-block;
	height: 0.45em;
	left: 0.15em;
	position: relative;
	top: 0.15em;
	transform: rotate(-45deg);
	vertical-align: top;
	width: 0.45em;
	top: 0;
	transform: rotate(135deg);
	margin-top: 2px;
	margin-left: 5px;
}

.chevron-up::before {
	border-style: solid;
	border-width: 0.15em 0.15em 0 0;
	content: '';
	display: inline-block;
	height: 0.45em;
	left: 0.15em;
	position: relative;
	top: 0.15em;
	transform: rotate(-45deg);
	vertical-align: top;
	width: 0.45em;
	top: 0;
	margin-top: 6px;
	margin-left: 5px;
}

/* End Menu */

Aspx page 

The menu and submenu show dynamically with the help of cache memory use. Only one-time database call.

<script src = "../Js/jquery-3.4.1.min.js" > < /script>

	<script type = "text/javascript" >
	$(document).ready(function() {
		$('.sub-menu ul').hide();
		$(".sub-menu a").click(function() {
			$(this).parent(".sub-menu").children("ul").slideToggle("100");
			$(this).find(".right").toggleClass("fa-caret-up fa-caret-down");
			$(this).find(".arrow").toggleClass("chevron-up chevron-down");
		});
	}); 
	
</script>

<nav class = "animated bounceInDown bg-dark" >
<ul >
	<asp: Repeater ID = "RptMainMenu"
runat = "server"
OnItemDataBound = "RptMainMenu_ItemDataBound" >
	<ItemTemplate >
	<li class = "sub-menu " > < a href = "#" > < % # Eval("MenuName") % > < span id = "UpDownArrow"
class = "chevron-down arrow" > < /span><div class="fa fa-caret-down right"></div > < /a> <
ul style = "display:none;" >
	<asp: Repeater ID = "RptSubMenu"
runat = "server" >
	<ItemTemplate >
	<li > < a href = '<%# Eval("FormUrl").ToString().Replace("~", "")%>' > < % # Eval("MenuName") %> < /a></li >
	</ItemTemplate> 
	</asp:Repeater> 
	<asp: HiddenField ID = "hfMainMenuId"
runat = "server"
Value = '<%# Eval("ID") %>' / >
	</ul>
	</li> 
	</ItemTemplate> 
	</asp:Repeater> 
	</ul> 
	</nav>

Cs page

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using RelianceCommissionBAL;
using System.Web.Caching;
using RelianceCommissionDAL;

public partial class MasterPage : System.Web.UI.MasterPage
{
    DataTable DtSubMenu;
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            GenerateMenuItem();
        }
    }
    protected void lsLoginStatus_LoggedOut(object sender, EventArgs e)
    {
        Session.Clear();
        Session.Abandon();
    }
    public void GenerateMenuItem()
    {
        try
        {
            CommonBAL objCB = new CommonBAL();
            string userName = Convert.ToString(Session["UserName"]);
            TimeSpan ts = new TimeSpan(6, 0, 0);  
            DataSet DsMainMenu = new DataSet();
            if (Cache["MENU-SUBMENU"] == null)
            {
                DsMainMenu = objCB.GetNewFormRoleAllocation(null);
                Cache["MENU-SUBMENU"] = DsMainMenu;
                Cache.Insert("MENU-SUBMENU", DsMainMenu, null, Cache.NoAbsoluteExpiration, ts);
                LogData.InserLogData("MENU-SUBMENU- Caching Its processing with Database hit", this.Page.ToString());
            }
            else
            {
                DsMainMenu = (DataSet)Cache["MENU-SUBMENU"];
            }
            DtSubMenu = DsMainMenu.Tables[1].Select("UserName=" + "'" + userName + "'" + "").CopyToDataTable();
            RptMainMenu.DataSource = DsMainMenu.Tables[0].Select("UserName=" + "'" + userName + "'" + "").CopyToDataTable();
            RptMainMenu.DataBind();
        }
        catch (Exception ex)
        {
            string Errormsg = "Error Occurred In Binding Bucket Data " + PageVariableConstant.ErrorMsg;
            ScriptManager.RegisterStartupScript(this.Page, typeof(Page), "Xe54", "ShowAllMessages('" + Errormsg + "', 'e');", true);
            LogData.InserLogData(ex.ToString(), this.Page.ToString());
            ExceptionLogDAL.InsertExceptionLog(ex, "MasterPage.master.cs", "GenerateMenuItem", DateTime.Now, DateTime.Now, "GenerateMenuItem");

        }
    }
    protected void RptMainMenu_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            string MainMenuId = (e.Item.FindControl("hfMainMenuId") as HiddenField).Value;
            Repeater RptSubMenu = e.Item.FindControl("RptSubMenu") as Repeater;

            DataView dv = new DataView(DtSubMenu);
            dv.RowFilter = string.Format("ParentId={0}", Convert.ToInt32(MainMenuId));
            RptSubMenu.DataSource = dv;
            RptSubMenu.DataBind();
        }
    }

}

In DB 

Create a menu Table in the Name and other columns if we want to like the img icon...etc of the menu, and set ID as the primary key. Create Submenu Table and add the menu Id as a foreign key in this table, according to shown below PFA.

Dynamic Menu and Submenu with Cache Memory