了解最新技术文章
在使用 ASP.NET Core 构建基于角色的 Web API 时,代码优先方法可能是一种强大且高效的方法。使用它,我们可以在代码中定义数据模型和关系,然后自动生成相应的数据库模式。这会导致什么?毫无疑问,更快的开发周期和更大的灵活性。怎么会?因为可以快速轻松地更改数据模型,而无需直接修改数据库架构。您可以在 swagger.io 上阅读有关“设计优先”和“代码优先”方法的更多信息。
在本教程中,我们将介绍使用 ASP.NET Core 6 创建基于角色的 Web API 的步骤。我们将使用 Swagger UI 来可视化我们的端点并与作为数据库的 MS SQL Server 进行交互。该应用程序将包括身份验证模块和事件模块。登录用户将能够查看与其帐户关联的事件,而具有管理员角色的用户可以创建、更新和删除事件。
你将学到的东西:
项目设置
如何建立API数据库
配置自动映射器
快速身份验证设置
开始使用 Swagger
注册端点
登录功能
为事件添加 CRUD
如何添加基于角色的授权
创建 DbSeeder
添加 CORS
让我们开始吧!
首先,我们需要建立我们的项目。为此,请打开 Visual Studio,创建一个新项目,然后选择 ASP.NET Core Web API。
选择应用程序的名称,然后单击“下一步”。
初始化应用程序后,我们需要配置数据库。我们将使用EntityFrameworkCore作为ORM,因此它将帮助我们管理数据库。因此,我们应该安装一些软件包。
成功安装软件包后要做的下一件事是创建DbContext。创建DataContext.cs文件并继承DBContext类。在这里我们将定义我们的表。
全屏12345678公共 类 DataContext : DbContext{ 公共 DataContext (DbContextOptions 选项): 基(选项) { } //定义我们的表}
然后我们应该打开Program.cs文件并添加dbContext。我们应该指定来自 appsettings.json 文件的dbProvider和连接字符串。dbProvider可以是SqlServer、MySql或InMemory。
全屏123456789101112// 添加数据库上下文var dbProvider = 生成器. 配置。GetConnectionString ( "提供者" ) ;建设者。服务。AddDbContext <DataContext> (选项= > _ { if ( dbProvider == " SqlServer " ) { 选项。UseSqlServer ( builder.Configuration.GetConnectionString ( " SqlServerConnectionString " ) ) ; _ _ _ } }) ;
确保您已在appsettings.json文件中添加ConnectionString和Provider,如下所示:
全屏123456……“连接字符串”:{ “提供商”:“SqlServer”, "SqlServerConnectionString": "数据源=(localdb)\\MSSQLLocalDB;数据库=HRApplication2;集成安全性=True;连接超时=30;"},……
配置 DbContext后,需要生成数据库模型。在这种情况下,我们需要两个实体 - User 和 Event - 以及第三个表 - UserEvent - 在它们之间建立多对多关系。为了实现这一目标,建议我们在其中创建一个 Models 文件夹和一个 DbModels 子文件夹,我们可以在其中创建数据库实体。
让我们从用户模型开始。每个用户都应该有 一个唯一的 ID、 电子邮件、 名字、 姓氏、 密码(将以散列格式存储)、角色(可以是演示的用户和管理员)以及与UserEvent表相关的UserEvents。
全屏12345678910公开 课 用户{ 公共 字符串 用户 ID { 获取; 设置; } 公共 字符串 电子邮件 { 获取; 设置; } 公共 字符串 名字 { 获取; 设置; } 公共 字符串 姓氏 { 获取; 设置; } 公共 字符串 密码 { 获取; 设置; } 公共 字符串 角色 { 获取; 设置; } 公共 IList < UserEvent > UserEvents { 获取; 设置; }}
事件模型还应该具有唯一的 ID、标题、类别、日期以及与UserEvents表的关系。
全屏12345678公开 课 活动{ 公共 字符串 Id { 获取; 设置; } 公共 字符串 标题 { 获取; 设置; } 公共 字符串 类别 { 获取; 设置; } 公共 DateTime 日期 { 获取; 设置; } 公共 IList < UserEvent > UserEvents { 获取; 设置; }}
由于一个用户可以参加多个事件,一个事件可以由多个用户参加,因此我们需要在这些实体之间建立多对多的关系。为此,我们将创建一个名为UserEvents的附加表。该表将包括UserId和EventId列,它们将建立用户和事件实体之间的关系。
全屏1234567公共 类 用户事件{ 公共 字符串 用户 ID { 获取; 设置; } 公共 用户 用户 { 获取; 设置; } 公共 字符串 EventId { 获取; 设置; } 公共 事件 事件 { 获取; 设置; }}
创建数据库模型后,下一步是将它们注册到DbContext中。为了实现这一点,我们可以导航到DataContext.cs文件,将所有实体添加为DbSets,并声明我们的关系和主键。这可以通过重写OnModelCreating方法并利用 Fluent API 配置关系和键来完成。完成后,结果应如下所示:
全屏1234567891011121314151617 号18192021公共 类 DataContext : DbContext{ 公共 DataContext (DbContextOptions 选项): 基(选项) { } 公共 DbSet <用户> 用户 { 获取; 设置; } 公共 DbSet < 事件 > 事件 { 获取; 设置; } 公共 DbSet < UserEvent > UserEvents { 获取; 设置; } protected override void OnModelCreating (模型构建器 构建器) { 基地. OnModelCreating (构建器); 建设者。实体<用户> ( ) 。HasKey ( u => 新 { 你。用户身份 }) ; 建设者。实体<事件> ( ) 。HasKey ( e => 新 {
准备好数据库设计后,我们应该生成一个初始迁移来创建数据库。
打开包管理器控制台并写入命令:
添加-迁移InitialCreate
成功执行后,我们应该使用以下命令更新数据库:
更新数据库
然后使用 Microsoft SQL Management Studio,您应该会看到新创建的数据库。
AutoMapper将帮助我们将一种模型转换为另一种模型。这会将输入模型转换为dbModel。我们这样做的原因是我们可能不需要将一个模型的所有属性都包含在另一个模型中。您将在本教程后面看到我们将如何准确地使用它。在此之前,我们首先需要对其进行配置。您可以在官方文档中找到AutoMapper更详细的解释。
首先,我们必须安装 AutoMaper NuGet 包。接下来,我们可以生成一个MappingProfiles.cs文件来定义所有映射。出于组织目的,建议在 Helpers 文件夹下创建此文件。
要声明我们的映射,MappingProfiles应继承 Profile 类,并且我们可以使用CreateMap<from, to>()方法声明我们的映射。如果我们需要能够在相反方向映射模型,我们可以包含.ReverseMap()方法。
完成映射后,我们必须导航到Program.cs文件并使用MappingProfiles注册AutoMapper。
全屏12345678910……var config = 新的 MapperConfiguration ( cfg => { cfg 。AddProfile (新的 MappingProfiles ( )) ; }) ;var 映射器 = 配置. 创建映射器( ) ;建设者。服务。添加单例(映射器);……
我们将使用JWT令牌进行身份验证。它们为我们提供了一种以 JSON 对象的形式在各方之间安全传输信息的方法。您可以在此处阅读有关 JWT 令牌的更多信息。要使用它们,我们必须首先安装必要的 NuGet 包。我们需要Microsoft.IdentityModel.Tokens和Microsoft.AspNetCore.Authentication.JwtBearer。
接下来,我们必须在appsettings.json 文件中定义一些令牌配置。这些配置包括 Issuer、Audience 和 SecretKey。
全屏12345“Jwt”:{ "发行人": "https://localhost:7244/", "观众": "https://localhost:7244/", “密钥”:“S1u*p7e_r+S2e/c4r6e7t*0K/e7y”}
定义令牌配置后,我们可以在Program.cs文件中配置 JWT 服务。这涉及指定将与任何必要的验证参数一起使用的架构。
全屏1234567891011121314151617 号181920建设者。服务。添加身份验证(选项 => { 选项。DefaultAuthenticateScheme = JwtBearerDefaults 。身份验证方案; 选项。DefaultChallengeScheme = JwtBearerDefaults 。身份验证方案; 选项。默认方案 = JwtBearerDefaults 。身份验证方案; })。添加JwtBearer ( o => { 哦。TokenValidationParameters = 新的 TokenValidationParameters { ValidIssuer = 构建者. 配置[ “ Jwt:发行者” ] , 有效受众 = 构建者. 配置[ “ Jwt:受众” ] , IssuerSigningKey = 新的 SymmetricSecurityKey (编码.UTF8.GetBytes (构建器.配置[ “ Jwt : Key ” ])) , 验证发行者 = true , 验证受众 = true , 验证生命周期 = false , 验证发行者签名密钥 = true } ; }) ;……
确保您还添加了app.UseAuthentication();
为了使用Swagger UI测试我们的应用程序端点,我们必须在Program.cs文件中包含app.UseSwaggerUI()。
之后,我们必须生成一个AuthResponse过滤器,以帮助使用 JWT 令牌测试经过身份验证的端点。为此,我们可以创建一个实现IOperationFilter接口的AuthResponsesOperationFilter类。Apply 方法应包含将AuthResponse过滤器添加到 Swagger 所需的逻辑。
全屏1234567891011121314151617 号181920 参考 = 新的 OpenApiReference { 类型 = 参考类型。安全方案, ID = “承载者” } } , 新 列表<字符串> ( ) } } ; 操作。安全性 = 新 列表< OpenApiSecurityRequirement > { 安全要求 } ; 操作。回应。添加(“ 401 ” , 新的 OpenApiResponse { 描述 = “未经授权” }) ; } }}
之后,确保您已将过滤器添加为Program.cs .AddSwaggerGen方法中的选项。
全屏1234567891011121314151617 号1819建设者。服务。添加SwaggerGen (选项 => { 选项。SwaggerDoc (“ v1 ” , 新的 OpenApiInfo { 标题 = “ Northwind CRUD ” , 版本 = “ v1 ” }) ; 选项。AddSecurityDefinition (“承载” , 新的 OpenApiSecurityScheme { In = 参数位置。标题, 描述 = “请输入有效的令牌” , 名称 = “授权” , 类型 = 安全方案类型。http , BearerFormat = “ JWT ” , 方案 = “承载者” }) ; 选项。操作 过滤器<AuthResponsesOperationFilter> ( ) ; } );
您可以阅读《什么是Swagger?》更详细的解释。在官方文档中。
完成配置后,我们可以继续创建注册端点。第一步是生成RegisterInputModel.cs文件,该文件应位于Models/InputModels文件夹下。
注册过程需要电子邮件、名字、姓氏、密码和确认密码字段。所有这些字段都是必填字段,因此我们将包含[Required]属性。我们还将在电子邮件字段中包含[EmailAddress]属性。我们可以根据需要添加其他属性,例如最小和最大长度。然而,为了演示的目的,我们将坚持使用这些属性。
全屏1234567891011121314151617 号公共 类 RegisterInputModel{ [电子邮件地址] 公共 字符串 电子邮件 { 获取; 设置; } [必填] 公共 字符串 名字 { 获取; 设置; } [必填] 公共 字符串 姓氏 { 获取; 设置; } [必填] 公共 字符串 密码 { 获取; 设置; } [必填] 公共 字符串 确认密码 { 获取; 设置; }}
接下来,我们必须向MappingProfiles.cs文件添加一个映射,以实现RegisterInputModel和User模型之间的双向转换。
CreateMap<RegisterInputModel, User>().ReverseMap();
为了保持关注点分离,我们将创建一个 Services 文件夹。每个模块都有自己的服务来与数据库交互。我们可以首先生成AuthService.cs文件并注入DataContext和Configuration。
我们在AuthService.cs中的第一个方法应该是GenerateJwtToken,它将电子邮件和角色作为参数并返回包含用户信息的JWT令牌。
全屏1234567891011121314151617 号181920212223公共 字符串 GenerateJwtToken (字符串 电子邮件, 字符串 角色){ var 发行者 = this . 配置[ “ Jwt:Issuer ” ] ; var 观众 = this . 配置[ “ Jwt:受众” ] ; var key = 编码。ASCII 码。GetBytes ( this.configuration [ “ Jwt :Key ” ] ) ; var tokenDescriptor = 新的 SecurityTokenDescriptor { 主题 = 新的 ClaimsIdentity (新 [ ] { new Claim ( " Id " , Guid.NewGuid ( ) . ToString ( ) ) , _ 新 声明(JwtRegisteredClaimNames .Sub ,电子邮件),_ 新 声明(JwtRegisteredClaimNames 。电子邮件, 电子邮件), 新的 声明(ClaimTypes .角色, 角色), 新 声明(JwtRegisteredClaimNames . Jti , 指导。新指南()。转字符串( )) }) , 过期 = 日期时间。现在。添加分钟( 5 ) , 发行人 = 发行人, 观众 = 观众, SigningCredentials = new SigningCredentials ( new SymmetricSecurityKey ( key ) , SecurityAlgorithms . HmacSha512Signature ) } ;
为了对密码进行哈希处理,我们将使用BCrypt.Net.BCrypt。首先,我们必须安装该包并将其作为 using 语句添加到文件的开头。
使用 BC = BCrypt.Net.BCrypt;
之后,我们将创建几个辅助方法。一个将验证具有给定电子邮件的用户是否存在,另一个将验证该用户,另外两个将通过电子邮件和 ID 获取用户。
全屏1234567891011121314151617 号18192021public bool IsAuthenticated (字符串 电子邮件, 字符串 密码){ var 用户 = this . GetByEmail (电子邮件); 返回 这个。DoesUserExists (电子邮件) && BC 。验证(密码, 用户。密码);}公共 布尔 DoesUserExists (字符串 电子邮件){ var 用户 = this . 数据上下文。用户。FirstOrDefault ( x => x 。电子邮件 == 电子邮件) ; 返回 用户 != null ;}公共 用户 GetById (字符串 id ){ 返回 这个。数据上下文。用户。FirstOrDefault ( c = > c .UserId == id ) ; }公共 用户 GetByEmail (字符串 电子邮件){ 返回 这个。数据上下文。用户。FirstOrDefault ( c = > c .Email == email ) ; }
在创建register方法之前,我们必须首先创建一个生成唯一ID的方法。该方法可以定义如下:
全屏1234567891011公共 类 IdGenerator{ 公共 静态 字符串 CreateLetterId (int length ) { var 随机 = 新 随机( ) ; 常量 字符串 字符 = “ ABCDEFGHIJKLMNOPQRSTUVWXYZ ” ; 返回 新 字符串( Enumerable . Repeat ( chars , length ) 。选择( s => s [随机.下一个( s .长度)]) 。数组( )) ; }}
现在我们可以继续实现 Register 方法。在此方法中,我们将生成一个唯一 ID,检查它是否已存在,如果存在,则生成一个新 ID。然后,我们将散列用户的密码并将新用户添加到数据库中。
全屏1234567891011121314151617 号18公共 用户 注册用户(用户 模型){ var id = IdGenerator 。创建字母ID ( 10 ) ; var exitWithId = this . GetById ( id ) ; while ( existWithId != null ) { id = IdGenerator 。创建字母ID ( 10 ) ; 存在有 ID = 这个. GetById ( id ) ; } 模型。用户ID = id ; 模型。密码 = BC 。HashPassword (模型.密码) ; var userEntity = this . 数据上下文。用户。添加(型号); 这个。数据上下文。保存更改( ) ; 返回 用户实体。实体;}
如果您还没有创建AuthController,那么现在是时候了。转到Controllers文件夹并添加AuthController,它应该继承Controller类。我们还应该添加[ApiController]属性和[Route( "[controller]" )]以便 Swagger 识别它。
之后,如果我们使用映射器、authService 和记录器并创建 RegisterMethod,则应该注入它们。它应该是只有未经身份验证的用户才能访问的发布请求。它应该接受RegisterInputModel作为参数并检查ModelState是否有效。如果是这样,它将为该用户生成 jwt 令牌。整个方法应该如下所示:
全屏1234567891011121314151617 号18192021[允许匿名][ HttpPost ( “注册” )]public ActionResult <string>注册(RegisterInputModel userModel )_ _ { 尝试 { if ( ModelState . IsValid ) { if ( userModel .密码 != userModel .确认密码) { return BadRequest ( "密码不匹配!" ) ; } if ( this . authService .DoesUserExists ( userModel . Email ) ) { return BadRequest ( "用户已经存在!" ) ; } var 映射模型 = this . 映射器。Map < RegisterInputModel , User > ( userModel ) ; 映射模型。角色 = “用户” ;
登录功能类似,只是我们需要在数据库中搜索用户。我们应该首先创建LoginInputModel.cs,这次只有电子邮件和密码字段。不要忘记将其添加到MappingProfiles.cs中 ,否则它将无法工作。
全屏123456789公共 类 登录输入模型{ [电子邮件地址] [必填] 公共 字符串 电子邮件 { 获取; 设置; } [必填] 公共 字符串 密码 { 获取; 设置; }}
然后在AuthController.cs中创建 Login 方法,该方法将以LoginInputModel作为参数并检查用户是否经过身份验证。如果是这样,它应该生成一个令牌。否则,它应该返回错误。
全屏1234567891011121314151617 号18192021[允许匿名][ HttpPost ( “登录” )]公共 ActionResult <字符串> 登录( LoginInputModel userModel ){ 尝试 { if ( ModelState . IsValid ) { if ( this . authService . IsAuthenticated ( userModel .电子邮件, userModel .密码)) { var 用户 = this . authService 。GetByEmail ( userModel.Email ) ; _ _ var 令牌 = this . authService 。GenerateJwtToken ( userModel.Email , user.Role ) ; _ _ _ _ 返回 确定(令牌); } return BadRequest ( "邮箱或密码不正确!" ) ; } 返回 BadRequest (模型状态);
完成身份验证后,我们可以开发事件的端点。我们将创建完整的 CRUD 操作。与用户一样,我们应该创建EventService.cs文件。它将包括通过 ID 获取事件、获取特定用户的所有事件、创建新事件、更新现有事件和删除事件的方法。整个文件应如下所示:
全屏1234567891011121314151617 号181920212223公共 类 事件服务{ 私有 只读 DataContext dataContext ; 公共 事件服务(DataContext dataContext ) { 这个。数据上下文 = 数据上下文; } 公共 事件[ ] GetAllForUser (字符串 电子邮件) { var 用户 = this . 数据上下文。用户 。FirstOrDefault (用户 => 用户。电子邮件 == 电子邮件) ; 返回 这个。数据上下文。活动 。包含( ev = > ev .UserEvents ) 。其中( e => e . UserEvents . FirstOrDefault ( ue => ue . UserId == user . UserId ) != null ) 。数组( ) ; } 公共 事件 GetById (字符串 id )
接下来,您需要转到控制器并为每个请求设置一个方法。
我们将创建一个EventBindingModel,用于存储事件模型中的所有必要数据。
对于GetAll方法,请确保它使用GET请求并检索用户的令牌、对其进行解码并获取该用户的事件。
全屏1234567891011121314151617 号181920212223[ HttpGet ][授权]公共 ActionResult < EventBindingModel [ ] > GetAll ( ){ 尝试 { var userEmail = this . authService 。DecodeEmailFromToken ( this.Request.Headers [ “授权” ] ) ; _ _ _ var 事件 = this . 事件服务。GetAllForUser (用户电子邮件) ; return Ok ( this.mapper.Map < Event [ ] , EventBindingModel [ ] > ( events ) ) ; _ _ _ } catch (异常 错误) { 记录器。LogError (错误.消息) ; 返回 状态代码(500 ); }}……公共 字符串 DecodeEmailFromToken (字符串 标记){ var decodedToken = new JwtSecurityTokenHandler();
通过id获取也应该是以id作为参数的GET请求。
全屏1234567891011121314151617 号181920[授权]公共 ActionResult <事件> GetById (字符串 id ){ 尝试 { var eventEntity = this . 事件服务。GetById ( id ) ; if ( eventEntity != null ) { 返回 确定(事件实体); } 返回 未找到(); } 捕获 (异常 错误) { 记录器。LogError (错误.消息) ; 返回 状态代码(500 ); }}
删除端点将是DELETE请求,并且也会以 id 作为参数。
全屏1234567891011121314151617 号18192021[ HttpDelete ( “ {id} ” )][授权(角色 = “管理员” )]公共 ActionResult <事件> 删除(字符串 id ){ 尝试 { var eventEntity = this . 事件服务。删除(id ); if ( eventEntity != null ) { 返回 确定(事件实体); } 返回 未找到(); } 捕获 (异常 错误) { 记录器。LogError (错误.消息) ; 返回 状态代码(500 ); }}
为了简化添加或更新事件记录的过程,让我们专门为 Create 和 Update 操作创建一个EventInputModel 。该模型只需要我们提供 userEvents 的基本属性,包括标题、类别、日期、userId 和 eventId。通过使用此模型,我们无需为每个操作指定事件模型的所有属性。
全屏1234567891011121314151617 号18192021[ HttpPost ]public ActionResult <Event>创建(EventInputModel模型)_ _ { 尝试 { if ( ModelState . IsValid ) { var 映射模型 = this . 映射器。映射 < 事件输入模型, 事件 > (模型); var eventEntity = this . 事件服务。创建(映射模型); 返回 确定(事件实体); } 返回 BadRequest (模型状态); } 捕获 (异常 错误) { 记录器。LogError (错误.消息) ; 返回 状态代码(500 ); }
更新将是PUT请求,并且还将EventInputModel作为参数。
全屏1234567891011121314151617 号18192021[ HttpPut ]public ActionResult <Event>更新(EventInputModel模型)_ _ { 尝试 { if ( ModelState . IsValid ) { var 映射模型 = this . 映射器。Map < EventInputModel , Event > (模型) ; var eventEntity = this . 事件服务。更新(映射模型); if ( eventEntity != null ) { 返回 确定(事件实体); } 返回 未找到(); } 返回 BadRequest (模型状态); } 捕获 (异常 错误)
为了限制特定用户角色的某些操作,我们可以使用基于角色的授权。例如,在我们的场景中,我们希望将对事件的创建、更新和删除端点的访问权限限制为具有管理员角色的用户。
要进行设置,我们需要添加app.UseAuthorization(); 到我们的Program.cs文件。然后,对于每个需要限制访问的端点,我们将添加 [Authorize] 属性,该属性将指定允许的角色。例如,我们可以确保只有管理员才能访问删除端点。
全屏1234……[授权(角色 = “管理员” )]公共 ActionResult <事件> 删除(字符串 id )……
运行应用程序时,我们经常希望在数据库中预先填充一些数据,无论是出于测试目的还是其他原因。这就是播种的用武之地。首先,我们需要定义要使用的数据。
为此,我们可以创建一个 Resources 文件夹并添加两个 JSON 文件:一个用于用户,一个用于事件。这些文件应该包含我们想要填充到数据库中的数据。例如,我们的文件可能如下所示:
全屏1234567891011121314151617 号18[ { “用户ID”:“USERABCDE”, “名字”:“凯特”, “姓氏”:“洛伦兹”, “密码”:“凯特.洛伦茨”, “电子邮件”:“klorenz@hrcorp.com”, “角色”:“管理员” } , { “用户ID”:“ASERABCDE”, “名字”:“安东尼”, “姓氏”:“穆雷”, “密码”:“安东尼.默里”, “电子邮件”:“amurray@hrcorp.com”, “角色”:“用户” }]
接下来,我们应该创建一个包含 Seed 方法的DbSeeder类。该方法将读取我们之前定义的数据并将其填充到数据库中。为此,我们需要传入dbContext作为参数。
全屏1234567891011121314151617 号181920212223公共 类 DBSeeder{ 公共 静态 无效 种子(DataContext dbContext ) { 参数空异常。ThrowIfNull ( dbContext , nameof ( dbContext )) ; 数据库上下文。数据库。确保创建(); varexecutionStrategy = dbContext 。_ 数据库。创建执行策略(); 执行策略。执行( ( ) => { using ( var transaction = dbContext . Database . BeginTransaction ( )) { 尝试 { // 种子用户 if ( ! dbContext.Users.Any ( ) ) _ _ _ { var usersData = 文件. ReadAllText ( “ ./Resources/users.json ” ) ; var parsedUsers = JsonConvert 。DeserializeObject < User [ ] > ( usersData ) ; foreach(var user in parsedUsers)
之后,在我们的Helpers文件夹中,我们应该创建一个数据库初始化程序扩展,它将运行Seed方法。
全屏123456789101112131415公共 静态 类 DBInitializerExtension{ public static IApplicationBuilder UseSeedDB (此 IApplicationBuilder 应用程序) { 参数空异常。ThrowIfNull (应用程序, nameof (应用程序)) ; 使用 varscope = app 。_ 应用服务。创建作用域( ) ; var 服务 = 范围。服务提供商; var 上下文 = 服务. GetRequiredService <DataContext> ( ) ; _ _ DBSeeder 。种子(上下文); 返回 应用程序; }}
最后,我们需要打开Program.cs文件并添加app.UseSeedDB()方法。这确保了当我们的应用程序启动时,它将检查数据库中是否有任何数据。如果没有,我们之前创建的 Seed 方法将自动用我们定义的数据填充它。
要为我们的端点启用跨源资源共享(CORS),我们需要在Program.cs文件中添加 cors 服务。在这种情况下,我们将允许从任何区域进行访问,但您可以根据需要指定特定的域。
全屏123456建设者。服务。AddCors (策略生成器 => 策略生成器。添加默认策略(策略 => 政策。与起源(“ * ” ) 。允许任意标头( ) 。允许任意标头( )));
然后添加app.UseCors(); 方法。
这将允许我们从前端应用程序访问我们的 API。