Saturday, November 30, 2019

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

Kindly read my previous articles which explain in depth about getting started with ASP.NET Core Blazor.
  • ASP.NET Core Blazor CRUD Using Entity Framework And Web API
  • ASP.NET Core Blazor Filtering And Sorting Using Entity Framework And Web API
This article will explain,
  1. Creating sample database and Student Master and Detail Table in SQL Server to display in our web application.
  2. How to create an ASP.NET Core Blazor Web application.
  3. How to install the Package for using Entity Framework and creating DBContext class.
  4. How to get a result from Web API and bind result in Blazor client Razor view
  5. Creating Master/Detail with Sorting and Filtering features for the HTML table
  6. Creating Master/Detail table using Blazor Dynamic Content.
ASP.NET Core
Blazor Dynamic Content
In Blazor, we can write our own component using the C# Code. We all know that in Blazor, we can write C# code in our client HTML function part, sometimes we need to create and bind the results dynamically to our HTML page. In this article using the Blazor Dynamic Content we create the detail table dynamically and display during the runtime as when the user clicks on the detail grid display icon in master grid.
ASP.NET Core
We can also call this a Master/Detail HTML Grid or Hierarchical Grid or Nested Grid.
Why we need Nested or Hierarchical Grid or Master/Detail Grid
In real time projects like Order Management, Production management, Students Management etc. we need to display the data in the hierarchical result.
For example, let’s take a Student Management project at a University. For student management, we need to create many relational tables like Student Master, Student Details and etc. In Student Master, we store student ID, Name, Email, Phone and Address. In Student Details, we store the students' final exam results for displaying Student Major, Studying Year with Term, and Grade details. Both these tables will be related with StudentID. We join these tables to display the complete student details.

Initially, we will be displaying all the students Master records in HTML table for the view. Users can click on expand icon on each student to view his complete details.
Here, in the below image, we can see that as we bind both the result of Student Master and Student detail in HTML table and we display the detail only when user clicks on the Student Master Icon  which is near to the Student ID.when the user clicks on the Student ID “2”,  then the next details Grid was being displayed to show student results in detail by Major,Year, Term, and Grade.

Here, we are displaying student details by each student Id.
ASP.NET Core
In our example, we also added the Filtering and Sorting functionality for our Master/Detail 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 we must have installed the preview of Visual Studio 2017 (15.7) or above.
Step 1 - Create a database and a table
We will be using our SQL Server database for our WEB API and EF. First, we create a database named StudentsDB and a table as StudentMaster. Here is the SQL script to create a database table and sample record insert query in our table. Run the query given below in your local SQL Server to create a database and a table to be used in our project. 
  1. USE MASTER    
  2. GO    
  3. --1) Check    
  4. --  for the Database Exists.If the database is exist then drop and create new DB    
  5. IF EXISTS(SELECT [nameFROM sys.databases WHERE[name] = 'StudentGradeDB')    
  6. DROP DATABASE StudentGradeDB    
  7. GO    
  8. CREATE DATABASE StudentGradeDB    
  9. GO    
  10. USE StudentGradeDB    
  11. GO    
  12. --1) //////////// StudentMasters    
  13.    
  14. CREATE TABLE[dbo].[StudentMasters](    
  15.         [StdID] INT IDENTITY PRIMARY KEY,  
  16.          [StdName][varchar](100) NOT NULL,  
  17.           [Email][varchar](100) NOT NULL,   
  18.           [Phone][varchar](20) NOT NULL,   
  19.           [Address][varchar](200) NOT NULL  
  20.           )    
  21.     --insert sample data to Student Master table    
  22. INSERT INTO [StudentMasters]([StdName], [Email], [Phone], [Address])    
  23.         VALUES('Shanu''syedshanumcain@gmail.com''01030550007''Madurai,India')    
  24. INSERT INTO [StudentMasters]([StdName], [Email], [Phone], [Address])    
  25.         VALUES('Afraz''Afraz@afrazmail.com''01030550006''Madurai,India')    
  26. INSERT INTO [StudentMasters]([StdName], [Email], [Phone], [Address])    
  27.         VALUES('Afreen''Afreen@afreenmail.com''01030550005''Madurai,India')    
  28.   
  29. select * from[StudentMasters]    
  30.   
  31.  --1) //////////// StudentDetails    
  32. CREATE TABLE[dbo].[StudentDetails](    
  33.     [StdDtlID] INT IDENTITY PRIMARY KEY, [StdID] INT,   
  34.     [Major][varchar](100) NOT NULL,  
  35.      [Year][varchar](30) NOT NULL,   
  36.      [Term][varchar](30) NOT NULL,  
  37.       [Grade][varchar](10) NOT NULL)  
  38.           
  39. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  40.         VALUES(1, 'Computer Science''FirstYear''FirstTerm''A')    
  41. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  42.         VALUES(1, 'Computer Science''FirstYear''SecondTerm''B')    
  43. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  44.         VALUES(1, 'Computer Science''SecondYear''FirstTerm''C')    
  45. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  46.         VALUES(2, 'Computer Engineer''ThirdYear''FirstTerm''A')    
  47. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  48.         VALUES(2, 'Computer Engineer''ThirdYear''SecondTerm''A')    
  49. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  50.         VALUES(3, 'English''First Year''FirstTerm''C')    
  51. INSERT INTO[StudentDetails]([StdID], [Major], [Year], [Term], [Grade])    
  52.         VALUES(3, 'Economics''First Year''FirstTerm''A')    
  53.   
  54. select * from StudentDetails   
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 a few seconds. You will see the 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 3 projects will be automatically created in the solution Explorer.
Client Project
The first project created is the Client project and it will be as our Solutionname.Client and here we can see our Solutionname is “BlazorASPCORE”. This project will be mainly focused for all the client-side view. Here we will be adding all our page views to be displayed in the client side in the browser.
ASP.NET Core
We can see a few sample page have been already added here and we can also see a shared folder like our MVC application where we will have 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 shred 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 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 to perform the CRUD operation for maintaining student 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 name “StudentMasters,StudentDetails” to create the Model class in our Shared project.
Scaffold-DbContext "Server= ServerName;Database=StudentGradeDB;user id=UserID;password=Password;Trusted_Connection=True;MultipleActiveResultSets=true" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables StudentMasters,StudentDetails
Press enter create connection string, Model Class and Database Context.
ASP.NET Core
We can see StudentMasters  and StudentDetails Model class and StudentGradeDBContext 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 Student 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 StudentMasters Model from the Shared Project for performing the CRUD operation.
ASP.NET Core
Select the Data Context Class as our StudentsDBContext 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 only the Get method from our Web API.
Same like this we also create a Web API for our StudentDetails
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/StudentMasters/

Run the program and paste API path to test our output.
ASP.NET Core
For StudentDetails we can pass the Student ID to get only one student details. Here we can see the result for student ID as “1” we call the Web API as /api/StudentDetails/1
ASP.NET Core
Now we will bind all this WEB API Json result in our Razor View page from our Client project for display the Master/Detail HTML table.
Working with Client Project
NoteIn 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 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 Students.chtml
ASP.NET Core
In Razor view Page we have 3 parts of code. The first one  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. Here 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 BLAZORASPCORE.Shared  
  2. @using BLAZORASPCORE.Shared.Models  
  3. @page "/Students"  
  4. @using Microsoft.AspNetCore.Blazor.Browser.Interop  
  5. @inject HttpClient Http  
ASP.NET Core
Master HTML Grid data Bind part
Next, we design our Student page to bind the student Master and Student Detail results from the Web API to HTML table.
Binding Student Master Details
In the Init Method we get the Student Master details from Web API and bind the result in HTML table using foreach loop. Here we bind the result for Student Master Grid and in each row's first column we add the Toggle image and, in this Toggle we call the getStudentsDetails(studentsID) method to display the Detail HTML grid for the related Student. We pass the Student ID to the function and we get the related student details for the student and bind the result in detail grid and also we will show the detail grid only when the toggle image button is clicked and if the toggle button is clicked again we hide the detail grid.
  1. @foreach (var StudentMasters in stdMaster)  
  2.       {  
  3.           <tr style="border-style:dashed;border-width:2px;border-color: @(StudentMasters.StdId == studentIDs ? "#ff6a00": "#a2aabe")">  
  4.               <td align="center" style="border: solid1px#659EC7; padding: 5px;table-layout:fixed;">  
  5.   
  6.                   @if (@StudentMasters.StdId == studentIDs)  
  7.                   {  
  8.                       <img src="@Imagename" onclick="@(async () => await getStudentsDetails(@StudentMasters.StdId))" />  
  9.                   }  
  10.                   else  
  11.                   {  
  12.                       <img src="Images/toggle.png" onclick="@(async () => await getStudentsDetails(@StudentMasters.StdId))" />  
  13.   
  14.                   }  
  15.   
  16.               </td>  
  17.               <td align="center">  
  18.   
  19.                   <span style="color:#9F000F">  
  20.                       @StudentMasters.StdId  
  21.                   </span>  
  22.               </td>  
  23.               <td align="center">  
  24.                   <span style="color:#9F000F">  
  25.                       @StudentMasters.StdName  
  26.                   </span>  
  27.               </td>  
  28.               <td align="center">  
  29.                   <span style="color:#9F000F">  
  30.                       @StudentMasters.Email  
  31.                   </span>  
  32.               </td>  
  33.               <td align="center">  
  34.                   <span style="color:#9F000F">  
  35.                       @StudentMasters.Phone  
  36.                   </span>  
  37.               </td>  
  38.               <td align="center">  
  39.                   <span style="color:#9F000F">  
  40.                       @StudentMasters.Address  
  41.                   </span>  
  42.               </td>  
  43.           </tr>  
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 soring image click.
  1. <table style="background-color:#FFFFFF; border-style:inset;border-width:1px;border-color:#6D7B8D; padding:2px;width:100%;table-layout:fixed;" cellpadding="1" cellspacing="1">  
  2.        <tr style="background-color:#2d364d ; color:#FFFFFF ;border-style:dashed;border-width:2px;border-color:0A2464;" >  
  3.            <td width="30" align="center"></td>  
  4.            <td width="80" align="center">  
  5.                <img src="@ImageSortname" onclick="@(async () => await StudentSorting("StdId"))" height="24" width="24"/>  
  6.                Student ID  
  7.                 
  8.            </td>  
  9.            <td width="240" align="center">  
  10.                <img src="@ImageSortname" onclick="@(async () => await StudentSorting("StdName"))" height="24" width="24"/>     
  11.                Student Name    
  12.            </td>  
  13.            <td width="240" align="center">  
  14.                <img src="@ImageSortname" onclick="@(async () => await StudentSorting("Email"))" height="24" width="24"/>  
  15.                Email   
  16.            </td>  
  17.            <td width="120" align="center">  
  18.                <img src="@ImageSortname" onclick="@(async () => await StudentSorting("Phone"))" height="24" width="24"/>  
  19.                Phone   
  20.            </td>  
  21.            <td width="340" align="center">  
  22.                <img src="@ImageSortname" onclick="@(async () => await StudentSorting("Address"))" height="24" width="24"/>  
  23.                Address   
  24.            </td>  
  25.        </tr>  
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="30" align="center"></td>  
  3.             <td width="80" align="center">Filter : </td>  
  4.             <td width="240" align="center">  
  5.                 <input width="70" onchange=@OnstdNameChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  6.             </td>  
  7.             <td width="240" align="center">  
  8.                 <input width="70" onchange=@OnEmailChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  9.             </td>  
  10.             <td width="120" align="center">  
  11.                 <input width="70" onchange=@OnPhoneChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  12.             </td>  
  13.             <td width="340" align="center">  
  14.                 <input width="70" onchange=@OnAddressChanged oninput="(this.dispatchEvent(new CustomEvent('change', {bubbles: true})))" />  
  15.             </td>  
  16.         </tr>  
Bind the Detail Grid result
Firstly we check the StudentDetails result is null. If its 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 StudentsID with student detail and bind the result in Detail Grid.
  1. @if (stdDetail != null)  
  2.          {  
  3.              @if (showDetailStatus == 1)  
  4.              {  
  5.                  @if (@StudentMasters.StdId == studentIDs)  
  6.                  {  
  7.                      <tr style="background-color:#6D7B8D ; color:honeydew ;border-style:dashed;border-width:2px;border-color:#ECF3F4;">  
  8.                          <td colspan="6" align="center">  
  9.                              Student Details of  Student Id - <strong> @StudentMasters.StdId </strong> ,Total @stdDetail.Length Grade details for this Student  
  10.                          </td>  
  11.                      </tr>  
  12.                      <tr>  
  13.                          <td></td>  
  14.                          <td colspan="5">  
  15.   
  16.                              <table style="background-color:#ECF3F4;border-style:dashed;border-width:2px;border-color:#0A2464; padding:5px;width:100%;table-layout:fixed;" cellpadding="1" cellspacing="1">  
  17.                                  <tr style="background-color:#659EC7 ; color:#FFFFFF ;border-style:dashed;border-width:2px;border-color:0A2464;">  
  18.                                      <td width="160" align="center">  
  19.                                          <Strong>Student Detail</Strong>  
  20.                                      </td>  
  21.                                      <td width="240" align="center">  
  22.                                          Major  
  23.                                      </td>  
  24.                                      <td width="240" align="center">  
  25.                                          Year  
  26.                                      </td>  
  27.                                      <td width="120" align="center">  
  28.                                          Term  
  29.                                      </td>  
  30.                                      <td width="340" align="center">  
  31.                                          Grade  
  32.                                      </td>  
  33.                                  </tr>  
  34.                                  @foreach (var stdDtls in stdDetail)  
  35.                                  {  
  36.                                      <tr>  
  37.                                          <td align="center">  
  38.                                              @stdDtls.StdDtlId  
  39.                                          </td>  
  40.                                          <td align="center">  
  41.   
  42.                                              <span style="color:#9F000F">  
  43.                                                  @stdDtls.Major  
  44.                                              </span>  
  45.                                          </td>  
  46.                                          <td align="center">  
  47.                                              <span style="color:#9F000F">  
  48.                                                  @stdDtls.Year  
  49.                                              </span>  
  50.                                          </td>  
  51.                                          <td align="center">  
  52.                                              <span style="color:#9F000F">  
  53.                                                  @stdDtls.Term  
  54.                                              </span>  
  55.                                          </td>  
  56.                                          <td align="center">  
  57.                                              <span style="color:#9F000F">  
  58.                                                  @stdDtls.Grade  
  59.                                              </span>  
  60.                                          </td>  
  61.                                      </tr>  
  62.                                  }  
  63.   
  64.                              </table>  
  65.   
  66.   
  67.                          </td>  
  68.                      </tr>  
  69.                  }  
  70.              }  
  71.          }  
Function Part
Function part is 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.
Init Method
In the Init method we get the result of Web API for student details and store it in the StudentMaster object and we use this object to be bound in our html table using the foreach statement.
  1. @functions {  
  2.     StudentMasters[] stdMaster;  
  3.     StudentDetails[] stdDetail;  
  4.   
  5.     StudentMasters stdmst = new StudentMasters();  
  6.     StudentDetails stdDtl = new StudentDetails();  
  7.   
  8.     int showDetailStatus = 0;  
  9.     int sortStatus = 0;  
  10.     int studentIDs = 0;  
  11.     string Imagename = "Images/toggle.png";  
  12.     string ImageSortname = "Images/sortAsc.png";  
  13.   
  14.     protected override async Task OnInitAsync()  
  15.     {  
  16.         stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");  
  17.     }  
Detail Grid bind, Hide/Show method
In the Master grid Toggle image click event we call this below method and pass the studentID to get the appropriate student details from the Web API and bind the result.
  1. protected async Task getStudentsDetails(int StudID)  
  2.     {  
  3.         if (studentIDs != StudID)  
  4.         {  
  5.             Imagename = "Images/expand.png";  
  6.             showDetailStatus = 1;  
  7.         }  
  8.         else  
  9.         {  
  10.             if (showDetailStatus == 0)  
  11.             {  
  12.                 Imagename = "Images/expand.png";  
  13.                 showDetailStatus = 1;  
  14.             }  
  15.             else  
  16.             {  
  17.                 Imagename = "Images/toggle.png";  
  18.                 showDetailStatus = 0;  
  19.             }  
  20.   
  21.         }  
  22.         studentIDs = StudID;  
  23.         stdDetail = await Http.GetJsonAsync<StudentDetails[]>("/api/StudentDetails/" + Convert.ToInt32(StudID));  
  24.     }  
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 sort the Web API result and bind the result in the HTML table. We also do the reverse sorting of Ascending and descending.
  1. //Sorting  
  2.   protected async Task StudentSorting(string SortColumn)  
  3.   {  
  4.       stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");  
  5.   
  6.   
  7.       if (ids == 0)  
  8.       {  
  9.           ImageSortname = "Images/sortDec.png";  
  10.           ids = 1;  
  11.   
  12.           switch (SortColumn)  
  13.           {  
  14.               case "StdId":  
  15.                   stdMaster = stdMaster.OrderBy(x => x.StdId).ToArray() ;  
  16.                   break;  
  17.               case "StdName":  
  18.                   stdMaster = stdMaster.OrderBy(x => x.StdName).ToArray();  
  19.                   break;  
  20.   
  21.               case "Email":  
  22.                   stdMaster = stdMaster.OrderBy(x => x.Email).ToArray();  
  23.                   break;  
  24.               case "Phone":  
  25.                   stdMaster = stdMaster.OrderBy(x => x.Phone).ToArray();  
  26.                   break;  
  27.               case "Address":  
  28.                   stdMaster = stdMaster.OrderBy(x => x.Address).ToArray();  
  29.                   break;  
  30.   
  31.           }  
  32.       }  
  33.       else  
  34.       {  
  35.           ImageSortname = "Images/sortAsc.png";  
  36.           ids = 0;  
  37.   
  38.           switch (SortColumn)  
  39.           {  
  40.               case "StdId":  
  41.                   stdMaster = stdMaster.OrderByDescending(x => x.StdId).ToArray();  
  42.                   break;  
  43.               case "StdName":  
  44.                   stdMaster = stdMaster.OrderByDescending(x => x.StdName).ToArray();  
  45.                   break;  
  46.   
  47.               case "Email":  
  48.                   stdMaster = stdMaster.OrderByDescending(x => x.Email).ToArray();  
  49.                   break;  
  50.               case "Phone":  
  51.                   stdMaster = stdMaster.OrderByDescending(x => x.Phone).ToArray();  
  52.                   break;  
  53.               case "Address":  
  54.                   stdMaster = stdMaster.OrderByDescending(x => x.Address).ToArray();  
  55.                   break;  
  56.           }  
  57.       }    
  58.   }  
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 studentFilteringList and in this method we pass the filtering column Textbox value and column Name.
  1. // For Filtering by Student Name  
  2.     void OnstdNameChanged(UIChangeEventArgs args)  
  3.     {  
  4.         string values = args.Value.ToString();  
  5.         studentFilteringList(values, "StudentName");  
  6.     }  
  7.   
  8.   
  9.     // For Filtering by Email  
  10.     void OnEmailChanged(UIChangeEventArgs args)  
  11.     {  
  12.         string values = args.Value.ToString();  
  13.         studentFilteringList(values, "Email");  
  14.     }  
  15.   
  16.   
  17.     // For Filtering by Phone  
  18.     void OnPhoneChanged(UIChangeEventArgs args)  
  19.     {  
  20.         string values = args.Value.ToString();  
  21.         studentFilteringList(values, "Phone");  
  22.     }  
  23.   
  24.   
  25.     // For Filtering by Adress  
  26.     void OnAddressChanged(UIChangeEventArgs args)  
  27.     {  
  28.         string values = args.Value.ToString();  
  29.         studentFilteringList(values, "Address");  
  30.     }  
Here we create a common function named as studentFilteringList 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 studentFilteringList(String Value,string columnName)  
  3. {  
  4.     stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");  
  5.   
  6.     if (Value.Trim().Length >0)  
  7.     {  
  8.         switch (columnName)  
  9.         {  
  10.             case "StudentName":  
  11.                 stdMaster = stdMaster.Where(x => x.StdName.Contains(Value)).ToArray();  
  12.                 break;  
  13.   
  14.             case "Email":  
  15.                 stdMaster = stdMaster.Where(x => x.Email.Contains(Value)).ToArray();  
  16.                 break;  
  17.             case "Phone":  
  18.                 stdMaster = stdMaster.Where(x => x.Phone.Contains(Value)).ToArray();  
  19.                 break;  
  20.             case "Address":  
  21.                 stdMaster = stdMaster.Where(x => x.Address.Contains(Value)).ToArray();  
  22.                 break;  
  23.             default:  
  24.                 stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");  
  25.                 break;  
  26.         }  
  27.     }  
  28.     else  
  29.     {  
  30.         stdMaster = await Http.GetJsonAsync<StudentMasters[]>("/api/StudentMasters/");   
  31.     }   
  32. }  
Razor Page with Dynamic Content
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 Students.chtml
ASP.NET Core
Like our previous Razor view page we use the same logic to bind the Master and the Detail grid but here instead of the direct HTML binding for the Detail grid we bind the detail grid result using the Blazor Dynamic Content. We have already seen the Master data binding and Toggle button click events. Now for this page we will directly explaining only for the Dynamic Content part.
Dynamic Content bind HTML part
Like our previous page we do all status checks and finally bind the Dynamic Content to display the Detail HTML table. We bind the result of Dynamic Content by using @DynamicConten object.
  1. @if (stdDetail != null)  
  2.             {  
  3.                 @if (showDetailStatus == 1)  
  4.                 {  
  5.                     @if (@StudentMasters.StdId == studentIDs)  
  6.                     {  
  7.                         <tr style="background-color:#6D7B8D ; color:honeydew ;border-style:dashed;border-width:2px;border-color:#ECF3F4;">  
  8.                             <td colspan="6" align="center">  
  9.                                 Student Details of  Student Id - <strong> @StudentMasters.StdId </strong> ,Total @stdDetail.Length Grade details for this Student  
  10.                             </td>  
  11.                         </tr>  
  12.                         <tr>  
  13.                             <td></td>  
  14.                             <td colspan="5">  
  15.                                 @DynamicContent  
  16.                             </td>  
  17.                         </tr>  
  18.                     }  
  19.                 }  
  20.             }  
Dynamic Content bind Function
We bind the Dynamic Content results using the RenderFragment object. Using the RenderFragment (Delegate) in our method we build the dynamic content and bind the result dynamically at runtime. 
  1. private Microsoft.AspNetCore.Blazor.RenderFragment DynamicContent;  
In the Detail HTML table grid bind method we create the dynamic Content to display the Detail grid inside the Master grid. In the  calling method every time we dynamically create the Detail grid and bind the result in RederFragment delegate with the use of builder we create table dynamically and bind the results.
  1.   stdDetail = await Http.GetJsonAsync<StudentDetails[]>("/api/StudentDetails/" + Convert.ToInt32(StudID));   
  2.   
  3.     DynamicContent = builder =>  
  4.     {   
  5.   
  6.         var seq = 0;  
  7.         builder.OpenElement(seq, "table");  
  8.         builder.AddAttribute(seq, "style""background-color:#ECF3F4;border-style:dashed;border-width:2px;border-color:#0A2464; padding:5px;width:100%;table-layout:fixed;");  
  9. // Heading  
  10. builder.OpenElement(++seq, "tr");  
  11.         builder.AddAttribute(++seq, "style""height: 30px;border-style:inset;border-width:1px;border-color:#6D7B8D; background-color:#336699 ; color:#FFFFFF ;");  
  12.         builder.OpenElement(++seq, "td");  
  13.         builder.AddContent(++seq, "Student Details");  
  14.   
  15.         builder.CloseElement();  
  16.   
  17.         builder.OpenElement(++seq, "td");  
  18.         builder.AddContent(++seq, "Major");  
  19.   
  20.         builder.CloseElement();  
  21.   
  22.         builder.OpenElement(++seq, "td");  
  23.         builder.AddContent(++seq, "Year");  
  24.   
  25.         builder.CloseElement();  
  26.   
  27.         builder.OpenElement(++seq, "td");  
  28.         builder.AddContent(++seq, "Term");  
  29.   
  30.         builder.CloseElement();  
  31.   
  32.         builder.OpenElement(++seq, "td");  
  33.         builder.AddContent(++seq, "Grade");  
  34.   
  35.         builder.CloseElement();  
  36.         builder.CloseElement();  
  37. //Tbody  
  38.   
  39. foreach (var stdDtls in stdDetail)  
  40.         {  
  41.             builder.OpenElement(++seq, "tr");  
  42.             builder.OpenElement(++seq, "td");   
  43.             builder.AddContent(++seq, stdDtls.StdDtlId);  
  44.   
  45.             builder.CloseElement();  
  46.   
  47.             builder.OpenElement(++seq, "td");   
  48.             builder.AddContent(++seq, stdDtls.Major);  
  49.   
  50.             builder.CloseElement();  
  51.   
  52.             builder.OpenElement(++seq, "td");   
  53.             builder.AddContent(++seq, stdDtls.Year);  
  54.   
  55.             builder.CloseElement();  
  56.   
  57.             builder.OpenElement(++seq, "td");   
  58.             builder.AddContent(++seq, stdDtls.Term);  
  59.   
  60.             builder.CloseElement();  
  61.   
  62.             builder.OpenElement(++seq, "td");   
  63.             builder.AddContent(++seq, stdDtls.Grade);  
  64.   
  65.             builder.CloseElement();  
  66.             builder.CloseElement();  
  67.         }  
  68.   
  69.   
  70.         builder.CloseElement();  
  71.     };  
Navigation Menu
Now we need to add this newly added Students and StudentDynamic 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="/Students">  
  3.         <span class="oi oi-list-rich" aria-hidden="true"></span> Student Details  
  4.     </NavLink>  
  5. </li>  
  6. <li class="nav-item px-3">  
  7.     <NavLink class="nav-link" href="/StudentDynamic">  
  8.         <span class="oi oi-list-rich" aria-hidden="true"></span> Student Dynamic   
  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 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 Blazors. It's really very cool and awesome to work with Blazor.

Lab 09: Publish and subscribe to Event Grid events

  Microsoft Azure user interface Given the dynamic nature of Microsoft cloud tools, you might experience Azure UI changes that occur after t...