天天看点

jsp 构建单页应用_如何使用服务器端Blazor构建单页应用程序

jsp 构建单页应用

介绍 (Introduction)

In this article, we will create a Single Page Application (SPA) using server-side Blazor. We will use an Entity Framework Core database. Single-Page Applications are web applications that load a single HTML page. They dynamically update that page as the user interacts with the app.

在本文中,我们将使用服务器端Blazor创建一个单页应用程序(SPA)。 我们将使用实体框架核心数据库。 单页应用程序是加载单个HTML页面的Web应用程序。 当用户与应用交互时,他们会动态更新该页面。

We will be creating a sample Employee Record Management System. We will perform CRUD operations on it. A modal popup will display the form to handle user inputs. The form will also have a dropdown list which will bind to a database table. We will also provide a filter option to the user to filter the employee records based on employee name.

我们将创建一个示例员工记录管理系统。 我们将对其执行CRUD操作。 模态弹出窗口将显示该表单以处理用户输入。 该表单还将具有一个下拉列表,该列表将绑定到数据库表。 我们还将为用户提供一个过滤选项,以根据员工姓名过滤员工记录。

We will be using Visual Studio 2017 and SQL Server 2017 for our demo.

我们将在演示中使用Visual Studio 2017和SQL Server 2017。

Let us look at the final application:

让我们看一下最终的应用程序:

什么是服务器端Blazor? (What is Server-Side Blazor?)

The release 0.5.0 of Blazor allows us to run Blazor applications on the server. This means that we can run the Blazor component server-side on .NET Core. A SignalR connection over the network will handle other functionalities such as UI updates, event handling, and JavaScript interop calls.

Blazor的0.5.0版本允许我们在服务器上运行Blazor应用程序。 这意味着我们可以在.NET Core的服务器端运行Blazor组件。 通过网络的SignalR连接将处理其他功能,例如UI更新,事件处理和JavaScript互操作调用。

For more information, refer to my previous article on Understanding Server-Side Blazor.

有关更多信息,请参阅我之前的有关理解服务器端Blazor的文章 。

先决条件 (Prerequisites)

  • Install the .NET Core 2.1 or above SDK from here

    从此处安装.NET Core 2.1或更高版本的SDK

  • Install Visual Studio 2017 v15.7 or above from here

    从此处安装Visual Studio 2017 v15.7或更高版本

  • Install ASP.NET Core Blazor Language Services extension from here

    从此处安装ASP.NET Core Blazor语言服务扩展

  • SQL Server 2012 or above.

    SQL Server 2012或更高版本。

Visual Studio 2017 versions below v15.7 do not support the Blazor framework.

v15.7以下的Visual Studio 2017版本不支持Blazor框架。

源代码 (Source Code)

Get the source code for this application from GitHub.

从GitHub获取此应用程序的源代码。

Important Note :

重要的提示 :

This article is valid for Blazor 0.5.0 release. The server-side Blazor might undergo breaking changes in future releases of Blazor.

本文适用于Blazor 0.5.0版本。 服务器端Blazor可能会在Blazor的将来版本中发生重大更改。

建立表格 (Creating a Table)

We will be using two tables to store our data.

我们将使用两个表来存储我们的数据。

  1. Employee: Used to store employee details. It contains fields such as EmployeeID, Name, City, Department, and Gender.

    员工:用于存储员工详细信息。 它包含诸如EmployeeID,姓名,城市,部门和性别之类的字段。

  2. Cities: This contains the list of cities. It is used to populate the City field of the Employee table. It contains two fields, CityID and CityName

    城市:包含城市列表。 它用于填充Employee表的City字段。 它包含两个字段,CityID和CityName

Execute the following commands to create both tables:

执行以下命令来创建两个表:

CREATE TABLE Employee (  
EmployeeID int IDENTITY(1,1) PRIMARY KEY,  
Name varchar(20) NOT NULL ,  
City varchar(20) NOT NULL ,  
Department varchar(20) NOT NULL ,  
Gender varchar(6) NOT NULL  
)    
GO      
      
CREATE TABLE Cities (      
CityID int IDENTITY(1,1) NOT NULL PRIMARY KEY,      
CityName varchar(20) NOT NULL       
)      
GO
           

Now, we will put some data into the Cities table. We will be using this table to bind a dropdown list in our web application. The user will select the desired city from this dropdown. Use the following insert statements:

现在,我们将一些数据放入Cities表中。 我们将使用此表来绑定Web应用程序中的下拉列表。 用户将从该下拉列表中选择所需的城市。 使用以下插入语句:

INSERT INTO Cities VALUES('New Delhi');  
INSERT INTO Cities VALUES('Mumbai');  
INSERT INTO Cities VALUES('Hyderabad');  
INSERT INTO Cities VALUES('Chennai');  
INSERT INTO Cities VALUES('Bengaluru');
           

Now, our Database part is complete. So we will proceed to create the server side application using Visual Studio 2017.

现在,我们的数据库部分已经完成。 因此,我们将继续使用Visual Studio 2017创建服务器端应用程序。

创建服务器端Blazor应用程序 (Create The Server Side Blazor Application)

Open Visual Studio and select File >> New >> Project.

打开Visual Studio,然后选择“文件>>新建>>项目”。

After selecting the project, a “New Project” dialog will open. Select .NET Core inside the Visual C# menu from the left panel. Then, select “ASP.NET Core Web Application” from the available project types. For project name, put in ServerSideSPA and press OK.

选择项目后,将打开“新建项目”对话框。 从左侧面板的Visual C#菜单中选择.NET Core。 然后,从可用的项目类型中选择“ ASP.NET Core Web应用程序”。 对于项目名称,放入ServerSideSPA ,然后按OK。

After clicking on OK, a new dialog will open asking you to select the project template. You will see two drop-down menus at the top left of the template window. Select “.NET Core” and “ASP.NET Core 2.1” from these dropdowns. Then, select the “Blazor (Server-side in ASP.NET Core)” template and press OK

单击确定后,将打开一个新对话框,要求您选择项目模板。 您将在模板窗口的左上方看到两个下拉菜单。 从这些下拉列表中选择“ .NET Core”和“ ASP.NET Core 2.1”。 然后,选择“ Blazor(ASP.NET Core中的服务器端)”模板,然后按OK。

This will create our server-side Blazor solution. You can observe the folder structure in solution explorer, as shown in the below image:

这将创建我们的服务器端Blazor解决方案。 您可以在解决方案资源管理器中观察文件夹结构,如下图所示:

The solution has two project files:

该解决方案有两个项目文件:

  1. ServerSideSPA.App: This is our server-side Blazor app. This project has all our component logic and our services. We will also create our models and data access layer in this project.

    ServerSideSPA.App:这是我们的服务器端Blazor应用程序。 该项目具有我们所有的组件逻辑和服务。 我们还将在此项目中创建模型和数据访问层。

  2. ServerSideSPA.Server: This is the ASP.NET Core hosted application. Instead of running client-side in the browser, the server-side Blazor app will run in the ASP.NET Core host application.

    ServerSideSPA.Server:这是ASP.NET Core托管的应用程序。 服务器端Blazor应用程序将在ASP.NET Core主机应用程序中运行,而不是在浏览器中运行客户端。

In future releases of Blazor, these two projects might be merged into one. But for now, the separation is required due to the differences in the Blazor compilation model.

在Blazor的将来版本中,这两个项目可能会合并为一个。 但是目前,由于Blazor编译模型的差异,需要进行分隔。

搭建应用模型 (Scaffolding the Model to the Application)

We are using Entity Framework core database first approach to create our models. We will create our model class in ServerSideSPA.App project.Navigate to Tools >> NuGet Package Manager >> Package Manager Console. Select “ServerSideSPA.App” from the Default project drop-down. Refer to the image below:

我们正在使用Entity Framework核心数据库优先方法来创建模型。 我们将在ServerSideSPA.App项目中创建模型类。转到工具>> NuGet软件包管理器>>软件包管理器控制台。 从默认的项目下拉列表中选择“发 E RVE rSideSPA.App”。 请参考下图:

First, we will install the package for the database provider that we are targeting which is SQL Server in this case. Hence, run the following command:

首先,我们将为目标数据库安装程序安装软件包,在本例中为SQL Server。 因此,运行以下命令:

Install-Package Microsoft.EntityFrameworkCore.SqlServer
           

Since we are using Entity Framework Tools to create a model from the existing database, we will install the tools package as well. Hence, run the following command:

由于我们使用实体框架工具从现有数据库创建模型,因此我们还将安装工具包。 因此,运行以下命令:

Install-Package Microsoft.EntityFrameworkCore.Tools
           

After you have installed both packages, we will scaffold our model from the database tables using the following command:

安装完两个软件包之后,我们将使用以下命令从数据库表中构建模型:

Scaffold-DbContext "Your connection string here" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables Employee, Cities
           

Do not forget to put your own connection string (inside “ ”). After this command executes successfully, it creates a models folder inside ServerSideSPA.App project. It contains three class files: myTestDBContext.cs, Cities.cs and Employee.cs. Hence, we have successfully scaffolded our Models using EF core database first approach.

不要忘记在“”中放入自己的连接字符串。 成功执行此命令后,它将在ServerSideSPA.App项目中创建一个models文件夹。 它包含三个类文件: myTestDBContext.cs,Cities.cs和Employee.cs 。 因此,我们已经成功使用EF核心数据库优先方法建立了模型。

为应用程序创建数据访问层 (Creating the Data Access Layer for the Application)

Right-click on ServerSideSPA.App project and then select Add >> New Folder and name the folder DataAccess. We will be adding our class to handle database related operations inside this folder only.

右键单击ServerSideSPA.App项目,然后选择添加>>新建文件夹,并将其命名为较旧的数据访问。 我们将添加我们的类以仅处理此文件夹内的数据库相关操作。

Right click on the DataAccess folder and select Add >> Class.

右键单击DataAccess文件夹,然后选择添加>>类。

Name your class EmployeeDataAccessLayer.cs. Open EmployeeDataAccessLayer.cs and put the following code into it:

将您的类命名为EmployeeDataAccessLayer.cs。 打开EmployeeDataAccessLayer.cs并将以下代码放入其中:

using Microsoft.EntityFrameworkCore;
using ServerSideSPA.App.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ServerSideSPA.App.DataAccess
{
    public class EmployeeDataAccessLayer
    {
        myTestDBContext db = new myTestDBContext();

        //To Get all employees details     
        public List<Employee> GetAllEmployees()
        {
            try
            {
                return db.Employee.AsNoTracking().ToList();
            }
            catch
            {
                throw;
            }
        }

        //To Add new employee record       
        public void AddEmployee(Employee employee)
        {
            try
            {
                db.Employee.Add(employee);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //To Update the records of a particluar employee      
        public void UpdateEmployee(Employee employee)
        {
            try
            {
                db.Entry(employee).State = EntityState.Modified;
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        //Get the details of a particular employee      
        public Employee GetEmployeeData(int id)
        {
            try
            {
                var employee = db.Employee.Find(id);
                db.Entry(employee).State = EntityState.Detached;
                return employee;
            }
            catch
            {
                throw;
            }
        }

        //To Delete the record of a particular employee      
        public void DeleteEmployee(int id)
        {
            try
            {
                Employee emp = db.Employee.Find(id);
                db.Employee.Remove(emp);
                db.SaveChanges();
            }
            catch
            {
                throw;
            }
        }

        // To get the list of Cities
        public List<Cities> GetCityData()
        {
            try
            {
                return db.Cities.ToList();
            }
            catch
            {
                throw;
            }
        }
    }
}
           

Here, we have defined the methods to handle database operations:

在这里,我们定义了处理数据库操作的方法:

  • GetAllEmployees will fetch all the employee data from the Employee table.

    GetAllEmployees将从Employee表中获取所有雇员数据。

  • AddEmployee will create a new employee record.

    AddEmployee将创建一个新的员工记录。

  • UpdateEmployee will update the record of an existing employee.

    UpdateEmployee将更新现有员工的记录。

  • GetEmployeeData will fetch the record of the employee corresponding to the employee ID passed to it.

    GetEmployeeData将获取与传递给它的员工ID对应的员工记录。

  • DeleteEmployee will delete the employee record corresponding to the employee id passed to it.

    DeleteEmployee将删除与传递给它的员工ID对应的员工记录。

  • GetCityData will fetch the list of all the cities from Cities table.

    GetCityData将从“城市”表中获取所有城市的列表。

创建服务类 (Creating the Service class)

Right click on the Services folder and select Add >> Class. Give it a name of “EmployeeService.cs” and click Add. This will add the EmployeeService class to the Services folder.

右键单击Services文件夹,然后选择Add >> Class。 给它“EmployeeService.cs”和CLI CK添加的一个名字。 这会将EmployeeS服务类添加到Services文件夹中。

Open EmployeeService.cs and put the following code into it:

打开EmployeeService.cs并将以下代码放入其中:

using ServerSideSPA.App.DataAccess;
using ServerSideSPA.App.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ServerSideSPA.App.Services
{
    public class EmployeeService
    {
        EmployeeDataAccessLayer objemployee = new EmployeeDataAccessLayer();

        public Task<List<Employee>> GetEmployeeList()
        {
            return Task.FromResult(objemployee.GetAllEmployees());
        }

        public void Create(Employee employee)
        {
            objemployee.AddEmployee(employee);
        }
        
        public Task<Employee> Details(int id)
        {
            return Task.FromResult(objemployee.GetEmployeeData(id));
        }
        
        public void Edit(Employee employee)
        {
            objemployee.UpdateEmployee(employee);
        }
        
        public void Delete(int id)
        {
            objemployee.DeleteEmployee(id);
        }
        
        public Task<List<Cities>> GetCities()
        {
            return Task.FromResult(objemployee.GetCityData());
        }
    }
}
           

We will invoke the methods of EmployeeDataAccessLayer class from our service. The service will be injected into our components. The components will call the service methods to access the database.

我们将从服务中调用EmployeeDataAccessLayer类的方法。 该服务将注入到我们的组件中。 这些组件将调用服务方法来访问数据库。

At this point in time, the ServerSideSPA.App project has the following structure:

此时,ServerSideSPA.App项目具有以下结构:

配置服务 (Configuring the Service)

To make the service available to the components, we need to configure it on the server-side app. Open ServerSideSPA.App >> Startup.cs file. Add the following line inside the ConfigureServices method of the Startup class.

为了使该服务可用于组件,我们需要在服务器端应用程序上对其进行配置。 打开ServerSideSPA.App >> Startup.cs文件。 在Startup类的ConfigureSer Vices方法中添加以下行。

services.AddSingleton<EmployeeService>();
           

Refer to the image below:

请参考下图:

Now we will proceed to create our view component.

现在,我们将继续创建视图组件。

创建视图组件 (Creating The View Component)

We will add the Razor page in the ServerSideSPA.App /Pages folder. By default, we have “Counter” and “Fetch Data” pages provided in our application. These default pages will not affect our application. For the sake of this tutorial, delete both of them from the ServerSideSPA.App /Pages folder.

我们将在ServerSideSPA.App / Pages文件夹中添加Razor页面。 默认情况下,我们的应用程序中提供了“计数器”和“获取数据”页面。 这些默认页面不会影响我们的应用程序。 为了本教程的缘故,请从ServerSideSPA.App / Pages文件夹中将它们都删除。

Right-click on ServerSideSPA.App /Pages folder and then select Add >> New Item. An “Add New Item” dialog box will open. Select “ASP.NET Core” from the left panel. Then select “Razor Page” from the templates panel and name it EmployeeData.cshtml. Click Add.

右键单击ServerSideSPA.App / Pages文件夹,然后选择添加>>新建项。 “添加新项”对话框将打开。 从左侧面板中选择“ ASP.NET Core”。 然后从模板面板中选择“ Razor Page”,并将其命名为EmployeeData。 cshtml。 单击添加。

This will add an EmployeeData.cshtml page to the Pages folder. This razor page will have two files, EmployeeData.cshtml and EmployeeData.cshtml.cs.Now, we will add code to these pages.

这会将EmployeeData.cshtml页面添加到Pages文件夹。 该剃刀页面将包含两个文件EmployeeData.cshtml和EmployeeData.cshtml.cs。 现在,我们将代码添加到这些页面。

EmployeeData.cshtml (EmployeeData.cshtml)

Open the EmployeeData.cshtml page and put the following code into it:

打开EmployeeData.cshtml页面,并将以下代码放入其中:

@page "/fetchemployee"
@inherits EmployeeDataModel

<h1>Employee Data</h1>
<p>This component demonstrates CRUD operation on Employee data</p>

<div>
    <div style="float:left">
        <button class="btn btn-primary" onclick="@AddEmp">Add Employee</button>
    </div>
    <div style="float:right; width:40%;">
        <div class="col-sm-6" style="float:left">
            <input class="form-control" type="text" placeholder="Search" bind="@SearchString" />
        </div>
        <div>
            <button type="submit" class="btn btn-default btn-info" onclick="@FilterEmp">Filter</button>
        </div>
    </div>
</div>

@if (empList == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class='table'>
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Gender</th>
                <th>Department</th>
                <th>City</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var emp in empList)
            {
                <tr>
                    <td>@emp.EmployeeId</td>
                    <td>@emp.Name</td>
                    <td>@emp.Gender</td>
                    <td>@emp.Department</td>
                    <td>@emp.City</td>
                    <td>
                        <button class="btn btn-default" onclick="@(async () => await EditEmployee(@emp.EmployeeId))">Edit</button>
                        <button class="btn btn-danger" onclick="@(async () => await DeleteConfirm(@emp.EmployeeId))">Delete</button>
                    </td>
                </tr>
            }
        </tbody>
    </table>

    if (isAdd)
    {
        <div class="modal" tabindex="-1" style="display:block" role="dialog">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h3 class="modal-title">@modalTitle</h3>
                        <button type="button" class="close" onclick="@closeModal">
                            <span aria-hidden="true">X</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <form>
                            <div class="form-group">
                                <label for="Name" class="control-label">Name</label>
                                <input for="Name" class="form-control" bind="@emp.Name" />
                            </div>
                            <div class="form-group">
                                <label asp-for="Gender" class="control-label">Gender</label>
                                <select asp-for="Gender" class="form-control" bind="@emp.Gender">
                                    <option value="">-- Select Gender --</option>
                                    <option value="Male">Male</option>
                                    <option value="Female">Female</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label asp-for="Department" class="control-label">Department</label>
                                <input asp-for="Department" class="form-control" bind="@emp.Department" />
                            </div>
                            <div class="form-group">
                                <label asp-for="City" class="control-label">City</label>
                                <select asp-for="City" class="form-control" bind="@emp.City">
                                    <option value="">-- Select City --</option>
                                    @foreach (var city in cityList)
                                    {
                                        <option value="@city.CityName">@city.CityName</option>
                                    }
                                </select>
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-block btn-info" onclick="@(async () => await SaveEmployee())" data-dismiss="modal">Save</button>
                    </div>
                </div>
            </div>
        </div>
    }

    if (isDelete)
    {
        <div class="modal" tabindex="-1" style="display:block" role="dialog">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h3 class="modal-title">Delete Employee</h3>
                    </div>
                    <div class="modal-body">
                        <h4>Do you want to delete this employee ??</h4>
                        <table class="table">
                            <tr>
                                <td>Name</td>
                                <td>@emp.Name</td>
                            </tr>
                            <tr>
                                <td>Gender</td>
                                <td>@emp.Gender</td>
                            </tr>
                            <tr>
                                <td>Department</td>
                                <td>@emp.Department</td>
                            </tr>
                            <tr>
                                <td>City</td>
                                <td>@emp.City</td>
                            </tr>
                        </table>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-danger" onclick="@(async () => await DeleteEmployee(emp.EmployeeId))" data-dismiss="modal">YES</button>
                        <button class="btn btn-warning" onclick="@closeModal">NO</button>
                    </div>
                </div>
            </div>
        </div>
    }
}
           

Let me explain this code. At the top, we have defined the route for this page as “/fetchemployee”. This means if we append “/fetchemployee” to the root URL of the app, we will be redirected to this page.

让我解释一下这段代码。 在顶部,我们已将此页面的路由定义为“ / fetchemployee”。 这意味着,如果将“ / fetchemployee”附加到应用程序的根URL,我们将被重定向到此页面。

We are also inheriting EmployeeDataModel class which is defined in EmployeeData.cshtml.cs file. This will allow us to use the methods defined in EmployeeDataModel class.

我们还将继承EmployeeData.cshtml.cs文件中定义的EmployeeDataModel类。 这将使我们能够使用EmployeeDataModel类中定义的方法。

After this, we have defined a button to add a new employee record. When clicked, this button will open a modal popup to handle the user inputs.

此后,我们定义了一个添加新员工记录的按钮。 单击时,此按钮将打开一个模式弹出窗口以处理用户输入。

We have also defined a searchbox and a corresponding button to filter the employee records based on employee name. If you enter an employee name and click on the filter button, it will show all matching employee records. If we click on the filter button without entering any value in the search box, it will return all the employee records.

我们还定义了一个搜索框和一个相应的按钮,用于根据员工姓名过滤员工记录。 如果输入员工名称并单击过滤器按钮,它将显示所有匹配的员工记录。 如果单击过滤器按钮但未在搜索框中输入任何值,它将返回所有员工记录。

The employee records returned from the database are stored in the empList variable. If the variable is not null, then we will bind the values to a table to display the employee records in a tabular fashion. Each employee record will also have two action links — Edit to edit the employee record, and Delete to delete the employee record.

从数据库返回的员工记录存储在empList变量中。 如果变量不为null,则我们将这些值绑定到表上以表格形式显示员工记录。 每个员工记录还将具有两个操作链接-“ 编辑”以编辑员工记录,以及“ 删除”以删除员工记录。

To handle the user inputs, we are using a form. We are using a single form for both Add Employee and Edit Employee functionality. The form is defined in a modal popup. The modal popup is displayed on the screen based on the value of the Boolean property isAdd. The value of this Boolean property is set in the code behind (.cshtml.cs) page.

为了处理用户输入,我们使用了一个表格。 我们正在为“添加员工”和“编辑员工”功能使用单一表格。 该表单在模式弹出窗口中定义。 基于布尔属性isAdd的值,模式弹出窗口显示在屏幕上。 在(.cshtml.cs)页面后面的代码中设置此布尔属性的值。

The City dropdown list inside the form is binding to our Cities table in the database with the help of the cityList variable. The cityList will be populated as the application boots up.

表单内的City下拉列表借助cityList变量绑定到数据库中的Cities表。 当应用程序启动时,将填充cityList。

The form will have a Save button which will invoke the SaveEmployee method. This method is defined in the code behind file to Add or update an employee record.

该窗体将具有一个保存按钮,它将调用SaveEmployee方法。 该方法在文件后面的代码中定义,用于添加或更新员工记录。

Similar to Add modal popup, we also have a Delete modal popup. It will be a read-only modal and ask for a confirmation to delete an employee record. Upon clicking “Yes”, it will invoke the DeleteEmployee method to delete the employee record.

与添加模式弹出窗口类似,我们还有一个删除模式弹出窗口。 这将是只读模式,并要求确认以删除员工记录。 单击“是”后,它将调用DeleteEmployee方法以删除员工记录。

EmployeeData.cshtml.cs (EmployeeData.cshtml.cs)

Open EmployeeData.cshtml.cs and put the following code into it.

打开EmployeeData.cshtml.cs并将以下代码放入其中。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor;
using Microsoft.AspNetCore.Blazor.Components;
using Microsoft.AspNetCore.Blazor.Services;
using ServerSideSPA.App.Models;
using ServerSideSPA.App.Services;

namespace ServerSideSPA.App.Pages
{
    public class EmployeeDataModel : BlazorComponent
    {
        [Inject]
        protected EmployeeService employeeService { get; set; }

        protected List<Employee> empList;
        protected List<Cities> cityList = new List<Cities>();
        protected Employee emp = new Employee();
        protected string modalTitle { get; set; }
        protected Boolean isDelete = false;
        protected Boolean isAdd = false;

        protected string SearchString { get; set; }

        protected override async Task OnInitAsync()
        {
            await GetCities();
            await GetEmployee();
        }

        protected async Task GetCities()
        {
            cityList = await employeeService.GetCities();
        }

        protected async Task GetEmployee()
        {
            empList = await employeeService.GetEmployeeList();
        }

        protected async Task FilterEmp()
        {
            await GetEmployee();
            if (SearchString != "")
            {
                empList = empList.Where(x => x.Name.IndexOf(SearchString, StringComparison.OrdinalIgnoreCase) != -1).ToList();
            }
        }

        protected void AddEmp()
        {
            emp = new Employee();
            this.modalTitle = "Add Employee";
            this.isAdd = true;
        }

        protected async Task EditEmployee(int empID)
        {
            emp = await employeeService.Details(empID);
            this.modalTitle = "Edit Employee";
            this.isAdd = true;
        }

        protected async Task SaveEmployee()
        {
            if (emp.EmployeeId != 0)
            {
                await Task.Run(() =>
                {
                    employeeService.Edit(emp);
                });
            }
            else
            {
                await Task.Run(() =>
                {
                    employeeService.Create(emp);
                });
            }
            this.isAdd = false;
            await GetEmployee();
        }

        protected async Task DeleteConfirm(int empID)
        {
            emp = await employeeService.Details(empID);
            this.isDelete = true;
        }

        protected async Task DeleteEmployee(int empID)
        {
            await Task.Run(() =>
            {
                employeeService.Delete(empID);
            });
            this.isDelete = false;
            await GetEmployee();
        }
        protected void closeModal()
        {
            this.isAdd = false;
            this.isDelete = false;
        }
    }
}
           

Let me explain this code. We have defined a class EmployeeDataModel. It will hold all the methods that we will be using in EmployeeData.cshtml page.

让我解释一下这段代码。 我们定义了一个类EmployeeDataModel。 它 将保存我们将在EmployeeData.cshtml页面中使用的所有方法。

We are injecting our EmployeeService to the EmployeeDataModel class so that the client-side methods can invoke our services.

我们正在将EmployeeService注入EmployeeDataModel类,以便客户端方法可以调用我们的服务。

The variables empList and cityList hold the data from the Employee and Cities tables. The variables are getting populated inside the OnInitAsync to make sure that the data is available to us as the page loads.

变量empList和cityList保存Employee和Cities表中的数据。 这些变量将填充到OnInitAsync内部,以确保在页面加载时数据可供我们使用。

We will use the FilterEmp method to filter the employee data based on the employee name property. This property will ignore the text case of the search string. It returns all the records that match either fully or partially with the search string.

我们将使用FilterEmp方法根据员工姓名属性过滤员工数据。 此属性将忽略搜索字符串的文本大小写。 它返回与搜索字符串完全或部分匹配的所有记录。

Clicking the “Add Employee” button will invoke the AddEmp method. It will initialize an empty instance of Employee model and set the value of the isAdd Boolean flag to true. This will open a modal popup with a form, asking the user to enter a new employee record. Similarly, we have defined an EditEmployee method. It fetches the record of the employee based on the employee id for which it is invoked. It will also set the value of isAdd to true to open the modal popup to edit the employee record.

单击“添加员工”按钮将调用AddEmp方法。 它将初始化Employee模型的空实例,并将isAdd布尔标志的值设置为true。 这将打开带有表单的模式弹出窗口,要求用户输入新的员工记录。 同样,我们定义了一个EditEmployee方法。 它根据为其调用的员工ID提取员工的记录。 还将isAdd的值设置为true,以打开模式弹出窗口以编辑员工记录。

The SaveEmployee method will check if it is invoked to add a new employee record or to edit an existing employee record. If the EmployeeId property is set, then it is an “edit” request, and we will invoke the Edit method of our service. If EmployeeId is not set, then it is a “create” request, and we will invoke the Create method of our service. We will then fetch the updated employee record by calling the GetEmployee method and will also set the value of isAdd to false, thus closing the modal popup.

SaveEmployee方法将检查是否调用了该方法以添加新的员工记录或编辑现有的员工记录。 如果设置了EmployeeId属性,则它是一个“编辑”请求,我们将调用服务的Edit方法。 如果未设置EmployeeId,则它是一个“创建”请求,我们将调用服务的Create方法。 然后,我们将通过调用getEmployee的方法取得更新的员工记录,也将设置isAdd的假值,从而关闭模式弹出。

The DeleteConfirm method is invoked by clicking the Delete button corresponding to an employee record. It will set the value of the isDelete Boolean flag to true. This will display a Delete confirmation modal popup. Upon clicking YES inside this popup, DeleteEmployee method is invoked. This will delete the employee record and set the isDelete Boolean flag to false to close the modal popup.

通过单击与员工记录对应的Delete按钮来调用DeleteConfirm方法。 它将isDelete布尔值标志的值设置为true。 这将显示一个删除确认模式弹出窗口。 在此弹出窗口中单击“是”后,将调用DeleteEmployee方法。 这将删除员工记录,并将isDelete布尔值标志设置为false以关闭模式弹出窗口。

将链接添加到导航菜单 (Adding Link to Navigation menu)

The last step is to add the link to our “EmployeeData” page in the navigation menu. Open ServerSideSPA.App/Shared/NavMenu.cshtml page and put the following code into it:

最后一步是将链接添加到导航菜单中的“ EmployeeData”页面。 打开ServerSideSPA.App/Shared/NavMenu.cshtml页面,并将以下代码放入其中:

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >ServerSideSPA</a>
    <button class="navbar-toggler" [email protected]>
        <span class="navbar-toggler-icon"></span>
    </button>
</div>

<div class=@(collapseNavMenu ? "collapse" : null) [email protected]>
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  Match=NavLinkMatch.All>
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="fetchemployee" target="_blank" rel="external nofollow" >
                <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch employee
            </NavLink>
        </li>
    </ul>
</div>

@functions {
bool collapseNavMenu = true;

void ToggleNavMenu()
{
    collapseNavMenu = !collapseNavMenu;
}
}
           

This completes our Single Page Application using server-side Blazor.

这将使用服务器端Blazor完成我们的单页应用程序。

执行演示 (Execution Demo)

Press F5 to launch the application.

按F5启动应用程序。

A web page will open as shown in the image below. The navigation menu on the left is showing a navigation link for the Employee data page.

如下图所示,将打开一个网页。 左侧的导航菜单显示Employee数据页面的导航链接。

Clicking on the “Employee data” link will redirect to the EmployeeData view. Here you can see all the employee data on the page. Notice the URL has “/fetchemployee” appended to it.

单击“雇员数据”链接将重定向到EmployeeData视图。 在这里,您可以在页面上看到所有员工数据。 请注意,URL附加了“ / fetchemployee”。

Click on the Add Employee button to open the “Add Employee” modal popup. Enter the data in all the fields and click on Save to create a new employee record.

单击添加员工按钮以打开“添加员工”模式弹出窗口。 在所有字段中输入数据,然后单击保存以创建新的员工记录。

This will create a new employee record and display the data in the view table. Add a few more records, and the view will be similar to the one shown below:

这将创建一个新的员工记录,并在视图表中显示数据。 再添加几条记录,该视图将类似于以下所示:

Clicking on the Edit button will open the modal popup for editing the employee record. Edit the input fields and click on save to update the employee record.

单击“编辑”按钮将打开用于编辑员工记录的模式弹出窗口。 编辑输入字段,然后单击保存以更新员工记录。

To filter the employee records, enter the employee name in the search box and click on the Filter button. The search text is case independent. The filter operation will return all the employee records matching the name entered in the search field. Refer to the image below:

要过滤员工记录,请在搜索框中输入员工名称,然后单击“过滤器”按钮。 搜索文本不区分大小写。 筛选操作将返回与在搜索字段中输入的名称匹配的所有员工记录。 请参考下图:

If you click on the Delete button corresponding to the employee record, it will open a delete confirmation popup asking for a confirmation to delete the employee record.

如果单击与员工记录对应的“删除”按钮,它将打开一个删除确认弹出窗口,要求确认删除员工记录。

Clicking on YES will delete the employee data and show the updated list of employees by refreshing the view table.

单击“是”将删除员工数据,并通过刷新视图表来显示更新的员工列表。

结论 (Conclusion)

We have created a server-side Blazor application using Entity Framework Core DB first approach with the help of Visual Studio 2017 and SQL Server 2017. We used a modal popup to handle user inputs via a form. We also implemented the search functionality on the employee records.

我们已在Visual Studio 2017和SQL Server 2017的帮助下,使用Entity Framework Core DB first方法创建了服务器端Blazor应用程序。我们使用模式弹出窗口通过表单处理用户输入。 我们还对员工记录实施了搜索功能。

Please get the source code from GitHub and play around to get a better understanding.

请从GitHub获取源代码并进行尝试以获得更好的理解。

Get my book Blazor Quick Start Guide to learn more about Blazor.

获取我的书《 Blazor快速入门指南》,以了解有关Blazor的更多信息。

You can check out my other articles on Blazor here.

您可以在此处查看有关Blazor的其他文章。

Preparing for interviews? Read my article on C# Coding Questions For Technical Interviews

准备面试吗? 阅读有关技术面试的C#编码问题的文章

也可以看看 (See Also)

  • ASP.NET Core — Getting Started With Blazor

    ASP.NET Core — Blazor入门

  • ASP.NET Core — CRUD Using Blazor And Entity Framework Core

    ASP.NET Core —使用Blazor和Entity Framework Core的CRUD

  • Cascading DropDownList In Blazor Using EF Core

    使用EF Core在Blazor中级联DropDownList

  • Creating an SPA Using Razor Pages With Blazor

    使用带有Blazor的Razor页面创建SPA

  • Deploying a Blazor Application on IIS

    在IIS上部署Blazor应用程序

Originally published at https://ankitsharmablogs.com/

最初发布在https://ankitsharmablogs.com/

翻译自: https://www.freecodecamp.org/news/how-to-build-a-single-page-application-using-server-side-blazor-1e37875e8ed/

jsp 构建单页应用