This post is the second post in the WebGrid series. I have previously shared a post explaining how to create a WebGrid in MVC from scratch for both C# and VB programmers. If you have come directly to this post, then I would recommend, please check the previous post’s code. Since the example, here extends the code and procedures from the previous post.
Here’s what I am doing. I have two tables in my SQL Server database. I’ll extract data from the master table, that is dbo.Products and bind the data to the WebGrid. I want to extract more (misc.) details, based on the WebGrid’s selected row value, by making an Ajax call to server, which will fetch data from the details table called dbo. ProductDetails.
The example here uses data from two tables, a Master table and Details table. I have created the Product Master table here. Now lets create the product details table.
CREATE TABLE [dbo].[ProductDetails]( [Product_ID] [int] NULL, [Brand] [varchar](100) NULL, [Price] [numeric](18, 2) NULL, [Availability] [varchar](10) NULL, [Quantity] [int] NULL )
Add few rows of data to the table.
INSERT INTO ProductDetails (Product_ID, Brand, Price, Availability, Quantity) VALUES (1, 'Natrag', 20, 'In Stock', 110), (2, 'Mono', 15, 'In Stock', 200), (3, 'Elxin', 17.5, 'In Stock', 121), (4, 'Parcc', 275, 'In Stock', 10), (5, 'Smart', 22, 'In Stock', 87), (6, 'Doms', 40, 'In Stock', 11), (7, 'X-Presso', 175, 'In Stock', 65)
Once your database is ready, create your MVC project for WebGrid.
The Model (C# Code)
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace webgridSample.Models { public class modelProducts { // PROPERTIES FOR PRODUCTS. public int ProductID { get; set; } public string ProductName { get; set; } public string Brand { get; set; } // PROPERTIES FOR PRODDUCT DETAILS. public decimal Price { get; set; } public string Availability { get; set; } public int Quantity { get; set; } } }
If you have checked my previous post on Introduction to WebGrid in MVC, then you’ll see the Model had properties for the Product Master. In the above Model I have added few more properties (the last 3) for Product Details.
Option Explicit On Namespace webgridSample.Models Public Class modelProducts ' PROPERTIES FOR PRODUCTS. Public Property ProductID() As Integer Get Return m_ProductID End Get Set(value As Integer) m_ProductID = value End Set End Property Private m_ProductID As Integer Public Property ProductName() As String Get Return m_ProductName End Get Set(value As String) m_ProductName = value End Set End Property Private m_ProductName As String Public Property Brand() As String Get Return m_Brand End Get Set(value As String) m_Brand = value End Set End Property Private m_Brand As String ' PROPERTIES FOR PRODUCT DETAILS. Public Property Price() As Decimal Get Return m_Price End Get Set(value As Decimal) m_Price = value End Set End Property Private m_Price As Decimal Public Property Availability() As String Get Return m_Availability End Get Set(value As String) m_Availability = value End Set End Property Private m_Availability As String Public Property Quantity() As Integer Get Return m_Quantity End Get Set(value As Integer) m_Quantity = value End Set End Property Private m_Quantity As String End Class End Namespace
Now let us create the controller. If you haven’t created the controller yet, click this link, to learn the procedure to create a Controller
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using webgridSample.Models; using System.Data.SqlClient; namespace webgridSample.Controllers { public class productsController : Controller { const string sConnString = "Data Source=DNA;Persist Security Info=False;" + "Initial Catalog=DNA_Classified;User Id=sa;Password=demo;Connect Timeout=30;"; // LIST OBJECT WILL HOLD AND RETURN A LIST OF PRODUCTS. List<modelProducts> ourProducts = new List<modelProducts>(); public ActionResult viewProducts(modelProducts list) { using (SqlConnection con = new SqlConnection(sConnString)) { // QUERY THE TABLE FOR DATA. using (SqlCommand cmd = new SqlCommand("SELECT *FROM dbo.Product")) { cmd.Connection = con; con.Open(); SqlDataReader reader = cmd.ExecuteReader(); // POPULATE THE LIST WITH DATA. while (reader.Read()) { ourProducts.Add(new modelProducts { ProductID = Convert.ToInt32(reader["Product_ID"]), ProductName = reader["ProductName"].ToString(), Brand = reader["Brand"].ToString() }); } con.Close(); } } return View(ourProducts); } List<modelProducts> prodDetails = new List<modelProducts>(); [HttpGet()] public ActionResult getProductDetails(int id) // THE METHOD TO RECEIVE A REQUEST. { if (id != 0) { using (SqlConnection con = new SqlConnection(sConnString)) { using (SqlCommand cmd = new SqlCommand("SELECT *FROM dbo.ProductDetails WHERE Product_ID = " + id)) { cmd.Connection = con; con.Open(); SqlDataReader reader = cmd.ExecuteReader(); // POPULATE THE LIST WITH PRODUCT DETAILS. while (reader.Read()) { prodDetails.Add(new modelProducts { Price = Convert.ToInt32(reader["Price"]), Brand = reader["Brand"].ToString(), Availability = reader["Availability"].ToString(), Quantity = Convert.ToInt32(reader["Quantity"]) }); } con.Close(); } } } // RETURN DATA IN JSON FORMAT. return Json(new { list = prodDetails }, JsonRequestBehavior.AllowGet); } } }
Option Explicit On Imports webgridSample.webgridSample.Models Imports System.Data.SqlClient Namespace webgridSample Public Class productsController Inherits System.Web.Mvc.Controller Const sConnString As String = "Data Source=DNA;Persist Security Info=False;" & _ "Initial Catalog=DNA_Classified;User Id=sa;Password=demo;Connect Timeout=30;" Dim ourProducts As New List(Of modelProducts)() Function viewProducts(list As modelProducts) As ActionResult Using con As SqlConnection = New SqlConnection(sConnString) Using cmd As SqlCommand = New SqlCommand("SELECT *FROM dbo.Product") With cmd .Connection = con con.Open() Dim reader As SqlDataReader = cmd.ExecuteReader() ' POPULATE THE LIST WITH DATA. While reader.Read() ourProducts.Add(New modelProducts() With { _ .ProductID = reader("Product_ID").ToString(), _ .ProductName = reader("ProductName").ToString(), _ .Brand = reader("Brand").ToString() _ }) End While con.Close() End With End Using End Using Return View(ourProducts) End Function Dim prodDetails As New List(Of modelProducts)() ' THE METHOD TO RECEIVE A REQUEST. <HttpGet()> Public Function getProductDetails(ByVal id As Integer) As ActionResult If id <> 0 Then Using con As SqlConnection = New SqlConnection(sConnString) Using cmd As SqlCommand = New SqlCommand("SELECT *FROM dbo.ProductDetails WHERE Product_ID = " & id) cmd.Connection = con con.Open() Dim reader As SqlDataReader = cmd.ExecuteReader() ' POPULATE THE LIST WITH PRODUCT DETAILS. While reader.Read() prodDetails.Add(New modelProducts With { _ .Price = Convert.ToInt32(reader("Price")), .Brand = reader("Brand").ToString(), .Availability = reader("Availability").ToString(), .Quantity = Convert.ToInt32(reader("Quantity"))}) End While con.Close() End Using End Using End If ' RETURN DATA IN JSON FORMAT. Return Json(New With { Key .list = prodDetails }, JsonRequestBehavior.AllowGet) End Function End Class End Namespace
I am creating an object of the WebGrid class. Now, this will allow me to design the grid by adding the Columns etc. using the GetHTML() method (@objGrid.GetHtml). I have also created a <style> tag with classes to add some style to the grid.
The most important section in this View is the last column (with no header). It has an Anchor link attached, with an onclick event that calls a JavaScript function named getProductDetails().
This function has the code to make the Ajax call to the Controller function. The function takes a parameter, which is the ID, the product id, from the first column.
If the Ajax call is success, that is, the controller has processed the request and returned a data in JSON format (see the controller above with [HttpGet()], then it show the data in a <div> element (id = “showDetails”).
@{ ViewBag.Title = "Our Products Inventory"; WebGrid objGrid = new WebGrid(Model, rowsPerPage:5, canSort:false); } @*ADD STYLE FOR THE GRID*@ <style> .grid { font: 17px Calibri; width: 400px; background-color: #FFF; border: solid 1px #CD6736; } .grid td, th { padding: 2px; border: solid 1px #CD6736; text-align: center; text-transform: capitalize; } .grid-header { background-color: #CD6736; color: #FFF; text-align: left; } .grid-footer { color: #000; font: 17px Calibri; text-align: left; } .grid tr:hover { background: #FF0; color: #000; } a { cursor:pointer; color: #1464F4; } </style> @*CREATE AND ADD COLUMNS TO THE WebGrid USING GetHTML() METHOD*@ @objGrid.GetHtml( columns: objGrid.Columns ( objGrid.Column("ProductID", "Product ID"), objGrid.Column("ProductName", "Product Name"), objGrid.Column("Brand"), objGrid.Column(" ", format: (item) => Html.Raw("<a onclick='getProductDetails(" + item.ProductID + ")'>View More</a>")) //ADD A COLUMN WITH A LINK THAT WILL CALL JAVASCRIPT getProductDetails() FUNCTION ), caption: "Products Inventory", tableStyle: "grid", headerStyle: "grid-header", footerStyle: "grid-footer" ) @*jQuery CDN*@ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <div id="showDetails"></div> @*THE ELEMENT TO SHOW OTHER DETAILS*@ <script> function getProductDetails(id) { $.ajax({ type: 'GET', url: 'https://localhost:20196/products/getProductDetails/' + id, success: function (data) { // CREATE A DIV ELEMENT TO SHOW THE EXTRACTED DATA. (SOURCE: https://www.encodedna.com/2013/07/dynamically-add-remove-textbox-control-using-jquery.htm) var div = $(document.createElement('div')).css({ font: '13px Verdana', padding: '5px', margin: '10px 0', width: '170px', border: '1px dashed #777' }); // LOOP THROUGH EACH DATA AND APPEND IT TO THE DYNAMIC DIV. $.each(data, function (index, value) { if (value[0] != undefined) { $(div).append('<b>ID</b>: ' + id + '<br/ >' + '<b>Brand</b>: ' + value[0].Brand + '<br/ >' + '<b>Price</b>: ' + value[0].Price + '<br/ >' + '<b>Quantity</b>: ' + value[0].Quantity + '<br/ >' + '<b>Avalilability</b>: ' + value[0].Availability + '<br/ >'); } else { $(div).append('Details not Available'); } }); $('#showDetails').empty().append(div); } }); } </script>
The visual basic for the view is pretty much the same.
@Code ViewData("Title") = "Our Products Inventory" Dim objGrid As New WebGrid(Model, rowsPerPage:=5) End Code @objGrid.GetHtml( columns:=objGrid.Columns( objGrid.Column("ProductID"), objGrid.Column("ProductName", "Product Name"), objGrid.Column("Brand"), objGrid.Column(" ", , format:=@@<a onclick="getProductDetails(@item.ProductID)">View More</a>) ), caption:="Products Inventory" ) <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <div id="showDetails"></div> <script> function getProductDetails(id) { $.ajax({ type: 'GET', url: 'https://localhost:13771/products/getProductDetails/' + id, success: function (data) { // CREATE A DIV ELEMENT TO SHOW THE EXTRACTED DATA. (SOURCE: https://www.encodedna.com/2013/07/dynamically-add-remove-textbox-control-using-jquery.htm) var div = $(document.createElement('div')).css({ font: '13px Verdana', padding: '5px', margin: '10px 0', width: '170px', border: '1px dashed #777' }); // LOOP THROUGH EACH DATA AND APPEND IT TO THE DYNAMIC DIV. $.each(data, function (index, value) { if (value[0] != undefined) { $(div).append('<b>ID</b>: ' + id + '<br/ >' + '<b>Brand</b>: ' + value[0].Brand + '<br/ >' + '<b>Price</b>: ' + value[0].Price + '<br/ >' + '<b>Quantity</b>: ' + value[0].Quantity + '<br/ >' + '<b>Avalilability</b>: ' + value[0].Availability + '<br/ >'); } else { $(div).append('Details not Available'); } }); $('#showDetails').empty().append(div); } }); } </script>
That’s it. This is just the tip of the iceberg, when discussing about WebGrid in Asp.Net MVC. You can do more than what I have shown in the examples above. I’ll write and share more useful codes and examples on WebGrid in the coming days.