65.9K
CodeProject 正在变化。 阅读更多。
Home

关于 Blazor 应用以及如何使用 VS 2019、.NET Core 3、Web API 创建 ASP.NET Core Blazor CRUD 应用的必知信息

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (27投票s)

2019 年 12 月 12 日

CPOL

10分钟阅读

viewsIcon

68025

downloadIcon

2133

如何使用 Visual Studio 2019、.NET Core 3、Entity Framework 和 Web API 为 ASP.NET Core Blazor 创建一个简单的 CRUD 应用程序

引言

在本文中,我们将看到如何使用 Visual Studio 2019、.NET Core 3、Entity Framework 和 Web API 为 ASP.NET Core Blazor 创建一个简单的 CRUD 应用程序。Blazor 是 Microsoft 推出的一个新框架。

Blazor

Blazor 有两种应用程序开发方式,一种是 Blazor 客户端应用(目前处于预览阶段),另一种是 Blazor 服务器应用。Blazor 客户端应用运行在 WebAssembly 中,Blazor 服务器应用通过 SignalR 运行。Blazor 应用可以使用 C#、Razor 和 HTML 创建,而不是 JavaScript。Blazor WebAssembly 适用于所有现代 Web 浏览器,包括移动浏览器。Blazor 的主要优势在于 C# 代码文件和 Razor 文件被编译成 .NET 程序集。Blazor 具有可重用的组件,Blazor 组件可以是页面、对话框或输入表单,Blazor 也用于创建单页应用程序。Blazor 用于创建两种应用程序,一种是 Blazor 客户端应用,另一种是 Blazor 服务器端应用。在这里,我们将看到更多关于   

Blazor 客户端应用

  • Blazor 客户端仍处于预览阶段。 
  • Blazor 客户端使用 Web Assembly。
  • 在 Blazor 客户端中,所有 .NET DLL 都将下载到浏览器。下载大小可能更大,并且由于所有下载都发生在客户端浏览器中,加载可能会有一些时间延迟。
  • Blazor 客户端应用程序不需要服务器端依赖。
  • 所有类似的 JavaScript 编码都可以在 Blazor 客户端应用中完成,并且实际上不需要使用 JavaScript Interop。
  • 它可以部署为静态站点,这意味着它也支持离线。
  • 调试比 Blazor 服务器端更复杂。
  • 在客户端,数据库连接泄露以及所有应用程序代码都将在客户端,并且安全级别不是很好。

Blazor 服务器应用

  • 所有组件处理都将在服务器中进行。
  • Blazor 服务器使用 SignalR 连接从 Web 服务器连接到浏览器。
  • 在客户端,不会发生数据库连接泄露,因为所有操作都将在服务器中进行。
  • 所有表单连接都将在服务器端进行,并且不会下载任何 DLL 到客户端,因为所有 DLL 都将在 Web 服务器中。
  • 下载大小小,加载时间比 Blazor 客户端应用更快。
  • 我们可以在 Blazor 服务器端使用 .NET Core。
  • Blazor 服务器端调试非常棒。
  • 在任何 Web 浏览器中运行,因为不需要 WebAssemble。
  • 每个浏览器会话都通过 SignalR 连接打开。

背景

必备组件

Using the Code

步骤 1 - 创建数据库和表

我们将使用 SQL Server 数据库来支持我们的 WEB API 和 EF。首先,我们创建一个名为 CustDB 的数据库和一个名为 CustDB 的表。这是用于创建数据库表和在我们表中插入示例记录的 SQL 脚本。在您的本地 SQL Server 中运行以下查询,以创建将在我们的项目中使用的数据库和表。

USE MASTER       
GO       
       
-- 1) Check for the Database Exists .If the database is exist then drop and create new DB       
IF EXISTS (SELECT [name] FROM sys.databases WHERE [name] = 'CustDB' )       
DROP DATABASE CustDB       
GO       
       
CREATE DATABASE CustDB       
GO       
       
USE CustDB       
GO       
       
-- 1) //////////// Customer Masters    

IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'CustomerMaster' )       
DROP TABLE CustomerMaster       
GO       
       
CREATE TABLE [dbo].[CustomerMaster](       
        [CustCd] [varchar](20) NOT NULL ,         
        [CustName] [varchar](100) NOT NULL,          
        [Email]  [nvarchar](100) NOT NULL,        
        [PhoneNo] [varchar](100) NOT NULL,           
        [InsertBy] [varchar](100) NOT NULL,   
        PRIMARY KEY (CustCd)  
)       
       
-- insert sample data to Student Master table       
INSERT INTO [CustomerMaster]   (CustCd,CustName,Email,PhoneNo,InsertBy)       
     VALUES ('C001','ACompany','acompany@gmail.com','01000007860','Shanun')       
       
INSERT INTO [CustomerMaster]   (CustCd,CustName,Email,PhoneNo,InsertBy)       
     VALUES ('C002','BCompany','bcompany@gmail.com','0100000001','Afraz')  

INSERT INTO [CustomerMaster]   (CustCd,CustName,Email,PhoneNo,InsertBy)       
     VALUES ('C003','CCompany','ccompany@gmail.com','01000000002','Afreen')  

INSERT INTO [CustomerMaster]   (CustCd,CustName,Email,PhoneNo,InsertBy)       
     VALUES ('C004','DCompany','dcompany@gmail.com','01000001004','Asha')  
            
     select * from CustomerMaster 

步骤 2 - 创建 ASP.NET Core Blazor 服务器应用程序

安装完上面列出的所有先决条件后,点击桌面上的 开始 >> 程序 >> Visual Studio 2019 >> Visual Studio 2019。点击 新建 >> 项目

选择 Blazor 应用 并点击 下一步 按钮。

选择您的项目文件夹并输入您的项目名称,然后点击 创建 按钮。

选择 Blazor 服务器应用

创建 ASP.NET Core Blazor 服务器应用程序后,等待几秒钟。您将在解决方案资源管理器中看到以下结构

Data 文件夹中,我们可以添加所有的模型、DBContext 类、服务和控制器,我们将在本文中看到。

Pages 文件夹中,我们可以添加所有组件文件。所有组件文件都应该以 .razor 扩展名作为文件名。

Shared 文件夹中,我们可以添加所有左侧菜单的 NavMenu.razor 文件,并从 MainLayout.razor 文件更改主要内容。

_Imports.razor 文件中,我们可以看到所有导入集都已添加,以便在所有组件页面中使用。

App.razor 文件中,我们将添加在浏览器中运行应用程序时默认显示的主组件。Appsertings.json 可用于添加连接字符串。

Startup.cs 文件是一个重要的文件,我们在这里添加所有端点示例,例如控制器端点、HTTP 客户端、添加服务和 dbcontext,以便在启动 Configuration 方法中使用。

运行以测试应用程序

当我们运行应用程序时,我们可以看到左侧有导航,右侧包含数据。我们可以看到默认的示例页面和菜单将显示在我们的 Blazor 网站中。我们可以使用这些页面,也可以删除它们并开始创建我们自己的页面。

在组件中调试

Blazor 的巨大优势在于我们可以在 Razor 中使用 C# 代码,并在代码部分设置断点,在浏览器中,我们可以调试并检查我们的所有业务逻辑是否正常工作,并使用断点轻松追踪任何类型的错误。

为此,我们使用现有的 Counter 组件页面。

这是我们 Counter 页面的实际代码,在 Counter 中我们可以看到有一个按钮,点击按钮会调用方法来执行增量操作。

我们再添加一个按钮,并在按钮点击事件中调用该方法并将名称绑定到我们的组件页面中。

在 HTML 设计部分,我们添加以下代码

<h1>My Blozor Code part</h1>
    My Name is : @myName   <br />
 <button @onclick="ClickMe">Click Me</button>

注意:所有 C# 代码部分和函数都可以写在 @code {} 部分下。
我们添加方法 ClickMe 并声明属性以将名称绑定到 @Code 部分中。

[Parameter]
public string myName { get; set; }
private void ClickMe()
    {
        myName="Shanu";
    }

完整的 Counter 组件页面代码将如下所示

现在让我们在 ClickMe 方法中添加断点

运行程序并打开计数器页面。

我们可以看到,当我们点击 Click Me 按钮时,我们可以调试并检查我们放置的断点中的值。

现在让我们看看如何使用 EF 和 Web API 在 Blazor 中执行 CRUD 操作。

步骤 3 - 使用 Entity Framework

要在我们的 Blazor 应用程序中使用 Entity Framework,我们需要安装以下包

安装包

  • Microsoft.EntityFrameworkCore.SqlServer - 用于使用 EF 和 SQL Server
  • Microsoft.EntityFrameworkCore.Tools - 用于使用 EF 和 SQL Server
  • Microsoft.AspNetCore.Blazor.HTTTPClient - 用于从我们的 Blazor 组件与 WEB API 进行通信

首先,我们将添加 Microsoft.EntityFrameworkCore.SqlServer。为此,右键单击项目并单击 管理 NuGet 包

搜索所有三个包并安装所有需要的包,如下图所示。

添加数据库连接字符串

打开 appsetting 文件并添加连接字符串,如下图所示

"ConnectionStrings": {
    "DefaultConnection": "Server= DBServerName;Database=CustDB;
     user id= SQLID;-password=SQLPWD;Trusted_Connection=True;MultipleActiveResultSets=true"
},

创建模型类

接下来,我们需要创建 Model 类,该类与我们的 SQL 表同名,并且还定义与我们的 SQL 字段名相似的属性字段,如下所示。

右键单击 Data 文件夹并创建一个名为 “CustomerMaster.cs” 的新类文件

在该类中,我们添加了与我们的表列同名的属性字段,如下面的代码所示

      [Key]
        public string CustCd { get; set; }
        public string CustName { get; set; }
        public string Email { get; set; }
        public string PhoneNo { get; set; }
       public string InsertBy { get; set; }  

创建 dbContext 类

接下来,我们需要创建 dbContext 类。右键单击 Data 文件夹并创建一个名为 “SqlDbContext.cs” 的新类文件

我们将以下代码添加到 DbContext 类中,以便添加 SQLContext 并为我们的 CustomerMaster 模型添加 DBset

  public class SqlDbContext:DbContext
    {
        public SqlDbContext(DbContextOptions<SqlDbContext> options)
           : base(options)
        {
        } 
        public DbSet<BlazorCrudA1.Data.CustomerMaster> CustomerMaster { get; set; }
    }

在启动时添加 DbContext

DbContext 添加到 Startup.cs 文件中的 ConfigureServices 方法中,如下面的代码所示,我们还提供了用于连接 SQLServer 和 DB 的连接字符串。

services.AddDbContext<SqlDbContext>(options => 
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

请注意,在 ConfigureServices 方法中,我们还可以看到已添加了 weatherforecast 服务。如果创建新服务,则需要将服务添加为 ConfigureServices 方法中的以下代码。

  services.AddSingleton<WeatherForecastService>();

为 CRUD 操作创建 Web API

要创建我们的 WEB API 控制器,右键单击 Controllers 文件夹。点击 添加新控制器

在这里,我们将使用 Scaffold 方法来创建我们的 WEB API。我们选择带有操作的 API 控制器,使用 Entity Framework,然后点击 添加 按钮。

选择我们的 模型类DBContext 类,然后点击 添加 按钮。

我们的 WEB API,包含用于执行 CRUD 操作的 Get/Post/PutDelete 方法将自动创建,由于我们已对所有操作和方法使用了 Scaffold 方法并添加了代码,因此现在无需在 Web API 中编写任何代码。

为了测试 Get 方法,我们可以运行我们的项目并复制 GET 方法的 API 路径。在这里,我们可以看到获取 /api/CustomerMasters/ 的 API 路径。

运行程序并粘贴 API 路径以测试我们的输出。

如果您看到此错误,这意味着我们需要在 Startup.cs 文件的 Configure 方法中添加控制器的端点。

Startup.cs 文件的 Configure 方法中添加以下代码。

endpoints.MapControllers();

我们在 Configure 方法中将以下代码添加到 UseEndpoints 内部。

app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });

现在再次运行并检查 /api/CustomerMasters/ 以查看数据库中的 Json 数据。

现在我们将把所有这些 WEB API Json 结果绑定到组件中。

处理客户端项目

首先,我们需要添加 Razor 组件页面。

添加 Razor 组件

要添加 Razor 组件页面,右键单击客户端项目中的 Pages 文件夹。点击 添加 >> 新项 >> 选择 Razor 组件 >> 输入您的组件名称。这里,我们将其命名为 Customerentry.razor

请注意,所有组件文件都需要具有 .razor 扩展名。

在 Razor 组件页面中,我们有三个代码部分:第一部分是导入部分,我们导入所有引用和模型以在组件中使用;HTML 设计和数据绑定部分;最后,我们有函数部分,用于调用所有 Web API 以绑定到我们的 HTML 页面,并执行客户端业务逻辑以显示在组件页面中。

导入部分

首先,我们在 Razor 视图页面中导入所有需要的支持文件和引用。在这里,我们首先导入了要在视图中使用的 Model 类,还导入了 HTTPClient 以调用 Web API 来执行 CRUD 操作。

@page "/customerentry"
@using BlazorCrudA1.Data
@using System.Net.Http
@inject HttpClient Http 
@using Microsoft.Extensions.Logging

为服务器端 Blazor 注册 HTTPClient

为了在 Blazor 服务器端使用 HTTPClient,我们需要在 Startup.csConfigureServices 方法中添加以下代码。

services.AddResponseCompression(opts =>
            {
                opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                    new[] { "application/octet-stream" });
            });

            // Server Side Blazor doesn't register HttpClient by default
            if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
            {
                // Setup HttpClient for server side in a client side compatible fashion
                services.AddScoped<HttpClient>(s =>
                {
                    // Creating the URI helper needs to wait until the 
                    // JS Runtime is initialized, so defer it.      
                    var uriHelper = s.GetRequiredService<NavigationManager>();
                    return new HttpClient
                    {
                        BaseAddress = new Uri(uriHelper.BaseUri)
                    };
                });
            }

HTML 设计和数据绑定部分

接下来,我们设计我们的 Customer Master details 页面,以显示数据库中的 Customer 详细信息,并创建了一个表单来插入和更新 Customer details。我们还有 Delete 按钮,用于从数据库中删除 Customer 记录。

在 Blazor 中进行绑定时,我们使用 @bind="@custObj.CustCd",并通过 @onclick="@AddNewCustomer" 调用方法。

<h1> ASP.NET Core BLAZOR CRUD demo for Customers</h1>
<hr />
<table width="100%" style="background:#05163D;color:honeydew">
    <tr>
        <td width="20"> </td>
        <td>
            <h2> Add New Customer Details</h2>
        </td>
        <td> </td>
        <td align="right">
            <button class="btn btn-info" @onclick="@AddNewCustomer">Add New Customer</button>
        </td>
        <td width="10"> </td>
    </tr>
    <tr>
        <td colspan="2"></td>
    </tr>
</table>
<hr />
@if (showAddrow == true)
{
    <form>
        <table class="form-group">
            <tr>
                <td>
                    <label for="Name" 
                    class="control-label">Customer Code</label>
                </td>
                <td>
                    <input type="text" 
                    class="form-control" @bind="@custObj.CustCd" />
                </td>
                <td width="20"> </td>
                <td>
                    <label for="Name" 
                    class="control-label">Customer Name</label>
                </td>
                <td>
                    <input type="text" 
                    class="form-control" @bind="@custObj.CustName" />
                </td>
            </tr>
            <tr>
                <td>
                    <label for="Email" class="control-label">Email</label>
                </td>
                <td>
                    <input type="text" 
                    class="form-control" @bind="@custObj.Email" />
                </td>
                <td width="20"> </td>
                <td>
                    <label for="Name" 
                    class="control-label">Phone</label>
                </td>
                <td>
                    <input type="text" 
                    class="form-control" @bind="@custObj.PhoneNo" />
                </td>
            </tr>
            <tr>
                <td>
                    <label for="Name" 
                    class="control-label">Insert By</label>
                </td>
                <td>
                    <input type="text" 
                    class="form-control" @bind="@custObj.InsertBy" />
                </td>
                <td width="20"> </td>
                <td>
                </td>
                <td>
                    <button type="submit" 
                    class="btn btn-success" 
                     @onclick="@AddCustomer" 
                     style="width:220px;">Save</button>
                </td>
            </tr>
        </table>
    </form>
}
<table width="100%" style="background:#0A2464;color:honeydew">
    <tr>
        <td width="20"> </td>
        <td>
            <h2>Customer List</h2>
        </td>

    </tr>
    <tr>
        <td colspan="2"></td>
    </tr>
</table> 

@if (custs == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Customer Code</th>
                <th>Customerr Name</th>
                <th>Email</th>
                <th>Phone</th>
                <th>Inserted By</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var cust in custs)
            {
                <tr>
                    <td>@cust.CustCd</td>
                    <td>@cust.CustName</td>
                    <td>@cust.Email</td>
                    <td>@cust.PhoneNo</td>
                    <td>@cust.InsertBy</td>
                    <td><button class="btn btn-primary" 
                    @onclick="@(async () => 
                    await EditCustomer(cust.CustCd))" 
                    style="width:110px;">Edit</button></td>

                    <td><button class="btn btn-danger" 
                    @onclick="@(async () => 
                    await DeleteCustomer(cust.CustCd))">
                    Delete</button></td>
                </tr>
            }
        </tbody>
    </table>
}

函数部分

函数部分用于调用所有 Web API 以绑定到我们的 HTML 页面,并执行客户端业务逻辑以显示在组件页面中。在此函数中,我们为 AddEditDelete 学生详细信息创建了单独的函数,并调用 Web API 的 GetPostPutDelete 方法来执行 CRUD 操作,并在 HTML 中调用所有函数并绑定结果。

@code {

    private CustomerMaster[] custs;

    CustomerMaster custObj = new CustomerMaster();

    string ids = "0";
    bool showAddrow = false;

    bool loadFailed;

    protected override async Task OnInitializedAsync()
    {
        ids = "0";
        custs = await Http.GetJsonAsync<CustomerMaster[]>
        ("/api/CustomerMasters/");
    }

    void AddNewCustomer()
    {
        ids = "0";
        showAddrow = true;
        custObj = new CustomerMaster();
    }
    // Add New Customer Details Method
    protected async Task AddCustomer()
    {
        if (ids == "0")

        {
            await Http.SendJsonAsync
            (HttpMethod.Post, "/api/CustomerMasters/", custObj);
            custs = await Http.GetJsonAsync<CustomerMaster[]>
            ("/api/CustomerMasters/");
        }
        else
        {
            await Http.SendJsonAsync(HttpMethod.Put, "/api/CustomerMasters/" + 
                                     custObj.CustCd, custObj);
            custs = await Http.GetJsonAsync<CustomerMaster[]>
                    ("/api/CustomerMasters/");
        }

        showAddrow = false;
    }
    // Edit Method
    protected async Task EditCustomer(string CustomerID)
    {
        showAddrow = true;

        ids = "1";
        //try
        //{
        loadFailed = false;
        ids = CustomerID.ToString();
        custObj = await Http.GetJsonAsync<CustomerMaster>
                  ("/api/CustomerMasters/" + CustomerID);

        string s = custObj.CustCd;

        showAddrow = true;

        //    }
        //catch (Exception ex)
        //{
        //    loadFailed = true;
        //    Logger.LogWarning(ex, "Failed to load product {ProductId}", CustomerID);
        //}
    }
    // Delte Method
    protected async Task DeleteCustomer(string CustomerID)
    {
        showAddrow = false;

        ids = CustomerID.ToString();
        await Http.DeleteAsync("/api/CustomerMasters/" + CustomerID);

        custs = await Http.GetJsonAsync<CustomerMaster[]>("/api/CustomerMasters/");
    }
}

导航菜单

现在我们需要将这个新添加的 CustomerEntry Razor 组件添加到我们的左侧导航。为此,打开 Shared 文件夹并打开 NavMenu.cshtml 页面并添加菜单。

<li class="nav-item px-3">
            <NavLink class="nav-link" 
            href="CustomerEntry">
                <span class="oi oi-list-rich" 
                aria-hidden="true"></span> Customer Master
            </NavLink>
        </li>

构建并运行应用程序

关注点

请注意,在创建 DBContext 并设置连接字符串时,不要忘记添加您的 SQL 连接字符串。在这里,我们已经在 SQL Server 中创建了表并与 Web API 一起使用。您也可以通过服务和 Code First 方法来完成。希望大家喜欢这篇文章。在下一篇文章中,我们将看到更多使用 Blazor 的示例。使用 Blazor 真的很酷很棒。

历史

  • 2019 年 12 月 12 日:初始版本
© . All rights reserved.