• 第1章 模拟器/真机对后端数据的获取之后端实现


    1 准备工作

    1.2 User

    namespace Web.Domain.Users

    {

        ///

        /// 【用户--类】

        ///

        /// 摘要:

        ///     通过该实体类及其属性成员,用于实现当前程序【SecondPracticeServer】.【领域】.【用户集】.【用户】实体与“[SecondPracticeServer].[User]”表之间的CURD的交互操作,并把这些数据存储到数据库设置实例中(内存)。

        ///

        ///

        public class User

        {

            ///

            /// 【编号】

            ///

            /// 摘要:

            ///     获取/设置用户实体1个指定实例的长整型编号值。

            ///

            ///

            public long Id { get; set; }

            ///

            /// 【用户名】

            ///

            /// 摘要:

            ///     获取/设置1个指定的用户名。

            ///

            ///

            public string Name { get; set; }

            ///

            /// 【密码】

            ///

            /// 摘要:

            ///     获取/设置1个指定的密码。

            ///

            ///

            public string Password { get; set; }

            ///

            /// 【已经删除?】

            ///

            /// 摘要:

            ///     获取/设置1个值false(禁用)/true(默认值,启用),该值指示用户实体1个指定实例是否已经处于启用状态。

            ///

            ///

            public bool? IsEnable { get; set; }

            ///

            /// 【创建时间】

            ///

            /// 摘要:

            ///     获取/设置用户实体1个指定实例第1次被持久化到用户表中的时间。

            ///

            ///

            public DateTime CreateTime { get; set; }

        }

    }

    1.2 EFCoreContext

    using Microsoft.EntityFrameworkCore;

    using Web.Domain.Users;

    namespace Web.Data

    {

        ///

        /// 【EFCore上下文】

        ///

        /// 摘要:

        ///     通过该类实例化“Microsoft.EntityFrameworkCore.SqlServer”中间件,从而实例当前程中实体实例与SQLServer软件中指定数据库的数据交换操作。

        ///

        ///

        public class EFCoreContext : DbContext

        {

            #region 拷贝构造方法

            ///

            /// 【拷贝构造方法】

            ///

            /// 摘要:

            ///    基类构造通过该构造方法中的参数实例,连接到指定数据库(SQL Server)数据库软件中数据库。

            ///

            ///

            public EFCoreContext(DbContextOptions options) : base(options)

            {

                //如果(SQL Server)数据库软件中没有指定的数据库, 当通过Code First模式时,在第1次生成数据库时,则通过下1行语句结合数据库连接字符串,在(SQL Server)数据库软件中生成指定的数据库数据库、表、字段和约束规则。

                Database.EnsureCreated();

                /*

                如果(SQL Server)数据库软件中没有指定的数据库, 当通过Code First模式时,在第1次生成数据库时,则也通过下行执行迁移和更新命令行的结合数据库连接字符串,在(SQL Server)数据库软件中生成指定的数据库数据库、表、字段和约束规则。

                Add-Migration Initialize(Initialize:自动生成的迁移类名,这里特指:20220803125612_Initialize.cs):

                Update-Database Initialize(通过自动生成的迁移类中的定义,自动在指定的数据库软件中生成指定的数据库、表、字段和约束规则)

                 */

            }

            #endregion

            #region 属性

            ///

            /// 【用户数据库设置】

            ///

            /// 摘要:

            ///     获取/设置用户实体的数据库设置实例,用于实现当前程序【UserServer】.【领域】.【用户集】.【用户】实体与“[UserServer].[User]”表之间的CURD的交互操作,并把这些数据存储到数据库设置实例中(内存)。

            ///

            ///

            public DbSet UserDbSet { get; set; }

            #endregion

            #region 方法--私有/保护--覆写

            /// name="builder">模型生成器实例,用于把当前程序中实体和属性所定义的约束规则,映射到数据库指定表及其字段上。

            ///

            /// 【模型生成执行...】

            ///

            /// 摘要:

            ///     该方法把当前程序中实体和属性所定义的约束规则,映射到数据库指定表及其字段上。

            ///

            ///

            protected override void OnModelCreating(ModelBuilder builder)

            {

                //用户表约束规则,映射定义。

                builder.Entity().ToTable(nameof(User));

                builder.Entity().HasKey(user => user.Id);

                builder.Entity().Property(user => user.Name).HasMaxLength(30);

                builder.Entity().Property(user => user.Password).HasMaxLength(255);

                base.OnModelCreating(builder);

            }

            #endregion

        }

    }

    2 跨域(Cors)与Swagger

    2.1 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=SwaggerVue;Integrated Security=true;MultipleActiveResultSets=true;Trust Server Certificate=True",

        "SqlServerSQL": "Data Source=.;Initial Catalog=SecondPracticeServer;Integrated Security=False;Persist Security Info=False;User ID=zz;Password=zz;MultipleActiveResultSets=true;Trust Server Certificate=True"

      },

      // 跨域(Cors)配置的域名及其端口集,该端口集中是否包含有vue/uni-app前端项目的访问域名及其端口,如果配置域名及其端口集中,不包含后端项目的访问域名及其端口,

      //且在“Program.cs” 文件进行了限定定义,那么vue/uni-app前端是不能与.Net(Core)6后端项目进行交互操作的。

      "Cors": {

        "PolicyName": "CorsIpAccess", //vue/uni-app前端是不能与.Net(Core)6后端项目进行交互操作的策略名称。

        "EnableAllIPs": false, //当为true时,开放所有IP均可访问。    

        //跨域(Cors)配置的域名及其端口集,用来限定vue/uni-app前端的访问及其交互操作。

        //注意:http://127.0.0.1:1818 和 http://localhost:1818 是不一样的

        "IPs": "http://localhost:8080,http://localhost:8081,http://localhost:8082,http://localhost:8083,http://localhost:8021,https://localhost:443"

      },

      "Logging": {

        "LogLevel": {

          "Default": "Information",

          "Microsoft.AspNetCore": "Warning"

        }

      },

      "AllowedHosts": "*"

    }

    2.2 CorsMiddleware

    namespace Web.Middleware

    {

        ///

        /// 【跨域访问中间件】

        ///

        ///

        /// 摘要:

        ///     该管道中间件类主要为了解决在由Hbuilder创建的前端Xuni-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.”。

        ///

        public class CorsMiddleware

        {

            #region 拷贝构造方法

            ///

            /// 【下1个】

            ///

            ///

            /// 摘要:

            ///     .Net(Core)框架内置管道中的下1个管道中间件实例。

            ///

            private readonly RequestDelegate _next;

            /// name="next">.Net(Core)框架内置管道中的下1个管道中间件实例。

            ///

            /// 【拷贝构造方法】

            ///

            ///

            /// 摘要:

            ///    通过该构造方法中的参数实例,实例化.Net(Core)框架内置管道中的下1个管道中间件实例。

            ///

            public CorsMiddleware(RequestDelegate next)

            {

                _next = next;

            }

            #endregion

            #region 方法

            /// name="context">HTTP上下文实例。

            ///

            /// 【调用】

            ///

            ///

            /// 摘要:

            ///    通过该方法向.Net(Core)框架内置管道中集成当前管道中间件,解决在由Hbuilder创建的前端Xuni-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.”。

            ///

            public async Task Invoke(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

        }

    }

    2.3 Program

    using Microsoft.EntityFrameworkCore;

    using Microsoft.OpenApi.Models;

    using System.Reflection;

    using Web.Data;

    using Web.Middleware;

    var builder = WebApplication.CreateBuilder(args);

    //把“Microsoft.EntityFrameworkCore.SqlServer”中间件实例,依赖注入到.Net(Core)6框架内置容器中。

    builder.Services.AddDbContext

        //通过“DbContextOptionsBuilder”实例中的参数实例,为“Microsoft.EntityFrameworkCore.SqlServer”中间件的实例化提供参数实例,

        //最终把“Microsoft.EntityFrameworkCore.SqlServer”中间件实例,依赖注入到.Net(Core)6框架内置容器中。

        (options => options.UseSqlServer(builder.Configuration.GetConnectionString("SqlServerSQL")));

    builder.Services.AddControllers();

    builder.Services.AddEndpointsApiExplorer();

    //通过AddSwaggerGen依赖注入中间方法,把Swagger中间件实例注入到.Net(Core)6框架默认容器中。

    builder.Services.AddSwaggerGen(options => {

        options.SwaggerDoc("v1", new OpenApiInfo { Title = "第2次实践--接口文档", Version = "v1" });

        //获取"UserServer.xml"文件的文件名。

        string _xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";

        //获取"SecondPracticeServer.xml"文件的绝对路径。

        string _xmlFilePath = Path.Combine(AppContext.BaseDirectory, _xmlFileName);

        //把控件器行为方法中的注释信息加载到"Swagger/index.html"页面中的控件器行为方法进行渲染显示。

        //注意:如果不在“*.csproj”文件中启用“true”配置,下面语句会出现逻辑异常。

        options.IncludeXmlComments(_xmlFilePath, true);

    });

    //通过AddCors依赖注入中间方法,把Cors(跨域)中间件实例,注入到.Net(Core)6框架默认容器中。

    //Cors(跨域)操作是如果“appsettings.json”文件中配置的所有域名中,至少有1个与“vue/uni-app”前台项目相匹配域名时,则“vue/uni-app”前端项目就从当前后台项目中获取相关数据,从而实现页面的渲染显示。

    builder.Services.AddCors(options =>

    {

        //限定“appsettings.json”文件中配置的所有域名中,至少有1个与“vue/uni-app”前台项目相匹配域名,才能上“vue/uni-app”前端项目就从当前后台项目中获取相关数据,从而实现页面的渲染显示。

        if (!Convert.ToBoolean(builder.Configuration["Cors:EnableAllIPs"]))

        {

            options.AddPolicy(builder.Configuration["Cors:PolicyName"],

                policy =>

                {

                    policy

                    .WithOrigins(builder.Configuration["Cors:IPs"].Split(','))

                    .AllowAnyHeader()

                    .AllowAnyMethod();

                });

        }

        else

        {

            //不做限定,“vue”前台项目能够直接从当前后台项目中获取相关数据,从而实现页面的渲染显示

            options.AddPolicy(builder.Configuration["Cors:PolicyName"],

                policy =>

                {

                    policy

                    .SetIsOriginAllowed((host) => true)

                    .AllowAnyMethod()

                    .AllowAnyHeader()

                    .AllowCredentials();

                });

        }

    });

    var app = builder.Build();

    //把自定义管道中间中集成到.Net(Core)框架内置管道中,解决在由Hbuilder创建的前端Xuni-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();

    if (app.Environment.IsDevelopment())

    {

        app.UseSwagger();

        app.UseSwaggerUI();

    }

    app.UseHttpsRedirection();

    app.UseAuthorization();

    //把Cors(跨域)限制中间件管道中间中集成到.Net(Core)框架内置管道中,解决在由Hbuilder创建的前端Xuni-app项目(Cors)访问当前后端项目时,浏览器或App中会出现异常信息:

    //   “' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.”。

    app.UseCors(app.Configuration["Cors:PolicyName"]);

    app.MapControllers();

    app.Run();

    3控制器实现

    3.1 ResponseModel

    /// name="T">泛型类型实例(这里特指:1个指定实体的类型实例)。

        ///

        /// 【应答模型--纪录】

        ///

        /// 摘要:

        ///     该模型纪录以泛型形式,对指定的实体所有实例及其执行状态的数据进行储存,为客户端页面的渲染提供数据支撑。

        ///

        ///

        public record ResponseModel<T>

        {

            #region 属性

            ///

            /// 【状态】

            ///

            /// 摘要:

            ///     获取/设置指定控制器行方法的执行结果状态码的整型值,默认值:200(执行成功状态)。

            ///

            ///

            public int Status { get; set; } = 200;

            ///

            /// 【成功?】

            ///

            /// 摘要:

            ///     获取/设置1个值false(默认值,执行失败)/true(执行成功),该值指示指定控制器行方法的执行结果状态。

            ///

            ///

            public bool Success { get; set; } = false;

            ///

            /// 【信息】

            ///

            /// 摘要:

            ///     获取/设置指定控制器行方法的执行结果信息。

            ///

            ///

            public string Message { get; set; } = "";

            ///

            /// 【应答列表】

            ///

            /// 摘要:

            ///     获取/设置列表实例,该实例用于存储指定实体中的所有实例。

            ///

            ///

            public List ResponseList { get; set; }

            #endregion

        }

    3.2 UserController

    using Microsoft.AspNetCore.Mvc;

    using Microsoft.EntityFrameworkCore;

    using Web.Data;

    using Web.Domain.Users;

    using Web.Models;

    namespace Web.Controllers

    {

        ///

        /// 用户控制器

        ///

        [Route("[controller]/[action]")]

        [ApiController]

        public class UserController : Controller

        {

            #region 注入变量--拷贝构造方法

            ///

            /// 【EFCore上下文实例】

            ///

            ///

            /// 摘要:

            ///     声明角色实体的数据库设置实例, 该实例通过EFCore数据交换中间件实现当前程序与指定数据库之间的CURD操作。

            ///

            private readonly EFCoreContext _context;

            /// name="context">模型生成器实例,用于把当前程序中实体和属性所定义的约束规则,映射到数据库指定表及其字段上。

            ///

            /// 【拷贝构造方法】

            ///

            ///

            /// 摘要:

            ///    基类构造通过该构造方法中的参数实例,连接到指定数据库(SQL Server)数据库软件中数据库。

            ///

            public UserController(EFCoreContext context)

            {

                _context = context;

            }

            #endregion

            ///

            /// 【获取所有用户】

            ///

            ///

            /// 摘要:

            ///     该方法以异步方式,获取用户表中的所有用户实例,并把所有用户实例及其操作结果存储到消息模型实例中,为页面的渲染显示提供数据支撑。

            ///

            ///

            /// 返回:

            ///     消息模型实例,为页面的渲染显示提供数据支撑。

            ///

            [HttpGet]

            public async Task> UserList()

            {

                List _userList = await _context.UserDbSet.ToListAsync();

                return new ResponseModel()

                {

                    Message = "获取成功",

                    Success = true,

                    ResponseList = _userList,

                };

            }

            ///

            /// 【获取所有用户--POST】

            ///

            ///

            /// 摘要:

            ///     该方法以异步方式,获取用户表中的所有用户实例,并把所有用户实例及其操作结果存储到消息模型实例中,为页面的渲染显示提供数据支撑。

            ///

            ///

            /// 返回:

            ///     消息模型实例,为页面的渲染显示提供数据支撑。

            ///

            [HttpPost]

            public async Task> UserListPost()

            {

                List _userList = await _context.UserDbSet.ToListAsync();

                return new ResponseModel()

                {

                    Message = "获取成功",

                    Success = true,

                    ResponseList = _userList,

                };

            }

        }

    }

    对以上功能更为具体实现和注释见:221102_01SecondPracticeServer(模拟器、真机对后端数据的获取)。

  • 相关阅读:
    leetCode 45.跳跃游戏 II 贪心算法
    mysql8.0笔记
    SpringBoot自动装配原理分析
    记一次频繁fullgc排查到解决全流程复盘
    leetcode 322. Coin Change 零钱兑换(中等)
    氨基NH2/羧酸COOH/马来酰亚胺MAL修饰CdTe/CdS量子点
    35 | find方式的使用
    算法 杨辉三角求解 java打印杨辉三角 多路递归打印杨辉三角 递归优化杨辉三角 记忆法优化递归 帕斯卡三角形 算法(十二)
    电力行业首个自主可控的大模型发布了!百度飞桨、文心大模型提供支持
    【522. 最长特殊序列 II】
  • 原文地址:https://blog.csdn.net/zhoujian_911/article/details/127666570