1 自定义管道中间件
1.1 WebApi.Middleware.CorsMiddleware
namespace WebApi.Middleware
{
/// <summary>
/// 【跨域访问中间件--类】
/// <remarks>
/// 摘要:
/// 该管道中间件类主要为了解决在由vue/uni-app前端项目(Cors)访问当前后端项目时,浏览器或App中出现的异常:
/// 1、“has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.”。
/// 2、“has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.”。
/// </remarks>
/// </summary>
public class CorsMiddleware
{
#region 拷贝构造方法与变量
/// <summary>
/// 【下1个】
/// <remarks>
/// 摘要:
/// .Net(Core)框架内置管道中的下1个管道中间件实例。
/// </remarks>
/// </summary>
private readonly RequestDelegate _next;
///<param name="next">.Net(Core)框架内置管道中的下1个管道中间件实例。</param>
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过该构造方法中的参数实例,实例化.Net(Core)框架内置管道中的下1个管道中间件实例。
/// </remarks>
/// </summary>
public CorsMiddleware(RequestDelegate next)
{
_next = next;
}
#endregion
#region 方法
///<param name="context">HTTP上下文实例。</param>
/// <summary>
/// 【异步调用】
/// <remarks>
/// 摘要:
/// 通过该方法向.Net(Core)框架内置管道中集成当前管道中间件,解决由vue/uni-app前端项目(Cors)访问当前后端项目时,浏览器或App中出现的异常:
/// 1、“has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.”。
/// 2、“has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.”。
/// </remarks>
/// </summary>
public async Task InvokeAsync(HttpContext context)
{
//解决在由Hbuilder创建的前端Xuni-app项目(Cors)访问当前后端项目时,浏览器或App中会出现异常:
//“has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.”。
if (!context.Response.Headers.ContainsKey("Access-Control-Allow-Headers"))
{
context.Response.Headers.Add("Access-Control-Allow-Headers", "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization");
}
if (!context.Response.Headers.ContainsKey("Access-Control-Allow-Methods"))
{
context.Response.Headers.Add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS");
}
//解决在由Hbuilder创建的前端Xuni-app项目(Cors)访问当前后端项目时,浏览器或App中会出现异常:
//“has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.”。
if (!context.Response.Headers.ContainsKey("Access-Control-Allow-Origin"))
{
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
}
await _next(context);
}
#endregion
}
}
1.2 WebApi.Middleware.SwaggerHomeMiddleware
namespace WebApi.Middleware
{
/// <summary>
/// 【Swagger主页中间件--类】
/// <remarks>
/// 摘要:
/// 该管道中间件类主要为了把“/Swagger/index.html”设定为默认启动页面,在IIS部署后,
/// 通过当前管道中间件把“根路由”强制自动跳转到“根路由”+“/Swagger/index.html”,从而避免“根路由”页面中“404”错误的出现。
/// </remarks>
/// </summary>
public class SwaggerHomeMiddleware
{
#region 拷贝构造方法与变量
/// <summary>
/// 【下1个】
/// <remarks>
/// 摘要:
/// .Net(Core)框架内置管道中的下1个管道中间件实例。
/// </remarks>
/// </summary>
private readonly RequestDelegate _next;
///<param name="next">.Net(Core)框架内置管道中的下1个管道中间件实例。</param>
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过该构造方法中的参数实例,实例化.Net(Core)框架内置管道中的下1个管道中间件实例。
/// </remarks>
/// </summary>
public SwaggerHomeMiddleware(RequestDelegate next)
{
_next = next;
}
#endregion
#region 方法
///<param name="context">HTTP上下文实例。</param>
/// <summary>
/// 【异步调用】
/// <remarks>
/// 摘要:
/// 通过该方法向.Net(Core)框架内置管道中间件集成当前管道中间件,把“/Swagger/index.html”设定为默认启动页面,在IIS部署后,
/// 通过当前管道中间件把“根路由” 强制自动跳转到“根路由”+“/Swagger/index.html”,从而避免“根路由”页面中“404”错误的出现。
/// </remarks>
/// </summary>
public async Task InvokeAsync(HttpContext context)
{
if (context.Request.Path == "/")
{
context.Response.Redirect("/Swagger/index.html");
return;
}
await _next(context);
}
#endregion
}
}
2 重构Program.cs
using Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using System.Reflection;
using System.Runtime.InteropServices;
using WebApi.Middleware;
var builder = WebApplication.CreateBuilder(args);
//把“Microsoft.EntityFrameworkCore.SqlServer”中间件实例,依赖注入到.Net(Core)6框架内置容器中。
builder.Services.AddDbContext<EFCoreContext>(
//通过“DbContextOptionsBuilder”实例中的参数实例,为“Microsoft.EntityFrameworkCore.SqlServer”中间件的实例化提供参数实例,
//最终把“Microsoft.EntityFrameworkCore.SqlServer”中间件实例,依赖注入到.Net(Core)6框架内置容器中。
//IIS发布部署连接字符串必须使用“SQL Server身份认证”数据库连接方式,才能实现发布部署程序与数据库的CURD的操作。
options => options.UseSqlServer(builder.Configuration.GetConnectionString("SqlServerSQL")));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//通过AddSwaggerGen依赖注入中间,获取Api控制器方法的版本控制信息和注释等数据信息,依赖注入.Net7框架的内置容器中,为在“index.html”页面上渲染显示这些信息,作好预处理操作。
builder.Services.AddSwaggerGen(options => {
options.SwaggerDoc("v1",
new OpenApiInfo
{
Version = "v1",
Title = $"接口文档—{RuntimeInformation.FrameworkDescription}",
});
//获取"UserServer.xml"文件的文件名。
string _xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
//获取"WebApi.xml"文件的绝对路径。
string _xmlFilePath = Path.Combine(AppContext.BaseDirectory, _xmlFileName);
//把控件器行为方法中的注释信息加载到"Swagger/index.html"页面中的控件器行为方法进行渲染显示。
//注意:如果不在“*.csproj”文件中启用“<GenerateDocumentationFile>true</GenerateDocumentationFile>”配置,下面语句会出现逻辑异常。
options.IncludeXmlComments(_xmlFilePath, true);
});
var app = builder.Build();
//把自定义管道中间中集成到.Net(Core)框架内置管道中,解决vue/uni-app前端项目(Cors)访问当前后端项目时,浏览器或App中出现的异常:
// 1、“has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.”。
// 2、“has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.”。
app.UseMiddleware<CorsMiddleware>();
//注意:在IIS部署时必须把下面两个管道中间件从“if (app.Environment.IsDevelopment())”取出,否则;“http://localhost:8090/Swagger/index.html”页面会出现“404”错误。
app.UseSwagger();
app.UseSwaggerUI();
//该自定义管道中间件设定/Swagger/index.html为默认启动页面。
//注意:在IIS部署时如果不定义该自定义管道中间件“http://localhost:8090”页面会出现“404”错误,但“http://localhost:8090/Swagger/index.html”页面可用;
//如果定义该自定义管道中间件IIS部署后的“http://localhost:8090”页面会强制自动跳转到“http://localhost:8090/Swagger/index.html”页面,从而避免“根路由”页面中“404”错误的出现。
app.UseMiddleware<SwaggerHomeMiddleware>();
//“SwaggerHomeMiddleware”管道中间件的直接实现调用。
//app.Use(async (context, next) =>
//{
// if (context.Request.Path == "/")
// {
// context.Response.Redirect("/Swagger/index.html");
// return;
// }
// await next.Invoke();
//});
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
3 WebApi.Test.RoleTestModel
namespace WebApi.Test
{
public record RoleTestModel
{
/// <summary>
/// 【角色名】
/// <remarks>
/// 摘要:
/// 获取/设置1个指定的角色名。
/// </remarks>
/// </summary>
public string Name { get; set; }
/// <summary>
/// 【启用?】
/// <remarks>
/// 摘要:
/// 获取/设置1个值false(禁用)/true(默认值:启用),该值指示角色实体的1个指定实例是否处于启用状态。
/// </remarks>
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// 【备注】
/// <remarks>
/// 摘要:
/// 获取/设置1个指定角色的备注信息。
/// </remarks>
/// </summary>
public string Remark { get; set; }
}
}
4 WebApi.Controllers.RoleController
using Core.Domain.Users;
using Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using WebApi.Test;
namespace WebApi.Controllers
{
/// <summary>
/// 【角色Api控制器--类】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该类中的方法成员,为前端角色页面提供Api方法和数据支撑。
/// </remarks>
[Route("[controller]/[action]")]
[ApiController]
public class RoleController : ControllerBase
{
#region 拷贝构造方法与变量
private readonly EFCoreContext _context;
public RoleController(EFCoreContext context)
{
_context = context;
}
#endregion
#region 方法
/// <summary>
/// 【获取角色列表--需权限】
/// </summary>
/// <remarks>
/// 摘要:
/// 从角色表中获取角色实体的所有实例,并把这些实例存储到列表实例中。
/// </remarks>
/// <returns>
/// 返回:
/// 列表实例,该实例存储着角色实体的所有实例。
/// </returns>
[HttpGet]
public async Task<List<Role>> GetRoleListAsync()
{
return await _context.GetDbSet<Role>().ToListAsync();
}
/// <param name="role">角色实体的1个指定实例。</param>
/// <summary>
/// 【添加角色--需权限】
/// </summary>
/// <remarks>
/// 摘要:
/// 把角色实体1个指定实例持久化到持久化到角色表中。
/// </remarks>
/// <returns>
/// 返回:
/// 角色实体的1个指定实例。
/// </returns>
[HttpPost]
public async Task<Role> AddRoleAsync([FromBody] Role role)
{
await _context.GetDbSet<Role>().AddAsync(role);
await _context.SaveChangesAsync();
return role;
}
/// <param name="roleId">角色实体1个指定实例的长整型编号值。</param>
/// <summary>
/// 【更新角色--需权限】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过1个指定的长整型编号值,对1个角色实体1个指定实例并持久化到角色表的指定行中。
/// </remarks>
/// <returns>
/// 返回:
/// 角色实体的1个指定实例。
/// </returns>
[HttpPost]
public async Task<Role> UpdateRoleAsync(long roleId)
{
Role _model = await _context.GetDbSet<Role>().SingleAsync(role => role.Id == roleId);
_model.Remark = _model.Remark + "Update";
_context.GetDbSet<Role>().Update(_model);
await _context.SaveChangesAsync();
return _model;
}
#endregion
#region 方法--测试
/// <param name="roleTestModel">角色测试模型的1个指定实例。</param>
/// <summary>
/// 【添加角色(测试模型)--需权限】
/// </summary>
/// <remarks>
/// 摘要:
/// 把角色实体1个指定实例持久化到持久化到角色表中(只是测试使用,可以被删除)。
/// </remarks>
/// <returns>
/// 返回:
/// 角色实体的1个指定实例。
/// </returns>
[HttpPost]
public async Task<Role> AddRoleTestModelAsync([FromBody] RoleTestModel roleTestModel)
{
Role role = new Role() { Name = roleTestModel.Name, IsActive = roleTestModel.IsActive, Remark = roleTestModel.Remark };
await _context.GetDbSet<Role>().AddAsync(role);
await _context.SaveChangesAsync();
return role;
}
#endregion
}
}
5 IIS发布部署与调试注意
5.1 调试注意
5.1.1 使用“/Swagger/index.html”调试
5.1.1.1 通过角色模型记录实例调试
在“/Swagger/index.html”页面中使用带有“[FromBody]”参数实例的Api方法进行调试时,如果参数实例的类型为:“RoleTestModel”,则可以直接直接执行该Api方法:“WebApi.Controllers.RoleController.AddRoleTestModelAsync”,如下图所示:
5.1.1.2 直接通过角色实体实例调试
5.1.1 使用“Postman”调试
5.2 IIS发布部署注意
5.2.1 IIS发布部署依赖包
5.2.1.1 连接字符串必须使用“SQL Server身份认证”数据库连接方式
重构“appsettings.json”文件
{
"ConnectionStrings": {
//Trusted_Connection=true或Integrated Security=true/SSPI:“Windows凭据”对SQL Server进行身份验证,表示可以在不知道数据库用户名和密码的情况下时,依然可以连接SQL Server数据库。
//"integrated":"security=true是通过“Windows身份认证”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接;表示可以在不知道数据库用户名和密码的情况下时,依然可以连接SQL Server数据库,如果integrated", "security=false","或者不写,表示一定要输入正确的数据库登录名和密码。": null。
//Persist Security Info:该配置只用于通过“SQL Server身份认证”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接;简单的理解为"ADO在数据库连接成功后是否保存密码信息",True表示保存,False表示不保存.ADO缺省为True(ADO.net缺省为False,未测试,根据参考资料上说的)。
//MultipleActiveResultSets:它允许在单个连接上执行多重的数据库查询或存储过程,目前只适用于Sql Server 2005及其以上版本;如果不用MultipleActiveResultSets ,则一般报错为sqldatareader未关闭,即需要关闭了之后才能打开另一个。
//Trust Server Certificate:是否使用SSL证书和加密方式,对SQL Server数据库的连接字符串进行加密,该操作属性安全性配置,目前只适用于Sql Server 2005及其以上版本;
// "SqlServerWindows": "Data Source=.;Initial Catalog=ShopDemo;Integrated Security=true;MultipleActiveResultSets=true;Trust Server Certificate=True"
"SqlServerSQL": "Data Source=.;Initial Catalog=ShopDemo;Integrated Security=False;Persist Security Info=False;User ID=zz;Password=zz;MultipleActiveResultSets=true;Trust Server Certificate=True"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
5.2.1.2 依赖包
在WebApi启用项目中添加依赖包:
1、Microsoft.EntityFrameworkCore.Tools或Microsoft.EntityFrameworkCore.Design;其中Microsoft.EntityFrameworkCore.Tools依赖包包含Microsoft.EntityFrameworkCore.Desig依赖包,当前程序中使用Microsoft.EntityFrameworkCore.Tools依赖包。
2、注意:这两个依赖包必须直接引用在WebApi启用项目中,而非间接Data引用在项目中。
3、IIS部署的具体操作见:“第1章 基于.Net(Core)框架Web程序的IIS部署发布_zhoujian_911的博客-CSDN博客_.net iis发布”。
5.2.2 IIS发布部署404错误页面解决方案
在当前程序部署后,默认路由页会出现404错误,为了避免该错误必须把“SwaggerHomeMiddleware”自定义管道中间件集成到.Net内置义管道中间件,把默认路由页强制自动跳转到“/Swagger/index.html”,从而把默认路由页相对设定为了“/Swagger/index.html”。
对以上功能更为具体实现和注释见:221220_001shopvue(布局设计完成)。