European ASP.NET MVC 4 and MVC 5 Hosting

BLOG about ASP.NET MVC 3, ASP.NET MVC 4, and ASP.NET MVC 5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Bind Menu And Sub Menu Dynamically In ASP.NET MVC From Database Using LINQ

clock September 21, 2018 11:13 by author Peter

Many times we need to create a menu for a simple application. We ususally get stuck on how to bind the menu. Here in this article we you will learn how to bind menu and sub menu dynamically in ASP.NET MVC from database using linq.

Step 1
I am going to create a database which contains the following fields as well as some dummy data which contains parent & child relationship.
Use the below script to create table & insert query,
    USE [Dynamic_Menu] 
    GO 
    SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    SET ANSI_PADDING ON 
    GO 
    CREATE TABLE [dbo].[Menu_List]( 
        [M_ID] [int] IDENTITY(1,1) NOT NULL, 
        [M_P_ID] [int] NULL, 
        [M_NAME] [varchar](50) NULL, 
        [CONTROLLER_NAME] [varchar](50) NULL, 
        [ACTION_NAME] [varchar](50) NULL, 
     CONSTRAINT [PK_Menu_List] PRIMARY KEY CLUSTERED  
    ( 
        [M_ID] ASC 
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 
    GO 
    SET ANSI_PADDING OFF 
    GO 
    SET IDENTITY_INSERT [dbo].[Menu_List] ON 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (1, 0, N'My Menu', NULL, NULL) 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (2, 1, N'BCS', N'Menu', N'BCS_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (3, 2, N'Computer', N'Menu', N'Computer_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (4, 1, N'MCS', N'Menu', N'MCS_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (5, 2, N'Maths', N'Menu', N'Maths_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (6, 4, N'Marketing', N'Menu', N'Marketing_Action') 
    INSERT [dbo].[Menu_List] ([M_ID], [M_P_ID], [M_NAME], [CONTROLLER_NAME], [ACTION_NAME]) VALUES (7, 4, N'Finiance', N'Menu', N'Finiance_Action') 
    SET IDENTITY_INSERT [dbo].[Menu_List] OFF


Step 2
Now create simple MVC appliation using visual studio. After creating project add edmx file by right clicking on project go to Add => New Item => (from right side templates) select Data => Select ADO.NET Entity Data Model => Give proper name to it and click on add button.

Then select your table from database & create .edmx file into your ptoject. After adding the file autmatically connection string will get added into web config file.

Step 3
Now create model as below and add some properties; this model will be used into a controller & view.
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
     
    namespace Dynamic_Menu.Models 
    { 
        public class Menu_List 
        { 
            public int M_ID { get; set; } 
            public int? M_P_ID { get; set; } 
            public string M_NAME { get; set; } 
            public string CONTROLLER_NAME { get; set; } 
            public string ACTION_NAME { get; set; } 
        } 
    } 

Step 4
Now add controller into our application and write below code into it. From action method GetMenuList() we will get data from our database using linq query.
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Web; 
    using System.Web.Mvc; 
     
    namespace Dynamic_Menu.Controllers 
    { 
        public class HomeController : Controller 
        { 
            MenuEntities objEntity = new MenuEntities(); 
            public ActionResult Index() 
            { 
                return View();         
            } 
            public ActionResult GetMenuList() 
            { 
                try 
                { 
                    var result = (from m in objEntity.Menu_Tree 
                                  select new Dynamic_Menu.Models.Menu_List 
                                  { 
                                      M_ID = m.M_ID, 
                                      M_P_ID = m.M_P_ID, 
                                      M_NAME = m.M_NAME, 
                      CONTROLLER_NAME = CONTROLLER_NAME, 
                                      ACTION_NAME = ACTION_NAME, 
                                  }).ToList(); 
                    return View("Menu", result); 
                } 
                catch (Exception ex) 
                { 
                    var error = ex.Message.ToString(); 
                    return Content("Error"); 
                }  
            } 
        } 
    }

Step 5
Now create a view for Index action method as like.
    @{ 
        ViewBag.Title = "Index"; 
        Layout = "~/Views/Shared/_Layout.cshtml"; 
    } 
     
    <h2>Index</h2>


Now create layout view for our application. Also create one partial view (name Menu.cshtml) as brlow,  which will render menu tree list when we are going to call action method from our layout page. In this partial view we are getting data into a IEnumerable list format and we are applying some logic as below,

Note
This is just demo / sample application, according to your requirement you can add foreach loop for more hierarchy levels. This is only a two level menu tree strucure.
_Layout.cshtml  =>

    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <meta name="viewport" content="width=device-width" /> 
        <title>@ViewBag.Title</title> 
        @Html.Action("GetMenuList", "Home") 
    </head> 
    <body> 
        <div> 
            @RenderBody() 
        </div> 
    </body> 
    </html>

 Menu.cshtml =>

    @model IEnumerable<Dynamic_Menu.Models.Menu_List> 
    <div> 
        <ul> 
            @{foreach (var item in Model.Where(s => s.M_P_ID == 0).GroupBy(Obj => new { Obj.M_ID }).Distinct().ToList()) 
            { 
                <li> 
                    <a href="#"> 
                        @item.FirstOrDefault().M_NAME 
                    </a> 
                    <ul> 
                        @{foreach (var firstItem in (Model.Where(s => s.M_P_ID == item.FirstOrDefault().M_ID).ToList())) 
                        { 
                            <li> 
                                <a href="#"> 
                                    @firstItem.M_NAME 
                                </a> 
                                <ul> 
                                    @foreach (var secondItem in (Model.Where(s => s.M_P_ID == firstItem.M_ID).ToList())) 
                                    { 
                                        <li> 
                                            <a href="/@secondItem.CONTROLLER_NAME/@secondItem.ACTION_NAME"> 
                                                @secondItem.M_NAME 
                                            </a> 
     
                                        </li> 
                                    } 
                                </ul> 
     
                            </li> 
                        } 
                        } 
                    </ul> 
                </li> 
            } 
            } 
        </ul> 
    </div> 


Step 5
Now create another controller to render views whenever we are clicking on hyper links from menu, it will redirect to that view by using controller name & action name
    namespace Dynamic_Menu.Controllers 
    { 
        public class MenuController : Controller 
        { 
    public ActionResult Computer_Action() 
            { 
                return View(); 
            } 
            public ActionResult Maths_Action() 
            { 
                return View(); 
            } 
            public ActionResult Marketing_Action() 
            { 
                return View(); 
            } 
            public ActionResult Finiance_Action() 
            { 
                return View(); 
            } 
     
     } 
    }


Create some views for above action as like
 
View For Computer_Action as,
    @{ 
        Layout = "~/Views/Shared/_Layout.cshtml"; 
    } 
     
    <!DOCTYPE html> 
     
    <html> 
    <head> 
        <meta name="viewport" content="width=device-width" /> 
        <title>Computer_Action</title> 
    </head> 
    <body> 
        <div>  
            <h2>Welcome To Computer View</h2> 
        </div> 
    </body> 
    </html>

View For MCS_Action as
@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 

 
<!DOCTYPE html> 
 
<html> 
<head> 
    <meta name="viewport" content="width=device-width" /> 
    <title>MCS_Action</title> 
</head> 
<body> 
    <div>  
        <h2>Welcome To MCS View</h2> 
    </div> 
</body> 
</html> 


Step 6
Now run the application.
Index view after running the application into a browser.

If we click on menu   then our output will be:

In this article, you learned how to bind menu and sub menu dynamically in ASP.NET MVC from database using linq.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Is MVC Replacing ASP.NET Web Forms?

clock September 18, 2018 09:53 by author Peter

We often think that one technology will be totally replaced by a new release or new version of technology. This article tries to dicuss that and similar issues and I will share my industry experience, not just what I have seen in India (the largest IT Solutions Provider to the world) but also in the USA.

I consider this to be a very hot topic and a good candidate of debate but I will try to share my thoughts on such a burning topic. This article does not highlight or defame any technology, I am just going to provide my perspective as I have seen, experienced and advised to various clients and software teams.

Why new Versions

The principle “Change is Constant” applies very well to the software industry and I respect this overflow of information. Because this gives me reason to “Keep Learning and stay ahead of the Curve”. By saying so I didn't mean that someone must learn anything and everything you can get your hands on. No, certainly not, but before I explain this any further let's take a step back and understand “Why new Versions” keep coming.

We are fortunate that we have seen complete transition of the software industry from Desktop to Web to Mobile, future generations may not witness this great and life changing shift. Also, I recall my days when I was working and studying software in 1995, no one imagined that there will be MVC, WPF, WCF, so many versions of .NET and SQL Server and so on. Industry was happy with Microsoft Access, FoxPro, C, C++ and Oracle and so on. But our needs keep changing, they evolved and then shell is broken to have huge expansion and today we have many kinds of software technology and server products from client-side to server-side to mobile and hand-held and many more. We moved from on premise to the Cloud and Machine Learning is helping to dictate patterns and suggest needs.

This is why software companies keep building the latest and newest technologies to enable and empower the world to build for the future. When they release a version of a technology or language and they discover some issues or new features in that then they release newer versions and this in a chain-reaction process and it will not stop.

Oh, then I will die Learning

As per Darwin's Evolution Theory “Survival of the Fittest”, "fit" refers to "best adapted to the current environment". Here you simply replace environment with the software industry. I am one of you and I am not saying that everyone must learn everything but what I suggest is to stick to your technology of choice and have good knowledge of the offered tools and technologies and various versions and when to use which one.

Also, you don't necessarily need to understand every single thing. For example, I only focus on .NET and related technologies, if anything falls beyond this area then I am not bothered. To be more precise, I don't understand Microsoft CRM, SharePoint, System Center, SQL Server Database Administration and few more things like that.

But this is not my weak point because “I continue to build my .NET Muscle” and continue to learn about what helps me build Enterprise solutions using Microsoft .NET.

So choose your area of interest and where you have invested and then keep learning in a similar field and then you will no longer find it challenging because if you observe, new versions come after every few years and that must be otherwise it will be no fun!

Hmm, so Isn't MVC Replacing ASP.NET Web Forms

Such decisions are not final and have no concrete answers. Yes, the industry changes their needs and so new technologies such as MVC and WPF takes over. This definitely doesn't mean that ASP.NET Web Forms is replaced or it's dead. If you understand the Microsoft Web fundamentals, MVC is based on ASP.NET and industry is trying to shift as and when they can from Web Forms to MVC and reap the benefits it offers.

Did you know that MVC is much older than ASP.NET? Yes, ASP.NET 1.0 was released in 2002 and MVC was created in 1979 originally named as “Thing-Model-View-Controller” but later simplified to be known as MVC.

In my view I consider that there are now two technologies to build Web Solutions using Microsoft and based on your needs you can pick one that works well for you. Usually such technology selections are made by architects assigned to the project.

So there is no such Golden Rule that every new or existing application must be either created using MVC or migrated to MVC because MVC is the latest and future the of web. Though it is.

Architectural Thinking: Brownfield Vs Greenfield Applications

All software applications you have worked or will work in future are either Brownfield or Greenfield.

  • Brownfield Development: When any existing or legacy applications need to have new features or changes to address business needs, it is known as brownfield. In such situations, unless you are building a new module or component, you have less, limited or no scope to use new architectural styles, patterns and so on. The very reason of such limitations is because those old applications are built using an old version of technologies and the latest versions of one technology/framework and many are not be compatible with old versions.
  • Greenfield Development: When a brand-new project is being envisioned and no previous work is done in that or a related area then it's called Greenfield. In the software industry it doesn't happen very often. But whenever it happens its the architect's responsibility to determine what the best technology is to address business needs.

Hence, it's not appropriate to say that because MVC is so new hence every new web application must be made using MVC or if WPF is available in addition to Windows Forms so every desktop application must be made using WPF. Whatever is the case neither ASP.NET Web Forms nor Windows Forms can be totally ignored.

Why and Why not the Latest Technologies should be chosen

First the reasons why not.

  1. It's Brownfield and new technology doesn't fit anywhere.
  2. If new technology or versions are introduced then it will cause many build errors due to outdated references of non-supported library references.
  3. Business goals and software quality are not compromised by continuing to use current and available technologies like ASP.NET Web Forms over MVC or Windows Forms over WPF.
  4. You are not investing money in any extra off-the-shelf tools to handle issues that could have been handled by the latest versions of similar area of technologies, for example MVC instead of ASP.NET Web Forms, or WPF over Windows Forms.
  5. Teams often might not have a certain skill set that allows them to proceed with development using new technology options
  6. Budget allocation from a client often may impact your decision to use and develop using the latest technologies.
  7. If the core/bestselling features of a new candidate technology (MVC or WPF) are not being used at least up to 50% then you have done nothing.
  8. Considering how soon the client and business wants to have an application ready, it turns being a major factor to dictate the technology of choice.
  9. The client and business doesn't care how you do it; what matters is the end-result and a workable / good-enough software.
  10. No way to use old legacy downstream applications with the latest available technologies.

Why develop using Latest Technologies

  1. Greenfield software solution and no legacy or old piece of code is being used.
  2. Focus is more on Robustness, Testability, Object Oriented design and quality. (This doesn't mean previous technology can't accomplish these; it's about ease and in-built features and offerings).
  3. Amazing team with great skills to learn new technologies and adapt the changes.
  4. Company's vision is to showcase products build using latest technologies.
  5. Client themselves want the solution to be developed using latest technologies and have budget to support that.

Why MVC over ASP.NET Web Forms then

Note: this section assumes that you are aware of MVC benefits and the general technical terms used below.

  1. Separation of Concerns is the core of MVC.
  2. Single Responsibility Principle is done by default.
  3. Unified and even better framework to work on WebAPI, Mobile, HTML 5, CSS3, Security and Deployment (including Azure).
  4. Unit testing is easily done to have stable, robust and quality software solutions delivered continuously.
  5. Fast screen generation for CRUD operations via Scaffolding.
  6. Convention over configuration.

Summary
Based on my experience as an architect in the industry I would like to summarize that it's very hard for any organization to keep up with the latest version and technologies all the time because by the time you become comfortable with one version the newer is around the corner. So if you are working on MVC 4, then see if you can learn and try some application being developed on your own. Or if you just happen to be in the ASP.NET Web Forms world until now then I would encourage you to try converting that application to MVC for your personal benefit. This will force you to learn new technology and apply that learning. If you have made some progress in that then in the next interview you can proudly showcase your MVC knowledge and say that you have migrated ASP.NET Web Forms to MVC.



ASP.NET MVC 6 Hosting - HostForLIFE.eu :: Clickable Google Charts

clock September 7, 2018 11:52 by author Peter

Charts are an important aspect of reports as they make it simpler to understand a certain problem. Making charts clickable adds more reinforcement into the understanding of the problem.


Today, I shall be demonstrating clickable charts using Google Charts API in ASP.NET MVC5. Google Charts API is simple to use and provides a variety of options for customization of graphical chart reports for better analytical purposes.

Prerequisites
Following are some prerequisites before you proceed further in this tutorial.
Knowledge of Google charts API.
Knowledge of ASP.NET MVC5.
Knowledge of HTML.
Knowledge of JavaScript.
Knowledge of AJAX.
Knowledge of CSS.
Knowledge of Bootstrap.
Knowledge of C# programming.
Knowledge of C# LINQ.
Knowledge of jQuery.

You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is developed in Microsoft Visual Studio 2015 Enterprise. I am using SalesOrderDetail table extracted from Adventure Works Sample Database.

Let's begin now.

Step 1
Create a new MVC5 web application project and name it "Graphs".

Step 2
Open "Views\Shared\_Layout.cshtml" file and replace the following code in it.
<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <title>@ViewBag.Title</title> 
    @Styles.Render("~/Content/css") 
    @Scripts.Render("~/bundles/modernizr") 
 
    <!-- Font Awesome --> 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" /> 
 
    @* Custom *@ 
    @Styles.Render("~/Content/css/custom-style") 
</head> 
<body> 
    <div class="navbar navbar-inverse navbar-fixed-top"> 
        <div class="container"> 
            <div class="navbar-header"> 
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> 
                    <span class="icon-bar"></span> 
                    <span class="icon-bar"></span> 
                    <span class="icon-bar"></span> 
                </button> 
            </div> 
        </div> 
    </div> 
    <div class="container body-content"> 
        @RenderBody() 
        <hr /> 
        <footer> 
            <center> 
                <p><strong>Copyright © @DateTime.Now.Year - <a href="http://www.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p> 
            </center> 
        </footer> 
    </div> 
 
    @Scripts.Render("~/bundles/jquery") 
    @Scripts.Render("~/bundles/bootstrap") 
 
    <!-- Graphs --> 
    <script type="text/javascript" src="https://www.google.com/jsapi"></script> 
    @Scripts.Render("~/bundles/Script-custom-graphs") 
 
    @RenderSection("scripts", required: false) 
</body> 
</html>


In the above code, I have simply created the basic layout structure of this web project and I have also add reference to the Google charts API.

Step 3

Create a new "Models\HomeViewModels.cs" file and replace with the following code in it.
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
 
namespace Graphs.Models 

    public class SalesOrderDetail 
    { 
        public int Sr { get; set; } 
        public string OrderTrackNumber { get; set; } 
        public int Quantity { get; set; } 
        public string ProductName { get; set; } 
        public string SpecialOffer { get; set; } 
        public double UnitPrice { get; set; } 
        public double UnitPriceDiscount { get; set; } 
        public string Link { get; set; } 
    } 
}

In the above code, we have simply created our View Model which will map the data from text file into main memory as object. Also, notice that we have added "Link" property, which we will use as our clickable destination.

Step 4

Now, create "Controllers\HomeController.cs" file and replace the following code in it.
using Graphs.Models; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Reflection; 
using System.Web; 
using System.Web.Mvc; 
 
namespace Graphs.Controllers 

    public class HomeController : Controller 
    { 
        #region Index method 
 
        /// <summary> 
        /// GET: Home/Index method. 
        /// </summary> 
        /// <returns>Returns - index view page</returns>  
        public ActionResult Index() 
        { 
            // Info. 
            return this.View(); 
        } 
 
        #endregion 
 
        #region Test Page method 
 
        /// <summary> 
        /// GET: Home/TestPage method. 
        /// </summary> 
        /// <returns>Returns - test page view page</returns>  
        public ActionResult TestPage() 
        { 
            // Info. 
            return this.View(); 
        } 
 
        #endregion 
 
        #region Get data method. 
 
        /// <summary> 
        /// GET: /Home/GetData 
        /// </summary> 
        /// <returns>Return data</returns> 
        public ActionResult GetData() 
        { 
            // Initialization. 
            JsonResult result = new JsonResult(); 
 
            try 
            { 
                // Loading. 
                List<SalesOrderDetail> data = this.LoadData(); 
 
                // Setting. 
                var graphData = data.GroupBy(p => new 
                                    { 
                                        p.ProductName, 
                                        p.Link, 
                                        p.UnitPrice 
                                    }) 
                                    .Select(g => new 
                                    { 
                                        g.Key.ProductName, 
                                        g.Key.Link, 
                                        g.Key.UnitPrice 
                                    }).OrderByDescending(q => q.UnitPrice).ToList(); 
 
                // Top 10 
                graphData = graphData.Take(2).Select(p => p).ToList(); 
 
                // Loading drop down lists. 
                result = this.Json(graphData, JsonRequestBehavior.AllowGet); 
            } 
            catch (Exception ex) 
            { 
                // Info 
                Console.Write(ex); 
            } 
 
            // Return info. 
            return result; 
        } 
 
        #endregion 
 
        #region Helpers 
 
        #region Load Data 
 
        /// <summary> 
        /// Load data method. 
        /// </summary> 
        /// <returns>Returns - Data</returns> 
        private List<SalesOrderDetail> LoadData() 
        { 
            // Initialization. 
            List<SalesOrderDetail> lst = new List<SalesOrderDetail>(); 
 
            try 
            { 
                // Initialization. 
                string line = string.Empty; 
                string srcFilePath = "Content/files/SalesOrderDetail.txt"; 
                var rootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); 
                var fullPath = Path.Combine(rootPath, srcFilePath); 
                string filePath = new Uri(fullPath).LocalPath; 
                StreamReader sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read)); 
 
                // Read file. 
                while ((line = sr.ReadLine()) != null) 
                { 
                    // Initialization. 
                    SalesOrderDetail infoObj = new SalesOrderDetail(); 
                    string[] info = line.Split(','); 
 
                    // Setting. 
                    infoObj.Sr = Convert.ToInt32(info[0].ToString()); 
                    infoObj.OrderTrackNumber = info[1].ToString(); 
                    infoObj.Quantity = Convert.ToInt32(info[2].ToString()); 
                    infoObj.ProductName = info[3].ToString(); 
                    infoObj.SpecialOffer = info[4].ToString(); 
                    infoObj.UnitPrice = Convert.ToDouble(info[5].ToString()); 
                    infoObj.UnitPriceDiscount = Convert.ToDouble(info[6].ToString()); 
                    infoObj.Link = this.Url.Action("TestPage", "Home"); 
 
                    // Adding. 
                    lst.Add(infoObj); 
                } 
 
                // Closing. 
                sr.Dispose(); 
                sr.Close(); 
            } 
            catch (Exception ex) 
            { 
                // info. 
                Console.Write(ex); 
            } 
 
            // info. 
            return lst; 
        } 
 
        #endregion 
 
        #endregion 
    } 
}


In the above code, I have created a simple index() & TestPage() action methods along with a helper method LoadData() for data loading from text file and finally, GetData() action method which will be called by Google charts API AJAX method in order to map the data on the chart. The GetData() action method will return top the top two rows only which are sorted by product and unit price and grouped by product name.

Step 5
Create a new "Scripts\script-custom-graphs.js" script file and replace the following code in it.
// Load the Visualization API and the piechart package. 
google.load('visualization', '1.0', { 'packages': ['corechart'] }); 
 
// Set a callback to run when the Google Visualization API is loaded. 
$(document).ready(function () 

    $.ajax( 
    { 
        type: 'POST', 
        dataType: 'JSON', 
        url: '/Home/GetData', 
        success: 
            function (response) 
            { 
                // Set chart options 
                var options = 
                    { 
                        width: 1100, 
                        height: 900, 
                        sliceVisibilityThreshold: 0, 
                        legend: { position: "top", alignment: "end" }, 
                        chartArea: { left: 370, top: 50, height: "90%" }, 
 
                        bar: { groupWidth: "50%" }, 
                    }; 
 
                // Draw. 
                drawGraph(response, options, 'graphId'); 
            } 
    }); 
}); 
 
// Callback that creates and populates a data table, 
// instantiates the pie chart, passes in the data and 
// draws it. 
function drawGraph(dataValues, options, elementId) { 
    // Initialization. 
    var data = new google.visualization.DataTable(); 
 
    // Setting. 
    data.addColumn('string', 'Product Name'); 
    data.addColumn('number', 'Unit Price'); 
    data.addColumn('string', 'Link'); 
 
    // Processing. 
    for (var i = 0; i < dataValues.length; i++) 
    { 
        // Setting. 
        data.addRow([dataValues[i].ProductName, dataValues[i].UnitPrice, dataValues[i].Link]); 
    } 
 
    // Setting label. 
    var view = new google.visualization.DataView(data); 
    view.setColumns([0, 1, 
        { 
            calc: "stringify", 
            sourceColumn: 1, 
            type: "string", 
            role: "annotation" 
        } 
    ]); 
 
    // Instantiate and draw our chart, passing in some options. 
    var chart = new google.visualization.ColumnChart(document.getElementById(elementId)); 
 
    // Draw chart. 
    chart.draw(view, options); 
 
    // Link interaction. 
    var selectHandler = function (e) 
    { 
        // Verification. 
        if (chart.getSelection() != null && 
             chart.getSelection()[0] != null && 
             chart.getSelection()[0]['row'] != null && 
             chart.getSelection().length > 0) 
        { 
            if (chart.getSelection()[0]['column'] == 1) 
            { 
                // Setting. 
                var link = data.getValue(chart.getSelection()[0]['row'], 2) 
                window.open(link, '_blank'); 
            } 
        } 
    } 
 
    // Add our selection handler. 
    google.visualization.events.addListener(chart, 'select', selectHandler); 
}


Let's break down the code chunk by chunk. First, I have loaded the Google Charts API charts visualization package.
// Load the Visualization API and the piechart package. 
google.load('visualization', '1.0', { 'packages': ['corechart'] });


Then, I call the GetData() server side method via AJAX call and after successfully receiving the data, I simply set the default chart options then pass those options to a user-define JavaScript method "drawGraph(...)".
// Set a callback to run when the Google Visualization API is loaded. 
$(document).ready(function () 

    $.ajax( 
    { 
        type: 'POST', 
        dataType: 'JSON', 
        url: '/Home/GetData', 
        success: 
            function (response) 
            { 
                // Set chart options 
                var options = 
                    { 
                        width: 1100, 
                        height: 900, 
                        sliceVisibilityThreshold: 0, 
                        legend: { position: "top", alignment: "end" }, 
                        chartArea: { left: 370, top: 50, height: "90%" }, 
                        hAxis: 
                            { 
                                slantedText: true, 
                                slantedTextAngle: 18 
                            }, 
                        bar: { groupWidth: "50%" }, 
                    }; 
 
                // Draw. 
                drawGraph(response, options, 'graphId'); 
            } 
    }); 
});


Now, in the below drawGraph(...) method code, I add three new columns per row, the zero column will be the name of the products which will be shown on the chart axis, the first column will be the unit price of the product which will be shown on the graph for each product. After adding the column metadata for the chart, I will convert the received data from the server into DataTables data type accepted by the chart. Then I will set the annotation option for the first chart column which will display the correspondent values on the chart columns per each product. Then, I will draw the ColumnChart by calling Google charts API method. Next, I add the selection handler which will map target link to the target chart display column. Finally, I add the listener event which will call our selection handler method and open the link in a new window as we have coded in the selection handler; i.e.:

// Callback that creates and populates a data table, 
// instantiates the pie chart, passes in the data and 
// draws it. 
function drawGraph(dataValues, options, elementId) { 
    // Initialization. 
    var data = new google.visualization.DataTable(); 
 
    // Setting. 
    data.addColumn('string', 'Product Name'); 
    data.addColumn('number', 'Unit Price'); 
    data.addColumn('string', 'Link'); 
 
    // Processing. 
    for (var i = 0; i < dataValues.length; i++) 
    { 
        // Setting. 
        data.addRow([dataValues[i].ProductName, dataValues[i].UnitPrice, dataValues[i].Link]); 
    } 
 
    // Setting label. 
    var view = new google.visualization.DataView(data); 
    view.setColumns([0, 1, 
        { 
            calc: "stringify", 
            sourceColumn: 1, 
            type: "string", 
            role: "annotation" 
        } 
    ]); 
 
    // Instantiate and draw our chart, passing in some options. 
    var chart = new google.visualization.ColumnChart(document.getElementById(elementId)); 
 
    // Draw chart. 
    chart.draw(view, options); 
 
    // Link interaction. 
    var selectHandler = function (e) 
    { 
        // Verification. 
        if (chart.getSelection() != null && 
             chart.getSelection()[0] != null && 
             chart.getSelection()[0]['row'] != null && 
             chart.getSelection().length > 0) 
        { 
            if (chart.getSelection()[0]['column'] == 1) 
            { 
                // Setting. 
                var link = data.getValue(chart.getSelection()[0]['row'], 2) 
                window.open(link, '_blank'); 
            } 
        } 
    } 
 
    // Add our selection handler. 
    google.visualization.events.addListener(chart, 'select', selectHandler); 
}


Step 6
Create "Views\Home\_ViewGraphPartial.cshtml" & "Views\Home\Index.cshtml" files and replace following code in it.
Views\Home\_ViewGraphPartial.cshtml
<section> 
    <div class="well bs-component"> 
        <div class="row"> 
            <div class="col-xs-12"> 
                <!-- CHART --> 
                <div class="box box-primary"> 
                    <div class="box-header with-border"> 
                        <h3 class="box-title custom-heading">Product wise Graph</h3> 
                    </div> 
                    <div class="box-body"> 
                        <div class="chart"> 
                            <div id="graphId" style="width: 1100px; height: 900px; margin:auto;"></div> 
                        </div> 
                    </div><!-- /.box-body --> 
                </div><!-- /.box --> 
            </div> 
        </div> 
    </div> 
</section>


View\Home\Index.cshtml
@{ 
    ViewBag.Title = "ASP.NET MVC5 - Clickable Google Charts"; 

 
<div class="row"> 
    <div class="panel-heading"> 
        <div class="col-md-8  custom-heading3"> 
            <h3> 
                <i class="fa fa-pie-chart"></i> 
                <span>ASP.NET MVC5 - Clickable Google Charts</span> 
            </h3> 
        </div> 
    </div> 
</div> 
 
<div class="row"> 
    <section class="col-md-12 col-md-push-0"> 
        @Html.Partial("_ViewGraphPartial") 
    </section> 
</div>


In the above code, I have simply created the view code for the page which will display the chart. I have divided the page into two parts for better manageability.

Step 7
Now, create new "Views\Home\TestPage.cshtml" file and replace following code in it.
@{ 
    ViewBag.Title = "ASP.NET MVC5 - Clickable Google Charts"; 

 
<div class="row"> 
    <div class="panel-heading"> 
        <div class="col-md-8  custom-heading3"> 
            <h3> 
                <i class="fa fa-pie-chart"></i> 
                <span>ASP.NET MVC5 - Clickable Google Charts</span> 
            </h3> 
        </div> 
    </div> 
</div> 
 
<div class="row"> 
    <section class="col-md-12 col-md-push-0"> 
        <div class="well bs-component"> 
            <div class="row"> 
                <div class="col-xs-12"> 
                    <h1>Hello! I am Clickable Test Page</h1> 
                </div> 
            </div> 
        </div> 
    </section> 
</div>


In the above code, I have simply added a new page structure for the chart click event target.

HostForLIFE.eu ASP.NET MVC 6 Hosting
HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes. We have customers from around the globe, spread across every continent. We serve the hosting needs of the business and professional, government and nonprofit, entertainment and personal use market segments.

 



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in