技术文章

了解最新技术文章

当前位置:首页>技术文章>技术文章
全部 110 常见问题 0 技术文章 110

如何使用 ASP.NET Core 创建基于角色的 Web API

时间:2023-09-21   访问量:1027

在使用 ASP.NET Core 构建基于角色的 Web API 时,代码优先方法可能是一种强大且高效的方法。使用它,我们可以在代码中定义数据模型和关系,然后自动生成相应的数据库模式。这会导致什么?毫无疑问,更快的开发周期和更大的灵活性。怎么会?因为可以快速轻松地更改数据模型,而无需直接修改数据库架构。您可以在 swagger.io 上阅读有关“设计优先”和“代码优先”方法的更多信息。

在本教程中,我们将介绍使用 ASP.NET Core 6 创建基于角色的 Web API 的步骤。我们将使用 Swagger UI 来可视化我们的端点并与作为数据库的 MS SQL Server 进行交互。该应用程序将包括身份验证模块和事件模块。登录用户将能够查看与其帐户关联的事件,而具有管理员角色的用户可以创建、更新和删除事件。

你将学到的东西:

让我们开始吧!

项目设置

首先,我们需要建立我们的项目。为此,请打开 Visual Studio,创建一个新项目,然后选择 ASP.NET Core Web API。

 创建新的 ASP.NET Core Web API 项目

选择应用程序的名称,然后单击“下一步”。

定义 ASP.NET Core Web App 项目名称

设置 API 数据库

初始化应用程序后,我们需要配置数据库。我们将使用EntityFrameworkCore作为ORM,因此它将帮助我们管理数据库。因此,我们应该安装一些软件包。

设置 API 数据库

成功安装软件包后要做的下一件事是创建DbContext创建DataContext.cs文件并继承DBContext类。在这里我们将定义我们的表。


全屏12345678公共 DataContext DbContext{  公共 DataContext DbContextOptions 选项 选项  {  }  //定义我们的表}


然后我们应该打开Program.cs文件并添加dbContext我们应该指定来自 appsettings.json 文件的dbProvider和连接字符串。dbProvider可以是SqlServer、MySqlInMemory


全屏123456789101112// 添加数据库上下文var dbProvider = 生成器. 配置GetConnectionString ( "提供者" ) ;建设者服务AddDbContext <DataContext> 选项= > _  {    if ( dbProvider == " SqlServer " )    {   选项UseSqlServer ( builder.Configuration.GetConnectionString ( " SqlServerConnectionString " ) ) ; _ _ _    }  }) ;


确保您已appsettings.json文件中添加ConnectionStringProvider,如下所示:


全屏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的附加表。该表将包括UserIdEventId列,它们将建立用户事件实体之间的关系


全屏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.TokensMicrosoft.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

为了使用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文件添加一个映射,以实现RegisterInputModelUser模型之间的双向转换。

CreateMap<RegisterInputModel, User>().ReverseMap();

为了保持关注点分离,我们将创建一个 Services 文件夹。每个模块都有自己的服务来与数据库交互。我们可以首先生成AuthService.cs文件并注入DataContextConfiguration

我们在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

完成身份验证后,我们可以开发事件的端点。我们将创建完整的 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 )……


创建 DbSeeder

运行应用程序时,我们经常希望在数据库中预先填充一些数据,无论是出于测试目的还是其他原因。这就是播种的用武之地。首先,我们需要定义要使用的数据。

为此,我们可以创建一个 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

要为我们的端点启用跨源资源共享(CORS),我们需要在Program.cs文件中添加 cors 服务。在这种情况下,我们将允许从任何区域进行访问,但您可以根据需要指定特定的域。


全屏123456建设者服务AddCors (策略生成器 =>    策略生成器添加默认策略策略 =>     政策与起源*     允许任意标头( )     允许任意标头( ))


然后添加app.UseCors(); 方法。

这将允许我们从前端应用程序访问我们的 API。


上一篇:使用 Figma 自动布局和 App Builder 加速设计到代码

下一篇:使用 Ignite UI Dock Manager 管理复杂的 Web 布局并提高可用性

发表评论:

评论记录:

未查询到任何数据!

在线咨询

点击这里给我发消息 售前咨询专员

点击这里给我发消息 售后服务专员

在线咨询

免费通话

24小时免费咨询

请输入您的联系电话,座机请加区号

免费通话

微信扫一扫

微信联系
返回顶部