ASP.NET Core Blazor Master/Detail CRUD With Filtering And Sorting Using EF And Web API

Introduction

ASP.NET Core

In this article, let’s see how to create our own ASP.NET Core Blazor Master Detail HTML CRUD (Insert, Update, Select and Delete) for both Master and Detail Grid with Sorting and Filtering using Entity Framework, and Web API.  

Kindly read my previous articles which explains in depth about getting started with ASP.NET Core Blazor.

This article will explain:

  • How to Create Order Master and Order Detail table with sample records inserted.
  • How to create a ASP.NET Core Blazor Web application.
  • How to install the Package for using Entity Framework and creating DBContext class.
  • Create a separate WEB API for both Order Master and Order Detail  
  • How to get result from Web API and bind result in Blazor client Razor view to display our Master/Detail HTML grid.
  • Add Sorting /Filtering features for Master HTML grid.
  • Add/Edit/ and Delete each Order Master and Order Detail from grid. 

Prerequisites

Make sure you have installed all the prerequisites in your computer. If not, then download and install all, one by one. Note that since Blazor is the new framework and we must have installed preview of Visual Studio 2017 (15.7) or above.

Step 1 - Create a database and a table

We will create an Order Master and Order Detail table to be used for the Master and Detail Grid data binding. The following is the script to create a database, table and sample insert query. Run this script in your SQL Server

  1.  use master    
  2. --create DataBase    
  3. -- 1) Check for the Database Exists .If the database is exist then drop and create new DB    
  4. IF EXISTS (SELECT [nameFROM sys.databases WHERE [name] = 'OrderManagement' )    
  5. DROP DATABASE OrderManagement    
  6. GO    
  7.     
  8. CREATE DATABASE OrderManagement    
  9. GO    
  10.     
  11. USE OrderManagement    
  12. GO    
  13.     
  14.     
  15.     
  16. -- Create OrderMasters Table    
  17.     
  18. CREATE TABLE [dbo].[OrderMasters](     
  19. [Order_No] INT IDENTITY PRIMARY KEY,     
  20. [Table_ID] [varchar](20) NOT NULL,     
  21. [Description] [varchar](200) NOT NULL,     
  22. [Order_DATE] [datetime] NOT NULL,     
  23. [Waiter_Name] [varchar](20) NOT NULL    
  24. )    
  25.     
  26.     
  27. -- Insert OrderMasters sample data    
  28.     
  29. INSERT INTO [OrderMasters]     
  30.           ([Table_ID] ,[Description],[Order_DATE],[Waiter_Name])     
  31.     VALUES     
  32.           ('T1','Order for Table T1',GETDATE(),'SHANU' )     
  33.         
  34. INSERT INTO [OrderMasters]     
  35.           ([Table_ID] ,[Description],[Order_DATE],[Waiter_Name])     
  36.     VALUES     
  37.            ('T2','Order for Table T2',GETDATE(),'Afraz' )     
  38.              
  39. INSERT INTO [OrderMasters]     
  40.           ([Table_ID] ,[Description],[Order_DATE],[Waiter_Name])     
  41.      VALUES     
  42.              ('T3','Order for Table T3',GETDATE(),'Afreen')     
  43.                 
  44.     
  45.                 
  46. CREATE TABLE [dbo].[OrderDetails](     
  47.   [Order_Detail_No] INT IDENTITY PRIMARY KEY,    
  48.  [Order_No] INT,    
  49.  [Item_Name] [varchar](20) NOT NULL,      
  50.  [Notes] [varchar](200) NOT NULL,     
  51. [QTY]  INT NOT NULL,     
  52.  [Price] INT NOT NULL     
  53.  )    
  54.     
  55. --Now let’s insert the 3 items for the above Order No 'Ord_001'.     
  56.     
  57. INSERT INTO [OrderDetails]     
  58.           ( [Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  59.    VALUES     
  60.           (1,'Ice Cream','Need very Cold',2 ,160)     
  61.     
  62. INSERT INTO [OrderDetails]     
  63.           ([Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  64.    VALUES     
  65.           (1,'Coffee','Hot and more Suger',1 ,80)     
  66.              
  67.     
  68.           INSERT INTO [OrderDetails]     
  69.           ([Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  70.    VALUES     
  71.           (1,'Burger','Spicy',3 ,140)     
  72.              
  73.           INSERT INTO [OrderDetails]     
  74.           ([Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  75.    VALUES     
  76.           (2,'Pizza','More Chees and Large',1 ,350)     
  77.     
  78.              
  79.           INSERT INTO [OrderDetails]     
  80.           ([Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  81.    VALUES     
  82.           (2,'Cola','Need very Cold',3 ,50)     
  83.              
  84.           INSERT INTO [OrderDetails]     
  85.           ([Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  86.    VALUES     
  87.           (3,'IDLY','Hot',3 ,40)     
  88.     
  89.           INSERT INTO [OrderDetails]     
  90.           ([Order_No],[Item_Name],[Notes],[QTY] ,[Price])     
  91.    VALUES     
  92.           (3,'Thosa','Hot',3 ,50)     
  93.     
  94. -- To Select and test Order Master and Details    
  95.     
  96. Select * FROM OrderMasters    
  97.     
  98. Select * From OrderDetails   

Step 2 - Create ASP.NET Core Blazor Application

After installing all the prerequisites listed above and ASP.NET Core Blazor Language Services, click Start >> Programs >> Visual Studio 2017 >> Visual Studio 2017 on your desktop. Click New >> Project. Select Web >> ASP.NET Core Angular Web Application. Enter your project name and click OK.

ASP.NET Core

Select Blazor (ASP.NET Core hosted) and click ok

ASP.NET Core

After creating ASP.NET Core Blazor Application, wait for few seconds. You will see below structure in solution explorer.

ASP.NET Core

What is new in ASP.NET Core Blazor solution?

When we create our new ASP.NET Core Blazor application we can see that three projects will be automatically created in the solution Explorer.

Client Project

The first project is created as the Client project and it will be our Solutionname.Client and here we can see as our Solutionname as “BlazorASPCORE”. The project is named as client and this project will be mainly focused for all the client-side view. Here we will be adding all our page view to be display in the client side in browser.

ASP.NET Core

We can see as few sample pages have been already added here and we can also see a shared folder like our MVC application where will be having the Sharedfolder and Layout page for the Master page. Here in Blazor we have the MainLayout which will work like the Master page and NavMenu for the left side menu display.

Server Project

As the name indicates this project will be used as a Server project. This project is mainly used to create all our Controllers and WEB API Controllers to perform all business logic and perform CRUD operation using WEB API’s. In our demo application we will be adding a Web API in this Server project and all the WEB API in our Client application. This Server project will work like get/set the data from Database and from our Client project we bind or send the result to this server to perform the CRUD operation in database.

ASP.NET Core

Shared Project

As the name indicates this project works like a shared project. This project works as a Model for our Server project and for the Client project. The Model declared in this Shared project will be used in both the Server and in the Client project. We also install all the packages needed for our project here, for example to use the Entity Framework we install all the packages in this shared project.

ASP.NET Core

Run to test the application

When we run the application, we can see that the left side has navigation and the right side contains the data. We can see as the default sample pages and menus will be displayed in our Blazor web site. We can use the pages or remove it and start with our own page.

ASP.NET Core

Now let’s see how to add new page perform the CRUD operation for maintain Order details.

Using Entity Framework

To use the Entity Framework in our Blazor application we need to install the below packages

Install the Packages

Go to Tools and then select -> NuGet Package Manager -> Package Manager Console.

ASP.NET Core 

You can see the Console at the bottom of the VS 2017 IDE and in the right side of the combobox on the console select the Default project as your shared project” Select Shared”

ASP.NET Core
  • You can see the PM> and copy and paste the below line to install the Database Provider package. This package is used to set the database provider as SQL Servder

Install-Package Microsoft.EntityFrameworkCore.SqlServer

ASP.NET Core

We can see the package is installed in our Shared folder

Install the Entity Framework

  • You can see the PM> and copy and paste the below line to install the EF package.

Install-Package Microsoft.EntityFrameworkCore.Tools

ASP.NET Core

To Create DB Context and set the DB Connection string

  • You can see the PM> and copy and paste the below line set the Connection string and create DB Context. This is an important part as we give our SQL Server name, Database Name and SQL server UID and SQL Server Password to connect to our database to display our Master/Detail Grid. We also give our both SQL Table names, “OrderMasters ,OrderDetails” to create the Model class in our Shared project.

    Scaffold-DbContext "Server= SQLServerName;Database=OrderManagement;user id=SQLID;password=SQLPWD;Trusted_Connection=True;MultipleActiveResultSets=true" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables OrderMasters ,OrderDetails

Press enter to create connection string, Model Class and Database Context.

ASP.NET Core

We can see OrderMasters and OrderDetails Model class and OrderManagementContext class has been created in our Shared project. We will be using this Model and DBContext in our Server project to create our Web API to perform the CRUD operations. 

Creating Web API for Get Order details

To create our WEB API Controller, right click Controllers folder. Click Add New Controller.

ASP.NET Core

Here we will be using Scaffold method to create our WEB API. We select API Controller with actions, using Entity Framework.

ASP.NET Core

Select our Model and DatabaseContext from the Shared project.

ASP.NET Core 

Select our OrderMasters Model from the Shared Project for performing the CRUD operation.

ASP.NET Core

Select the Data Context Class as our OrderManagementContext from the Shared project. Our Controller name will be automatically added if you need you can change it and click the ADD.

ASP.NET Core 

We will be using all the Get/Post/Put and Delete method from our Web API.

Same like this we also create a Web API for our OrderDetails

To test Get Method, we can run our project and copy the GET method API path. Here, we can see our API path to get api/OrderMasters/

Run the program and paste API path to test our output.

ASP.NET Core

For OrderDetails we can pass the Order ID to get only one Orderdetails. Here we can see the result for Order No as “1” ,we call the Web API as /api/OrderDetails/1

ASP.NET Core

Now we will bind all this WEB API Json result in our Razor View page from our Client project for displaying the Master/Detail HTML table for performing CRUD operations and also with Filtering and Sorting options

Working with Client Project

Note
In this article we will create 2 Razor pages. In one Razor page we will create the Master Details HTML table with normal binding method and in another Razor page we will bind the Detail table using Blazor Dynamic Content.

Razor Page with normal binding

First, we need to add the new Razor view page

Add Razor View

To add the Razor view page right click the Pages folder from the Client project. Click on Add >> New Item

ASP.NET Core

Select Razor View >> Enter your page name,Here we have given the name as Orders.cshtml

ASP.NET Core

In Razor view Page we have 3 parts of code.  The first is the Import part where we import all the references and models for using in the view, HTML design and data bind part and finally we have the function part to call all the web API to bind in our HTML page and also to perform client-side business logic to be displayed in View page.

Import part

First, we import all the needed support files and references in our Razor View page.vHere we have first imported our Model class to be used in our view and also imported HTTPClient for calling the Web API to perform the CRUD operations.

  1. @using MasterDetailCRUD.Shared  
  2. @using MasterDetailCRUD.Shared.Models  
  3. @page "/Orders"  
  4. @using Microsoft.AspNetCore.Blazor.Browser.Interop  
  5.   
  6. @using System.Collections.Generic  
  7. @using Microsoft.AspNetCore.Blazor   

Master HTML Grid data Bind part

Next, we design our Order page to bind the Order Master and Order Detail results from the Web API to HTML table.

ASP.NET Core

Binding Order Master Details

In the Init Method we get the Order Master from Web API and bind the result in HTML table using foreach loop. Here we bind the result for Order Master Grid and in each row's first column we add the Toggle image and, in this Toggle, image click event. We call the getOrderDetails(OrderNo) method to display the Detail HTML grid for the related Order. We pass the Order number to the function and we get the related Order details for the Order and bind the result in detail grid also we will show the detail grid only when the toggle image button is clicked and if the toggle button clicked again we hide the detail grid. We also have Edit and Delete  buttons to edit and delete the Order Master record from database.

  1. @foreach (var OrderMasterobj in ordMaster) 
  2.       {  
  3.           <tr style="border-style:dashed;border-width:2px;border-color: @(OrderMasterobj.OrderNo == orderIDs ? "#ff6a00": "#a2aabe")">  
  4.               <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  5.   
  6.                   @if (@OrderMasterobj.OrderNo == orderIDs)  
  7.                   {  
  8.                       <img src="@Imagename" onclick="@(async () => await getOrderDetails(@OrderMasterobj.OrderNo))" />  
  9.                   }  
  10.                   else  
  11.                   {  
  12.                       <img src="Images/toggle.png" onclick="@(async () => await getOrderDetails(@OrderMasterobj.OrderNo))" />  
  13.   
  14.                   }  
  15.   
  16.               </td>  
  17.               <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  18.                   <span style="color:#9F000F">  
  19.                       <img src="Images/edit.gif" alt="Edit" width="24px" height="24px" onclick="@(async () => await EditOrderMaster(@OrderMasterobj.OrderNo))" />  
  20.                   </span>  
  21.               </td>  
  22.               <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  23.                   <span style="color:#9F000F">  
  24.                       <img src="Images/delete.gif" alt="Delete" width="24px" height="24px" onclick="@(async () => await DeleteOrderMaster(@OrderMasterobj.OrderNo))" />  
  25.                   </span>  
  26.               </td>  
  27.               <td align="left" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  28.                   <span style="color:#9F000F">  
  29.                       @OrderMasterobj.OrderNo  
  30.                   </span>  
  31.               </td>  
  32.               <td align="left" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  33.                   <span style="color:#9F000F">  
  34.                       @OrderMasterobj.TableId  
  35.                   </span>  
  36.               </td>  
  37.               <td align="left" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  38.                   <span style="color:#9F000F">  
  39.                       @OrderMasterobj.Description  
  40.                   </span>  
  41.               </td>  
  42.               <td align="left" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  43.                   <span style="color:#9F000F">  
  44.                       @OrderMasterobj.OrderDate  
  45.                   </span>  
  46.               </td>  
  47.               <td align="left" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  48.                   <span style="color:#9F000F">  
  49.                       @OrderMasterobj.WaiterName  
  50.                   </span>  
  51.               </td>  
  52.           </tr>   

Function Part

Function part calls all the web APIs to bind in our HTML page and also to perform client-side business logic to be displayed in View page.

Init Method

In the Init method we get the result of Web API for Order Master and store it in the ordMaster object and we using this object to be bound in our html table using the foreach statement.

  1. @functions {  
  2.     OrderMasters[] ordMaster;  
  3.     OrderDetails[] ordDetail;  
  4.   
  5.   
  6.     OrderMasters ordsM = new OrderMasters();  
  7.     OrderDetails ordsD = new OrderDetails();  
  8.   
  9.     Boolean showAddMaster = false;  
  10.     Boolean showAddDetail = false;  
  11.   
  12.     int showDetailStatus = 0;  
  13.     int sortStatus = 0;  
  14.     int orderIDs = 0;  
  15.     string Imagename = "Images/toggle.png";  
  16.     string ImageSortname = "Images/sortAsc.png";  
  17.   
  18.     string Messages = "";  
  19.   
  20.     protected override async Task OnInitAsync()  
  21.     {  
  22.         ordMaster = await Http.GetJsonAsync<OrderMasters[]>("/api/OrderMasters/");  
  23.         ordsD = new OrderDetails();  
  24.         ordsM = new OrderMasters();  
  25.         Messages = "";  
  26.     }  

Adding Sorting features in Table Heading

Here we have added the Sorting and Filtering features only for the Master HTML table. If needed then we can implement this same feature for Detail grid as well.

In the Master Table heading part for each heading we add the Sorting Image. In Sorting Image Button Click event we call the Sorting function and pass each Sorting Column name to the click event. In Function code part we sort the Web API and display the result by ascending and in descending order by each column header sorting image click.

  1. <table style=" background-color:#FFFFFF; border: solid 2px #6D7B8D; padding: 5px;width: 99%;table-layout:fixed;" cellpadding="2" cellspacing="2">  
  2.   
  3.         <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;border: solid 1px #659EC7;">  
  4.             <td width="120"></td>  
  5.             <td width="40" align="center"><b>Edit</b></td>  
  6.             <td width="40" align="center"><b>Delete</b></td>  
  7.             <td width="120" align="center" style="cursor: pointer;">  
  8.                 <b>OrderNo</b>    
  9.                 <img src="@ImageSortname" onclick="@(async () => await OrderMasterSorting("OrderNo"))" height="24" width="24" />  
  10.   
  11.             </td>  
  12.             <td width="240" align="center" style="cursor: pointer;">  
  13.                 <b>Table Name</b>    
  14.                 <img src="@ImageSortname" onclick="@(async () => await OrderMasterSorting("TableId"))" height="24" width="24" />  
  15.   
  16.             </td>  
  17.             <td width="240" align="center" style="cursor: pointer;">  
  18.                 <b>Description</b>    
  19.                 <img src="@ImageSortname" onclick="@(async () => await OrderMasterSorting("Description"))" height="24" width="24" />  
  20.   
  21.             </td>  
  22.             <td width="120" align="center" style="cursor: pointer;">  
  23.                 <b> Order Date</b>    
  24.                 <img src="@ImageSortname" onclick="@(async () => await OrderMasterSorting("OrderDate"))" height="24" width="24" />  
  25.             </td>  
  26.             <td width="340" align="center" style="cursor: pointer;">  
  27.                 <b> Waiter Name</b>    
  28.                 <img src="@ImageSortname" onclick="@(async () => await OrderMasterSorting("WaiterName"))" height="24" width="24" />  
  29.   
  30.             </td>  
  31.         </tr>  

Sorting Method

In Sorting image click on each column heading. We call this method and pass the column name to this method. This method depends on column name. We do sorting of the Web API result and bind the result in the HTML table. We also do the reverse sorting of ascending and descending.

  1. //Order Master  
  2.   
  3.     protected async Task OrderMasterSorting(string SortColumn)  
  4.     {  
  5.         ordMaster = await Http.GetJsonAsync<OrderMasters[]>("/api/OrderMasters/");  
  6.         Messages = "";  
  7.   
  8.         if (sortStatus == 1)  
  9.         {  
  10.             ImageSortname = "Images/sortDec.png";  
  11.             sortStatus = 0;  
  12.   
  13.             switch (SortColumn)  
  14.             {  
  15.                 case "OrderNo":  
  16.                     ordMaster = ordMaster.OrderBy(x => x.OrderNo).ToArray();  
  17.                     break;  
  18.                 case "TableId":  
  19.                     ordMaster = ordMaster.OrderBy(x => x.TableId).ToArray();  
  20.                     break;  
  21.   
  22.                 case "Description":  
  23.                     ordMaster = ordMaster.OrderBy(x => x.Description).ToArray();  
  24.                     break;  
  25.                 case "OrderDate":  
  26.                     ordMaster = ordMaster.OrderBy(x => x.OrderDate).ToArray();  
  27.                     break;  
  28.                 case "WaiterName":  
  29.                     ordMaster = ordMaster.OrderBy(x => x.WaiterName).ToArray();  
  30.                     break;  
  31.             }  
  32.         }  
  33.         else  
  34.         {  
  35.             ImageSortname = "Images/sortAsc.png";  
  36.             sortStatus = 1;  
  37.   
  38.             switch (SortColumn)  
  39.             {  
  40.                 case "OrderNo":  
  41.                     ordMaster = ordMaster.OrderByDescending(x => x.OrderNo).ToArray();  
  42.                     break;  
  43.                 case "TableId":  
  44.                     ordMaster = ordMaster.OrderByDescending(x => x.TableId).ToArray();  
  45.                     break;  
  46.   
  47.                 case "Description":  
  48.                     ordMaster = ordMaster.OrderByDescending(x => x.Description).ToArray();  
  49.                     break;  
  50.                 case "OrderDate":  
  51.                     ordMaster = ordMaster.OrderByDescending(x => x.OrderDate).ToArray();  
  52.                     break;  
  53.                 case "WaiterName":  
  54.                     ordMaster = ordMaster.OrderByDescending(x => x.WaiterName).ToArray();  
  55.                     break;  
  56.             }  
  57.         }  
  58.     }  

Adding Filtering features in Table Heading

In the Table heading part we add a new row. In table row we add the Textbox for each column to perform the filtering for the bound result. In Textbox onChange event we call the method to perform the Filtering operation from the code function part.

  1. <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;">  
  2.           <td width="140" align="center" colspan="4">  
  3.               <img src="Images/filter.png" width="24" height="24" /> Filter By  
  4.           </td>  
  5.           <td width="180" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;">  
  6.               <input width="70" onchange=@OnTableIdChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  7.           </td>  
  8.           <td width="180" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;">  
  9.               <input width="70" onchange=@OnDescriptionChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  10.           </td>  
  11.           <td width="180" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;"></td>  
  12.           <td width="180" align="center" style="border: solid 1px #FFFFFF; padding: 5px;table-layout:fixed;">  
  13.               <input width="70" onchange=@OnWaiterNameChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  14.           </td>  
  15.       </tr>  

Filtering Method

In each column heading part we have added a new row for performing the filtering of the HTML grid. In each column filter Textbox Change event we pass the textbox value. We call a common filtering method, OrderMasterFilteringList, and in this method we pass the filtering column Textbox value and column Name.

  1. // For Filtering by OrderNo  
  2.     void OnOrderNoChanged(UIChangeEventArgs args)  
  3.     {  
  4.         string values = args.Value.ToString();  
  5.         OrderMasterFilteringList(values, "OrderNo");  
  6.     }  
  7.   
  8.   
  9.     // For Filtering by TableId  
  10.     void OnTableIdChanged(UIChangeEventArgs args)  
  11.     {  
  12.         string values = args.Value.ToString();  
  13.         OrderMasterFilteringList(values, "TableId");  
  14.     }  
  15.   
  16.   
  17.     // For Filtering by Description  
  18.     void OnDescriptionChanged(UIChangeEventArgs args)  
  19.     {  
  20.         string values = args.Value.ToString();  
  21.         OrderMasterFilteringList(values, "Description");  
  22.     }  
  23.   
  24.   
  25.     // For Filtering by OrderDate  
  26.     void OnOrderDateChanged(UIChangeEventArgs args)  
  27.     {  
  28.         string values = args.Value.ToString();  
  29.         OrderMasterFilteringList(values, "OrderDate");  
  30.     }  
  31.   
  32.     // For Filtering by WaiterName  
  33.     void OnWaiterNameChanged(UIChangeEventArgs args)  
  34.     {  
  35.         string values = args.Value.ToString();  
  36.         OrderMasterFilteringList(values, "WaiterName");  
  37.     }  

Here we create a common function named as OrderMasterFilteringList and in this method we get the filtering column, Textbox value, and column Name. We do filtering from the Web API and bind the filtering result to the HTML Table.

  1. //Filtering  
  2. protected async Task OrderMasterFilteringList(String Value, string columnName)  
  3. {  
  4.     ordMaster = await Http.GetJsonAsync<OrderMasters[]>("/api/OrderMasters/");  
  5.   
  6.     Messages = "";  
  7.     if (Value.Trim().Length > 0)  
  8.     {  
  9.   
  10.         switch (columnName)  
  11.         {  
  12.   
  13.             case "TableId":  
  14.                 ordMaster = ordMaster.Where(x => x.TableId.Contains(Value)).ToArray();  
  15.                 break;  
  16.             case "Description":  
  17.                 ordMaster = ordMaster.Where(x => x.Description.Contains(Value)).ToArray();  
  18.                 break;  
  19.             case "WaiterName":  
  20.                 ordMaster = ordMaster.Where(x => x.WaiterName.Contains(Value)).ToArray();  
  21.                 break;  
  22.         }  
  23.   
  24.     }  
  25.     else  
  26.     {  
  27.         ordMaster = await Http.GetJsonAsync<OrderMasters[]>("/api/OrderMasters/");  
  28.     }  
  29. }  

Insert New Order Master

In the ADD New Order Master button click we will make visible the New Order Master Add table, where the user can enter the new Order information.

  1. <table width="100%" style="background:#05163D;color:honeydew">  
  2.     <tr>  
  3.         <td width="20"> </td>  
  4.         <td>  
  5.             <h2> Add New Order Master Information</h2>  
  6.         </td>  
  7.         <td> </td>  
  8.         <td align="right">  
  9.             <button class="btn btn-info" onclick="@AddNewOrderMasters">Add New Order</button>  
  10.         </td>  
  11.         <td width="10"> </td>  
  12.     </tr>  
  13.     <tr>  
  14.         <td colspan="2"></td>  
  15.     </tr>  
  16. </table>  

For a new Order Master we will make the OrderNo as 0. In the New Order Master save button click we will call the save method.

ASP.NET Core

When Add New Order button is clicked we show the Add/Edit Order Master. Here user can update or add new Order Master.

  1. @if (showAddMaster == true)  
  2. {  
  3.     <table style=" background-color:#FFFFFF; border: dashed 3px #6D7B8D; padding: 5px;width: 99%;table-layout:fixed;" cellpadding="2" cellspacing="2">  
  4.         <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;border: solid 1px #659EC7;">  
  5.             <td>  
  6.                 <h3> Add/Edit Order Master</h3>  
  7.             </td>  
  8.   
  9.         </tr>  
  10.         <tr>  
  11.             <td>  
  12.                 <table class="form-group">  
  13.                     <tr>  
  14.                         <td>  
  15.                             <label for="Name" class="control-label">Order No</label>  
  16.                         </td>  
  17.                         <td>  
  18.                             <input type="text" class="form-control" bind="@ordsM.OrderNo" readonly />  
  19.                         </td>  
  20.                         <td width="20"> </td>  
  21.                         <td>  
  22.                             <label for="Name" class="control-label">Table Name</label>  
  23.                         </td>  
  24.                         <td>  
  25.                             <input type="text" class="form-control" bind="@ordsM.TableId" />  
  26.                         </td>  
  27.                     </tr>  
  28.                     <tr>  
  29.                         <td>  
  30.                             <label for="Email" class="control-label">Description</label>  
  31.                         </td>  
  32.                         <td>  
  33.                             <input type="text" class="form-control" bind="@ordsM.Description" />  
  34.                         </td>  
  35.                         <td width="20"> </td>  
  36.                         <td>  
  37.                             <label for="Name" class="control-label">Date</label>  
  38.                         </td>  
  39.                         <td>  
  40.                             <input type="text" class="form-control" bind="@ordsM.OrderDate" />  
  41.                         </td>  
  42.                     </tr>  
  43.                     <tr>  
  44.                         <td>  
  45.                             <label for="Name" class="control-label">Waiter Name</label>  
  46.                         </td>  
  47.                         <td>  
  48.                             <input type="text" class="form-control" bind="@ordsM.WaiterName" />  
  49.                         </td>  
  50.                         <td width="20"> </td>  
  51.                         <td></td>  
  52.                         <td>  
  53.                             <button type="submit" class="btn btn-success" onclick="@(async () => await SaveOrderMasters())" style="width:220px;">Save</button>  
  54.                         </td>  
  55.                     </tr>  
  56.                 </table>  
  57.             </td>  
  58.         </tr>  
  59.     </table>  

Save Method

In the Save method we will check for the OrderNo. If the OrderNo is “0” then it will insert the new Order Master. Here we will call the Insert Web API method and if the OrderNo is > 0 then it means to update the Order record.

  1. //Save New or update Order Master  
  2.   
  3.     protected async Task SaveOrderDetails()  
  4.     {  
  5.         if (ordsD.OrderDetailNo == 0)  
  6.   
  7.         {  
  8.             await Http.SendJsonAsync(HttpMethod.Post, "/api/OrderDetails/", ordsD);  
  9.   
  10.         }  
  11.         else  
  12.         {  
  13.             await Http.SendJsonAsync(HttpMethod.Put, "/api/OrderDetails/" + ordsD.OrderDetailNo, ordsD);  
  14.         }  
  15.   
  16.         ordDetail = await Http.GetJsonAsync<OrderDetails[]>("/api/OrderDetails/" + Convert.ToInt32(ordsD.OrderNo));  
  17.         ordsD = new OrderDetails();  
  18.         showAddDetail = false;  
  19.         showAddMaster = false;  
  20.         Messages = "Order Detail Saved to Databse !";  
  21.     }  

ASP.NET Core

Update Order Master

The same as with Insert, we will display the update details for the user to edit the Order Master and save it. In the Edit method we will get all the details for the row where the user clicks on the Edit Icon and sets all the results to the appropriate TextBox. In the Save button click we will call the save method to save all the changes to the database like Insert.

  1. //Edit Order Master  
  2.   
  3.   protected async Task EditOrderMaster(int OrderNos)  
  4.   {  
  5.       showAddMaster = true;  
  6.       ordsM = await Http.GetJsonAsync<OrderMasters>("/api/OrderMasters/" + Convert.ToInt32(OrderNos));  
  7.   }  

Delete Order Master Details

In the Delete button click, we will delete the Order by passing the OrderNo to the delete method of the Web API to delete the record from the database.

  1. //Delete Order Master  
  2.     protected async Task DeleteOrderMaster(int OrderNos)  
  3.     {  
  4.         // ids = studentID.ToString();  
  5.         await Http.DeleteAsync("/api/OrderMasters/" + Convert.ToInt32(OrderNos));  
  6.   
  7.   
  8.         // await Http.DeleteAsync("/api/StudentMasters/Delete/" + Convert.ToInt32(studentID));  
  9.   
  10.         ordMaster = await Http.GetJsonAsync<OrderMasters[]>("/api/OrderMasters/");  
  11.         Messages = "Order Master Deleted from Database !";  
  12.     }  

ASP.NET Core

Detail Grid Bind the Detail Grid result

ASP.NET Core

Firstly, we check if the OrderDetail result is null, if it’s not null then we bind the result in HTML Table, before binding the result we also check for the showDetailStatus ==1 which means to show or hide the Detail Grid. By default, we set the showDetailStatus   as 0 and in Master grid Toggle image click event we change the status to 1 and if the showDetailStatus is 1 then we display the Detail grid we also check the Master grid OrderNo with Order detail and bind the result in Detail Grid.

  1. @if (ordDetail != null)  
  2.        {  
  3.            @if (showDetailStatus == 1)  
  4.            {  
  5.                @if (@OrderMasterobj.OrderNo == orderIDs)  
  6.                {  
  7.                    <tr style="background-color:#6D7B8D ; color:honeydew ;border-style:dashed;border-width:2px;border-color:#ECF3F4;">  
  8.                        <td colspan="8" align="center">  
  9.                            Order Details of  Order NO - <strong> @OrderMasterobj.OrderNo </strong> ,Total @ordDetail.Length  details for this Order  
  10.                        </td>  
  11.                    </tr>  
  12.                    <tr>  
  13.                        <td valign="top">  
  14.                            <button class="btn btn-info" onclick="@(async () => await AddNewOrderDetails(@OrderMasterobj.OrderNo))">Add New Detail</button>  
  15.                        </td>  
  16.                        <td colspan="7">  
  17.   
  18.                            <table style="background-color:#ECF3F4; border: solid 2px #3273d5; padding: 5px;width: 99%;table-layout:fixed;">  
  19.   
  20.                                <tr style="height: 30px; background-color:#336699 ; color:#FFFFFF ;">  
  21.                                    <td width="40" align="center"><b>Edit</b></td>  
  22.                                    <td width="40" align="center"><b>Delete</b></td>  
  23.                                    <td width="240" align="center">  
  24.                                        <b> Order Number</b>  
  25.                                    </td>  
  26.                                    <td width="240" align="center">  
  27.                                        <b>  Order Detail Number</b>  
  28.                                    </td>  
  29.                                    <td width="120" align="center">  
  30.                                        <b> Item Name</b>  
  31.                                    </td>  
  32.                                    <td width="340" align="center">  
  33.                                        <b>Comments</b>  
  34.                                    </td>  
  35.                                    <td width="120" align="center">  
  36.                                        <b>  QTY</b>  
  37.                                    </td>  
  38.                                    <td width="120" align="center">  
  39.                                        <b> Price</b>  
  40.                                    </td>  
  41.                                </tr>  
  42.                                @foreach (var orderDetailsObj in ordDetail)  
  43.                                {  
  44.                                    <tr>  
  45.                                        <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  46.                                            <span style="color:#9F000F">  
  47.                                                <img src="Images/edit.gif" alt="Edit" width="24px" height="24px" onclick="@(async () => await EditOrderDetails(@orderDetailsObj.OrderDetailNo))" />  
  48.                                            </span>  
  49.                                        </td>  
  50.                                        <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  51.                                            <span style="color:#9F000F">  
  52.                                                <img src="Images/delete.gif" alt="Delete" width="24px" height="24px" onclick="@(async () => await DeleteOrderDetails(@orderDetailsObj.OrderDetailNo))" />  
  53.                                            </span>  
  54.                                        </td>  
  55.                                        <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  56.                                            @orderDetailsObj.OrderNo  
  57.                                        </td>  
  58.                                        <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  59.   
  60.                                            <span style="color:#9F000F">  
  61.                                                @orderDetailsObj.OrderDetailNo  
  62.                                            </span>  
  63.                                        </td>  
  64.                                        <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  65.                                            <span style="color:#9F000F">  
  66.                                                @orderDetailsObj.ItemName  
  67.                                            </span>  
  68.                                        </td>  
  69.                                        <td align="center" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  70.                                            <span style="color:#9F000F">  
  71.                                                @orderDetailsObj.Notes  
  72.                                            </span>  
  73.                                        </td>  
  74.                                        <td align="right" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  75.                                            <span style="color:#9F000F">  
  76.                                                @orderDetailsObj.Qty  
  77.                                            </span>  
  78.                                        </td>  
  79.   
  80.                                        <td align="right" style="border: solid 1px #659EC7; padding: 5px;table-layout:fixed;">  
  81.                                            <span style="color:#9F000F">  
  82.                                                @orderDetailsObj.Price  
  83.                                            </span>  
  84.                                        </td>  
  85.                                    </tr>  
  86.                                }  
  87.   
  88.                            </table>  
  89.   
  90.   
  91.                        </td>  
  92.                    </tr>  
  93.                }  
  94.            }  
  95.        }  

Detail Grid bind, Hide/Show method

In the Master grid Toggle image click event we call this below method and pass the OrderNo to get the appropriate Order details from the Web API and bind the result in the

  1. //--------------- Detail Grid CRUD  
  2.   
  3.     protected async Task getOrderDetails(int ordID)  
  4.     {  
  5.         showAddMaster = false;  
  6.         showAddDetail = false;  
  7.         Messages = "";  
  8.         if (orderIDs != ordID)  
  9.         {  
  10.             Imagename = "Images/expand.png";  
  11.             showDetailStatus = 1;  
  12.   
  13.         }  
  14.         else  
  15.         {  
  16.             if (showDetailStatus == 0)  
  17.             {  
  18.                 Imagename = "Images/expand.png";  
  19.                 showDetailStatus = 1;  
  20.             }  
  21.             else  
  22.             {  
  23.                 Imagename = "Images/toggle.png";  
  24.                 showDetailStatus = 0;  
  25.             }  
  26.   
  27.         }  
  28.         orderIDs = ordID;  
  29.         ordDetail = await Http.GetJsonAsync<OrderDetails[]>("/api/OrderDetails/" + Convert.ToInt32(ordID));  
  30.     }  

 Order Detail Add/Edit and Delete

 

like the Order Master CRUD, we also do Insert/Edit and Delete for the Order Details. Here from the below gif image we can see the Detail grid bind, Insert, Update and Delete operations.
ASP.NET Core

Navigation Menu

Now we need to add this newly added Orders Razor page to our left Navigation. For adding this Open the Shared Folder and open the NavMenu.cshtml page and add the menu.

  1. <li class="nav-item px-3">  
  2.           <NavLink class="nav-link" href="" Match=NavLinkMatch.All>  
  3.               <span class="oi oi-home" aria-hidden="true"></span> Home  
  4.           </NavLink>  
  5.       </li>  
  6.       <li class="nav-item px-3">  
  7.           <NavLink class="nav-link" href="Orders">  
  8.               <span class="oi oi-plus" aria-hidden="true"></span> Orders Master Detail  
  9.           </NavLink>  
  10.       </li>  

Build and Run the application

ASP.NET Core

Conclusion

In this article we have added only one level of hierarchy of grid, you can extend this to create multilevel hierarchies of the HTML grid. Note as when creating the DBContext and setting the connection string, don’t forget to add your SQL connection string. Hope you all like this article and in the next article we will see more examples to work with Blazor. It's really very cool and awesome to work with Blazor.