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

1 准备工作

1.2 User

namespace Web.Domain.Users

{

    /// <summary>

    /// 【用户--类】

    /// <remarks>

    /// 摘要:

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

    /// </remarks>

    /// </summary>

    public class User

    {

        /// <summary>

        /// 【编号】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public long Id { get; set; }

        /// <summary>

        /// 【用户名】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public string Name { get; set; }

        /// <summary>

        /// 【密码】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public string Password { get; set; }

        /// <summary>

        /// 【已经删除?】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public bool? IsEnable { get; set; }

        /// <summary>

        /// 【创建时间】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public DateTime CreateTime { get; set; }

    }

}

1.2 EFCoreContext

using Microsoft.EntityFrameworkCore;

using Web.Domain.Users;

namespace Web.Data

{

    /// <summary>

    /// 【EFCore上下文】

    /// <remarks>

    /// 摘要:

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

    /// </remarks>

    /// </summary>

    public class EFCoreContext : DbContext

    {

        #region 拷贝构造方法

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public EFCoreContext(DbContextOptions<EFCoreContext> 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 属性

        /// <summary>

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

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public DbSet<User> UserDbSet { get; set; }

        #endregion

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

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

        /// <summary>

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

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        protected override void OnModelCreating(ModelBuilder builder)

        {

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

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

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

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

            builder.Entity<User>().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

{

    /// <summary>

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

    /// </summary>

    /// <remarks>

    /// 摘要:

    ///     该管道中间件类主要为了解决在由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.”。

    /// </remarks>

    public class CorsMiddleware

    {

        #region 拷贝构造方法

        /// <summary>

        /// 【下1个】

        /// </summary>

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        private readonly RequestDelegate _next;

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

        /// <summary>

        /// 【拷贝构造方法】

        /// </summary>

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        public CorsMiddleware(RequestDelegate next)

        {

            _next = next;

        }

        #endregion

        #region 方法

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

        /// <summary>

        /// 【调用】

        /// </summary>

        /// <remarks>

        /// 摘要:

        ///    通过该方法向.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.”。

        /// </remarks>

        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<EFCoreContext>

    //通过“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”文件中启用“<GenerateDocumentationFile>true</GenerateDocumentationFile>”配置,下面语句会出现逻辑异常。

    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<CorsMiddleware>();

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<T>

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

    /// <summary>

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

    /// <remarks>

    /// 摘要:

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

    /// </remarks>

    /// </summary>

    public record ResponseModel<T>

    {

        #region 属性

        /// <summary>

        /// 【状态】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

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

        /// <summary>

        /// 【成功?】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

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

        /// <summary>

        /// 【信息】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

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

        /// <summary>

        /// 【应答列表】

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// </summary>

        public List<T> 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

{

    /// <summary>

    /// 用户控制器

    /// </summary>

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

    [ApiController]

    public class UserController : Controller

    {

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

        /// <summary>

        /// 【EFCore上下文实例】

        /// </summary>

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        private readonly EFCoreContext _context;

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

        /// <summary>

        /// 【拷贝构造方法】

        /// </summary>

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        public UserController(EFCoreContext context)

        {

            _context = context;

        }

        #endregion

        /// <summary>

        /// 【获取所有用户】

        /// </summary>

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// <returns>

        /// 返回:

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

        /// </returns>

        [HttpGet]

        public async Task<ResponseModel<User>> UserList()

        {

            List<User> _userList = await _context.UserDbSet.ToListAsync();

            return new ResponseModel<User>()

            {

                Message = "获取成功",

                Success = true,

                ResponseList = _userList,

            };

        }

        /// <summary>

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

        /// </summary>

        /// <remarks>

        /// 摘要:

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

        /// </remarks>

        /// <returns>

        /// 返回:

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

        /// </returns>

        [HttpPost]

        public async Task<ResponseModel<User>> UserListPost()

        {

            List<User> _userList = await _context.UserDbSet.ToListAsync();

            return new ResponseModel<User>()

            {

                Message = "获取成功",

                Success = true,

                ResponseList = _userList,

            };

        }

    }

}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值