Dynamic Menu Generation With Web API And Angular

Introduction

In this article, we are going to implement a dynamic menu with the help of ASP.NET Web API and Angular JS.

We will create a login page that has two login types - Admin and User.

Admin login will lead to some different menu items and User login will come up with different menu items.

Prerequisite

  1. Programming of C#.
  2. Knowledge of JavaScript or AngularJS.

Implementation

Open Visual Studio.

 Visual Studio

Angular

Select ASP.NET Web Application, give the name of the solution, and click OK.

Create a class file, Menu. cs, inside the Models folder.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CustomMenuDemo.Models
{
    public class Menu
    {
        List<Menu> MenuList;
        public int MenuId { get; set; }
        public string MenuName { get; set; }
        public string MenuHref { get; set; }
        public List<Menu> GetMenu(int id)
        {
            MenuList = new List<Menu>();
            if (id == 1)
            {
                MenuList.Add(new Menu() { MenuId = 1, MenuName = "Add Employee", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 2, MenuName = "View Employee", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 3, MenuName = "Delete Employee", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 4, MenuName = "Edit Employee", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 5, MenuName = "Logout", MenuHref="#" });
            }
            else
            {
                MenuList.Add(new Menu() { MenuId = 1, MenuName = "Edit Details", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 2, MenuName = "My Task", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 3, MenuName = "Contact Us", MenuHref="#" });
                MenuList.Add(new Menu() { MenuId = 4, MenuName = "Logout", MenuHref="#" });
            }
            return MenuList;
        }
    }
}

Add a Controller file inside the Controllers folder.

Controller file

Give it a name as MenuController.

MenuController

Add the Controller class. Modify the content as below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using CustomMenuDemo.Models;
namespace CustomMenuDemo.Controllers
{
    public class MenuController : ApiController
    {
        // GET api/Menu
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }
        // GET api/Menu/5
        public List<Menu> Get(int id)
        {
            return new Menu().GetMenu(id);
        }
        // POST api/Menu
        public void Post([FromBody]string value)
        {
        }
        // PUT api/Menu/5
        public void Put(int id, [FromBody]string value)
        {
        }
        // DELETE api/Menu/5
        public void Delete(int id)
        {
        }
    }
}

Create an App/js folder inside the Content directory.

Add index.js file with the following content.

var myapp = angular.module('uirouteApp', ["ui.router"]);
myapp.config(function ($stateProvider) {
    $stateProvider
        .state('index', {
            url: "",
            views: {

            }
        })
        .state('Home', {
            url: "/Home",
            views: {
                "secondView": {
                    template: "<span class='category-note'>Logged in Successfully!</span>"
                }
            }
        });
});
myapp.controller('LoginController', function ($scope, $rootScope, $stateParams, $state, $http, LoginService, MenuService, UserService) {
    $rootScope.title = "AngularJS Login Sample";
    $scope.menus = [{ "MenuId": 1, "MenuName": "Home", "MenuHref": "#" }, { "MenuId": 2, "MenuName": "Contact Us", "MenuHref": "#" }];
    $scope.username = '';
    $scope.password = '';
    $scope.usertype = '';
    $scope.formSubmit = function (username, password, usertype) {
        $scope.username = username;
        $scope.password = password;
        $scope.usertype = usertype;
        if (LoginService.login($scope.username, $scope.password, $scope.usertype)) {
            $http({
                method: "GET",
                url: "http://localhost:54824/api/Menu/" + $scope.usertype
            }).then(function mySuccess(response) {
                $scope.menus = response.data;
                UserService.setUser({
                    username: $scope.username,
                    password: $scope.password,
                    usertype: $scope.usertype
                });
                $scope.$apply();
                $state.go("Home");
            }, function myError(response) {
                $scope.message = response.statusText;
            }); 
            $scope.error = '';
            $scope.username = '';
            $scope.password = '';
        } else {
            $scope.error = "Incorrect username/password !";
        }
    };
});
myapp.factory('LoginService', function ($http) {
    var isAuthenticated = false;
    var menus = null;
    return {
        login: function (username, password, type) {
            // fields validation check here
            return true;
        },
        isAuthenticated: function () {
            return isAuthenticated;
        }
    };
});
myapp.service('MenuService', function () {
    var menus = {};
    this.save = function (m) {
        this.menus = m;
    };
    this.getMenus = function () {
        return this.menus;
    };
});
myapp.service('UserService', function () {
    var user = {
        username: "",
        password: "",
        usertype: ""
    };
    this.setUser = function (u) {
        this.user = u;
    };
    this.getUser = function () {
        return this.user;
    };
});

Open Index. cshtml from Home View and add the below content.

<script src='http://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.min.js'></script>
<script src="~/Content/App/js/index.js"></script>
<div class="container" ng-app="uirouteApp" ng-controller="LoginController">
    <header class="projects">
        <h1 class="projects-title">Dynamic Menu:</h1>
    </header>
    <section class="projects">
        <div class="wrapper">
            <div class="row">
                <div class="col-md-3" ui-view="firstView">
                    <div>
                        <p ng-repeat="item in menus"><a href="{{item.MenuHref}}"> {{item.MenuName}}</a></p>
                    </div>
                </div>
                <div class="col-md-9" ui-view="secondView">
                    <h3>Login Page</h3>
                    <form class="form">
                        <div class="form-group">
                            <input type="text" class="form-control" ng-model="username" placeholder="username" required="" />
                        </div>
                        <div class="form-group">
                            <input type="password" class="form-control" ng-model="password" placeholder="password" required="" />
                        </div>
                        <div class="radio">
                            <label><input type="radio" ng-value="1" ng-model="usertype" name="optradio">Admin</label>
                        </div>
                        <div class="radio disabled">
                            <label><input type="radio" ng-value="2" ng-model="usertype" name="optradio">User</label>
                        </div>
                        <div class="form-group">
                            <button type="button" class="btn btn-success" ng-click="formSubmit(username, password, usertype)">Login</button>
                            <span class="text-danger">{{ error }}</span>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
</div>

Open Layout. cshtml from shared View and edit it with the below content.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Custom Menu</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
    <link rel='stylesheet prefetch' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css'>
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body style="background-color: #d1cccd">
    @RenderBody()
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

The directory structure will be as follows.

 Directory Structure

Build and run the application.

 Run

Give username and password and select Admin.

Select Admin

Click "Login".

Login

Now, click on Logout and check for User.

Logout

Give username and password and click "Login".

Dynamic menu

Note. This application only demonstrates how can we achieve the custom menu through Web API and AngularJS. You can get the menu values from the database unlike in this application the direct sending of menu information. You can define different Views based on the user or menu item. You can perform login check defined inside its service in index.js. You can do validation also.

You may need to change the URL "http://localhost:54824/api/Menu/" based on your server port.