Angular/.NET Core Web API 基础教程

在本教程中,将介绍如何使用Angular.NET Core创建一个基础的Web API应用程序,该应用程序将具备添加、编辑和删除客户信息的基本功能。将使用以下框架:

  • Angular Material
  • Bootstrap
  • .NET Core
  • Entity Framework

在计算机上运行

请确保已经安装了以下软件:

  • Node v12.19.*
  • Angular CLI 10.2.*
  • .NET Core3.1

在下载的代码中,打开文件:

api/Api/appsettings.Development.json

并将其中的“Data Source”更改为SQL Server地址:

"AngApiStarterConn": "Data Source=服务器名称;Initial Catalog=AngApiStarter;Integrated Security=True;"

构建API解决方案

构建API解决方案以确保NuGet包已安装,并且解决方案构建成功。在运行Entity Framework数据库更新之前,需要先成功构建解决方案。

打开命令提示符,导航到:

api/Data

然后运行以下命令,该命令将使用应用程序所需的结构更新SQL Server:

dotnet ef database update -s ..\Api\Api.csproj

现在应该在SQL Server中拥有一个名为AngApiStarter的数据库,其中包含一个名为Customers的表。可以使用以下SQL将一个示例客户插入到表中:

insert into customers(firstName, lastName) values('John', 'Smith');

通过运行API项目并访问以下URL,检查API是否可以从数据库获取数据,该URL应该返回数据库中的客户列表:

https://localhost:44381/api/customer

获取Angular所需库

导航到命令提示符中的ui文件夹,然后运行以下命令以获取运行Angular所需的库:

npm update

如果遇到模块未找到的错误,则可以运行以下命令以获取所需的模块:

npm install

启动Angular

通过运行以下命令启动Angular,这将启动服务器并在浏览器中打开应用程序:

ng serve --open

应用程序构建方式

从API的数据层开始,创建了一个Customer类模型:

public class Customer { [Required] public int CustomerId { get; set; } [Required, StringLength(80)] public string FirstName { get; set; } [Required, StringLength(80)] public string LastName { get; set; } }

然后创建了Customer的DbContext类,使用Customer类作为DbSet,它最终将成为数据库中的一个表:

public class AngApiStarterDbContext : DbContext { public DbSet Customer { get; set; } public AngApiStarterDbContext(DbContextOptions<AngApiStarterDbContext> options) : base(options) { } }

定义数据库连接字符串

在API项目中,定义了数据库连接字符串,并在Startup.cs的ConfigureServices方法中添加了以下代码:

services.AddDbContextPool<AngApiStarterDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("AngApiStarterConn")));

构建解决方案,然后使用命令提示符导航到Data项目文件夹,并运行以下命令以创建数据库迁移的类:

dotnet ef migrations add initialCreate -s ..\Api\Api.csproj

创建类后,运行以下命令在SQL Server中创建数据库和表:

dotnet ef database update -s ..\Api\Api.csproj

接口和实现

Data项目中包含了接口及其使用Entity Framework的实现:

public interface ICustomerData { Task<IEnumerable<Customer>> Get(); Task<Customer> GetCustomerById(int id); Task<Customer> Update(Customer customer); Task<Customer> Add(Customer customer); Task<int> Delete(int customerId); } public class SqlCustomerData : ICustomerData { public AngApiStarterDbContext DbContext { get; } public SqlCustomerData(AngApiStarterDbContext dbContext) { DbContext = dbContext; } ... }

API项目中的接口实现

在API项目中,在ConfigureServices方法中定义了接口的实现类:

services.AddScoped<ICustomerData, SqlCustomerData>();

控制器也通过依赖注入使用接口:

public class CustomerController : ControllerBase { public ICustomerData CustomerData { get; } public CustomerController(ICustomerData customerData) { CustomerData = customerData; } ... }

跨源资源共享(CORS)

由于API和UI将从不同的网站运行,因此需要允许UI网站通过CORS访问API。在API的appsettings.Development.json中,它有UI的url:

"CorsUrl": "http://localhost:4200"

然后在Startup.cs文件中指定CORS策略:

private readonly string corsPolicy = "defaultPolicy"; public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddPolicy(corsPolicy, builder => { builder.WithOrigins(Configuration["CorsUrl"]).AllowAnyMethod().AllowAnyHeader().AllowCredentials(); }); }); ... }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseCors(corsPolicy); ... }

使用Angular的入门项目,在项目中定义了Angular Materials组件:

import { MaterialModule } from './common/material.module';

然后在app.module.ts中只包含Material模块:

import { MaterialModule } from './common/material.module';

API url的位置在environments/environments.ts文件中定义:

export const environment = { production: false, apiCustomer: 'https://localhost:44381/api/customer' };

模型在model/ICustomer.ts文件中定义,与API的模型签名相同:

export interface ICustomer { customerId: number, firstName: string, lastName: string }

与API交互的支持在service/customer.service.ts文件中。它使用BehaviorSubject将客户列表作为Observable(可以将其视为数据流)。当Observable变化时,所有的观察者(可以将其视为监听器或订阅者)都会收到变化通知,并相应地做出反应。在CustomerService类中,当Observable需要通知所有观察者时,调用customerList.next方法:

private customerList = new BehaviorSubject<ICustomer[] | null>(null); customerList$ = this.customerList.asObservable(); ... //get the list of customers get(){ this.http.get<ICustomer[]>(this.url).pipe( ).subscribe(result => { if (result) //notify the Observers of the change this.customerList.next(result) }); }

Customer组件,显示可以管理的客户列表,通过在ngOnInit方法中订阅CustomerService类来监听变化:

export class CustomerComponent implements OnInit { ... ngOnInit(){ this.custService.customerList$.subscribe(data => this.customerList = data); } }

当用户点击添加或编辑客户按钮时,它将打开一个对话框,可以将数据传递给对话框,并定义对话框关闭时采取的操作。下面显示了在添加新客户时传递给对话框的数据,并在对话框关闭时调用CustomerService:

openAddDialog(){ let dialogRef = this.custDialog.open(CustomerDialog, { width: '300px', data: { action: 'add', customer: { customerId: 0, firstName: '', lastName: ''} } }); dialogRef.afterClosed().subscribe(result => { //add the customer if (result) this.custService.add(result) }); }

对于编辑客户,需要将客户数据的副本传递给对话框,而不是实际的客户数据,以便如果用户决定取消,客户值不会被更改:

customer: {...customer} //shallow copy the customer using spread operator

对话框组件在app/customer/dialog/customer-dialog.component.ts中定义,它使用MAT_DIALOG_DATA从Material的Dialog组件接受调用者的数据:

export class CustomerDialog { ... constructor(public dialogRef: MatDialogRef<CustomerDialog>, @Inject(MAT_DIALOG_DATA) public data: any) { this.action = data.action; this.customer = data.customer; } }

最后,使用npm添加Bootstrap库,并将对Bootstrap样式表的引用添加到index.html:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap...> <div class="d-flex flex-row justify-content-center"> <div class="d-flex flex-column">
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485