.Net初学 创建一个巨简单的.Net7 WebApi后端框架

02-27 1859阅读 0评论

工具

visual studio 2022

以下简称vs    Visual Studio安装指南_visual studio安装教程_技术人小柒的博客-CSDN博客

.Net初学 创建一个巨简单的.Net7 WebApi后端框架,.Net初学 创建一个巨简单的.Net7 WebApi后端框架,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,我们,注册,访问,第1张
(图片来源网络,侵删)
sqlserver 2022

以下简称mssql        SQL Server2022 Express和SSMS下载安装教程(超详细) (baidu.com)

redis

Redis下载安装图文教程(Windows版_超详细)_windows redis下载_Leeway啊樺的博客-CSDN博客

PDman

数据库设计,可以直接生成脚本,power design平替 PDMan数据库建模

创建项目

创建解决方案

打开vs点创建新项目,没什么可说的,有手就行,下一步

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

.Net初学 创建一个巨简单的.Net7 WebApi后端框架,.Net初学 创建一个巨简单的.Net7 WebApi后端框架,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,我们,注册,访问,第3张
(图片来源网络,侵删)

 搜索框输入core,因为.net和.net core又在一起了。选择asp.net core web api,下一步

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

 项目名称最好写的规范一点,一般都是   [公司名称.项目名称.net项目名称]和一些天花乱坠的标识,解决方案和项目放在同一目录去掉,很烦,项目总体的目录架构不太好看,然后把解决方案名称最好改掉,因为解决方案是项目的父级,最好是比项目名少一个节点。下一步

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

 最后一步选择.net7版本,https勾掉,安全机制影响开发效率,有需要的加上就好。点创建。

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

.Net初学 创建一个巨简单的.Net7 WebApi后端框架,.Net初学 创建一个巨简单的.Net7 WebApi后端框架,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,我们,注册,访问,第7张
(图片来源网络,侵删)

完成,成功创建一个api项目,直接可以跑,把docker换成iis express

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

跑起来看到是core内置的swagger,方便测试服务接口用   try it out ==> Excute ,200就是成功。

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

项目层级

根据项目实际需要分层,我这里分了七层:(懒得重新创建了,直接用之前的项目截图)

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

从上到下分别是:

1.API接口层, 用于实现各种场景需求的服务,主要存放controller控制器

2.Cache缓存

3.Common辅助类层,存放一些公用的方法和帮助类

4.DAL数据访问层,主要一些基本的操作数据库的方法。

5.IRepository抽象层,因为我们用到了ioc容器,所以保存了一些控制反转的机制,用于存放抽象类

6.Model实体层,存放数据实体类,包括实现特定需求业务的实体,枚举,接口响应数据类型,调用其他接口的请求类型

7.Repository 业务逻辑层,需要实现上面的抽象层,达到控制反转的效果,同时相当于三层架构中的BLL层级,实现各项实际业务。

根据实际场景缩减或扩展。

实现登录功能

数据结构

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

表结构仅供参考,根据实际需求创建 。

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

这里创建好了直接生成脚本去执行

实体创建

然后在项目的model层创建一个entity文件夹,创建一个用户的实体类

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

内容:

using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace Project.TM.WCore.Model.Entity.JCXX
{
    /// 
    /// 用户信息表
    /// 
    [Table("T_JCXX_User")]
    public class UserEntity
    {
        /// 
        /// ID
        /// 
        [Dapper.Key]
        public int Id { get; set; }
        /// 
        /// 名称
        /// 
        public string? Name { get; set; }
        /// 
        /// 用户名
        /// 
        public string? UserName { get; set; }
        /// 
        /// 密码
        /// 
        public string? Password { get; set; }
        /// 
        /// 性别
        /// 
        public bool Sex { get; set; }
        /// 
        /// 年龄
        /// 
        public int Age { get; set; }
        /// 
        /// 生日
        /// 
        public string? Birthday { get; set; }
        /// 
        /// 联系方式
        /// 
        public string? Contact { get; set; }
        /// 
        /// 职称
        /// 
        public string? Occupation { get; set; }
        /// 
        /// 部门
        /// 
        public string? Department { get; set; }
        /// 
        /// 邮箱
        /// 
        public string? Email { get; set; }
        /// 
        /// 居住地
        /// 
        public string? City { get; set; }
        /// 
        /// 公司
        /// 
        public string? Company { get; set; }
        /// 
        /// 头像
        /// 
        public string? Avatar { get; set; }
        /// 
        /// 标签
        /// 
        public int Tag { get; set; }
        /// 
        /// 个人介绍
        /// 
        public string? Introductory { get; set; }
        /// 
        /// 是否启用
        /// 
        public bool Isuse { get; set; }
        /// 
        /// 部门/组织/角色
        /// 
        public string[]? role { get; set; }
        /// 
        /// 创建人
        /// 
        public string? Creator { get; set; }
        /// 
        /// 创建时间
        /// 
        public DateTime Createtime { get; set; }
        /// 
        /// 更新人
        /// 
        public string? Updator { get; set; }
        /// 
        /// 更新时间
        /// 
        public DateTime Updatetime { get; set; }
    }
}
创建dapperhelper帮助类

 这里我们用到dapperDapper简介 - 非法关键字 - 博客园 (cnblogs.com)

 ORM框架简介_orm框架是什么意思_Courage-Hu的博客-CSDN博客

 实现对数据库的连接和增删改查基本方法

在common层创建一个DapperHelper类

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

 nuget:

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

 直接把数据库连接串替换成你自己的,内容:

using System.Data.SqlClient;
using System.Data;
using Dapper;
namespace Project.TM.WCore.Common
{
    /// 
    /// Dapper帮助类
    /// 
    public class DapperHelper
    {
        #region 连接
        /// 
        /// 数据库连接串
        /// 
        public static string ConnectionString = string.Empty;
        /// 
        /// 注册一个连接事件
        /// 
        public static IDbConnection? connection = null;
        /// 
        /// 构造函数
        /// 
        public DapperHelper()
        {
            //ConnectionString = ConnectionProvider.GetConnection();
            ConnectionString = SettingProvider.GetConnection();
            //ConnectionString = ConfigurationManager.ConnectionStrings["SqlConnetion"].ConnectionString;
        }
        /// 
        /// 获得conn对象
        /// 
        /// 
        public IDbConnection GetConn()
        {
            return new SqlConnection(ConnectionString);
        }
        /// 
        /// 打开conn
        /// 
        /// 
        public void OpenConn(IDbConnection conn)
        {
            conn.Open();
        }
        /// 
        /// 销毁conn
        /// 
        /// 
        public void DisposeConn(IDbConnection conn)
        {
            conn.Dispose();
            conn.Close();
        }
        #endregion
        #region 业务类
        /// 
        /// 查询.
        /// 
        /// 实体类型.
        /// sql执行语句.
        /// 泛型类.
        public static List Query(string sql)
             where T : class
        {
            using (connection = new SqlConnection(ConnectionString))
            {
                return connection.Query(sql).ToList();
            }
        }
        /// 
        /// 查询单条记录
        /// 
        /// 
        /// 
        /// new{...}
        /// 
        public T ExecuteQuery(string sql, object? obj = null)
        {
            T result;
            using (connection = new SqlConnection(ConnectionString))
            {
                result = connection.QueryFirstOrDefault(sql, obj);
            }
            return result;
        }
        /// 
        /// 查询多条记录
        /// 
        /// 
        /// 
        /// new{...}
        /// 
        public IEnumerable ExecuteQuerys(string sql, object? obj = null)
        {
            IEnumerable result;
            using (connection = new SqlConnection(ConnectionString))
            {
                result = connection.Query(sql, obj);
            }
            return result;
        }
        /// 
        /// 查询指定数据.
        /// 
        /// 实体类型.
        /// sql执行语句.
        /// 泛型类.
        /// 类.
        public static T? Query(string sql, T t)
             where T : class
        {
            using (connection = new SqlConnection(ConnectionString))
            {
                return connection.Query(sql, t).SingleOrDefault();
            }
        }
        /// 
        /// 查询的in操作.
        /// 
        /// 实体类型.
        /// sql执行语句.
        /// 泛型类.
        public static List Query(string sql, int[] ids)
            where T : class
        {
            using (connection = new SqlConnection(ConnectionString))
            {
                return connection.Query(sql, new { ids }).ToList();
            }
        }
        /// 
        /// 增删改
        /// 
        /// 
        /// 
        /// 
        /// 
        public int ExecuteNonQuery(string sql, T obj)
        {
            int result = 0;
            try
            {
                using (connection = new SqlConnection(ConnectionString))
                {
                    result = connection.Execute(sql, obj);
                }
            }
            catch { }
            return result;
        }
        /// 
        /// 添加
        /// 
        /// 实体类型.
        /// sql执行语句.
        /// 传入实体类型.
        /// int.
        public static int Add(string sql)
            where T : class
        {
            using (connection = new SqlConnection(ConnectionString))
            {
                return connection.Execute(sql);
            }
        }
        /// 
        /// 新增后获取id
        /// 
        /// 
        /// 
        /// 
        /// 
        public static int AddResultId(string sql)
        {
            int Id = 0;
            using (connection = new SqlConnection(ConnectionString))
            {
                using (SqlCommand command = new SqlCommand(sql, connection as SqlConnection))
                {
                    connection.Open();
                    Id = Convert.ToInt32(command.ExecuteScalar());
                    connection.Close();
                }
            }
            return Id;
        }
        /// 
        /// 多语句操作.
        /// 
        /// 实体类型.
        /// sql执行语句.
        public static void QueryMultiple(string sql)
        {
            using (connection = new SqlConnection(ConnectionString))
            {
                var multiReader = connection.QueryMultiple(sql);
                multiReader.Dispose();
            }
        }
        #endregion
        #region 事务
        /// 
        /// 开启事务
        /// 
        /// 
        /// 
        public IDbTransaction BeginTransaction(IDbConnection conn)
        {
            return conn.BeginTransaction();
        }
        /// 
        /// 提交事务
        /// 
        /// 
        /// 
        public void Commit(IDbTransaction tran)
        {
            tran.Commit();
        }
        /// 
        /// 回滚事务
        /// 
        /// 
        /// 
        public void Rollback(IDbTransaction tran)
        {
            tran.Rollback();//回滚
        }
        /// 
        /// 销毁事务
        /// 
        /// 
        /// 
        public void Dispose(IDbTransaction tran)
        {
            tran.Dispose();//销毁
        }
        /// 
        /// 查询带事务
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public List? ExecuteQuerys(string sql, IDbTransaction tran)
        {
            try
            {
                return (List)connection.Query(sql, tran);
            }
            catch (Exception)
            {
                return null;
            }
        }
        /// 
        /// 使用事务查询多条记录
        /// 
        /// 
        /// 
        /// new{...}
        /// 
        public IEnumerable ExecuteQuerys(string sql, IDbTransaction tran, IDbConnection conn, object? obj = null)
        {
            IEnumerable result;
            result = conn.Query(sql, obj, tran);
            return result;
        }
        /// 
        /// 使用事务查询单条记录
        /// 
        /// 
        /// 
        /// new{...}
        /// 
        public T ExecuteQuery(string sql, IDbTransaction tran, IDbConnection conn, object? obj = null)
        {
            T result;
            result = conn.QueryFirstOrDefault(sql, obj, tran);
            return result;
        }
        /// 
        /// 增删改带事务
        /// 
        /// 
        /// 
        /// 
        public int ExecuteNonQuery(string sql, IDbConnection conn, IDbTransaction tran)
        {
            try
            {
                int count = conn.Execute(sql, transaction: tran);
                return count;
            }
            catch (Exception)
            {
                return 0;
            }
        }
        /// 
        /// 新增后获取id带事务
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public int AddResultId(string sql,IDbConnection conn,IDbTransaction tran)
        {
            try
            {
                return Convert.ToInt32(new SqlCommand(sql, conn as SqlConnection, tran as SqlTransaction).ExecuteScalar());
            }
            catch (Exception)
            {
                return 0;
            }
        }
        #endregion
        /// 
        /// 获取表名称
        /// 
        /// 
        public static string GetTable()
        {
            var tableAttribute = (System.ComponentModel.DataAnnotations.Schema.TableAttribute)typeof(T).GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.Schema.TableAttribute), true)[0];
            return tableAttribute.Name.ToString();
        }
    }
}
创建数据访问层和增删改查方法

这里创建了两个类上面是用户信息数据访问类,下面是数据访问层继承的基类

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

 这里用基类写一些通用方法,

1.方便业务逻辑层(bll)直接调用,减少代码量

using Project.TM.WCore.Common;
using Project.TM.WCore.Model.Entity.SPLC;
using Project.TM.WCore.Model.Struct;
using System.Data;
namespace Project.TM.WCore.DAL
{
    /// 
    /// dal基类
    /// 
    public abstract class IBasicsDal where T : class, new()
    {
        /// 
        /// dapper帮助类
        /// 
        public DapperHelper dapper;
        /// 
        /// sql拼接结构体
        /// 
        public SqlStruct sqlStruct;
        /// 
        /// 构造函数
        /// 
        protected IBasicsDal()
        {
            this.dapper = new DapperHelper();
        }
        #region 基类虚方法,基本操作方法
        /// 
        /// 分页查询
        /// 
        /// 
        /// 
        /// 
        public virtual Tuple GetPageList(int index, int size)
        {
            List list = dapper.ExecuteQuerys(DisposeSql()).ToList();
            return new Tuple(list.Skip((index - 1) * size).Take(size).ToList(), list.Count);
        }
        /// 
        /// 获取列表
        /// 
        /// 
        public virtual List GetList()
        {
            return dapper.ExecuteQuerys(DisposeSql()).ToList();
        }
        /// 
        /// 根据id获取列表
        /// 
        /// 
        /// 
        public virtual T GetListById(int id)
        {
            return dapper.ExecuteQuery(DisposeSql(id));
        }
        /// 
        /// 根据参数获取列表
        /// 
        /// 
        /// 
        public virtual List GetListByParam(Dictionary param)
        {
            return dapper.ExecuteQuerys(DisposeSql(0, param)).ToList();
        }
        /// 
        /// 新增
        /// 
        /// 
        /// 
        public virtual bool Add(T entity)
        {
            return Convert.ToBoolean(dapper.ExecuteNonQuery(DisposeSql(0, entity: entity), entity));
        }
        /// 
        /// 新增返回id
        /// 
        /// 
        /// 
        public virtual int AddResultId(T entity)
        {
            return DapperHelper.AddResultId(DisposeSql(0, entity: entity, type: 1));
        }
        /// 
        /// 删除
        /// 
        /// 
        /// 
        public virtual bool Delete(int id)
        {
            return dapper.ExecuteNonQuery(DisposeSql(id, type: 2), null) > 0 ? true : false;
        }
        /// 
        /// 批量删除
        /// 
        /// 
        /// 
        public virtual bool Deletes(dynamic[] ids)
        {
            return dapper.ExecuteNonQuery(DisposeSql(0, null, null, ids, 2), null) > 0 ? true : false;
        }
        /// 
        /// 编辑
        /// 
        /// 
        /// 
        public virtual bool Edit(T entity)
        {
            return dapper.ExecuteNonQuery(DisposeSql(0, null, entity, null, 3), entity) > 0 ? true : false;
        }
        /// 
        /// 批量新增
        /// 
        /// 
        /// 
        public virtual bool AddList(List entityList)
        {
            foreach (var item in entityList)
            {
                var result = SqlHelper.Add(item);
                if (!result) return result;
            }
            return true;
        }
        #endregion
        #region 事务操作
        /// 
        /// 新增并返回id带事务
        /// 
        /// 
        /// 
        /// 
        /// 
        public int TranAddResultId(string Sql, IDbConnection conn, IDbTransaction tran)
        {
            int id = dapper.AddResultId(Sql, conn, tran);//新增后获取id
            return id;
        }
        /// 
        /// 事务操作(未开启)
        /// 
        /// 1:新增,2:删除,3:修改
        /// 
        public bool TranEntity(Dictionary tranDic)
        {
            DapperHelper dapper = new DapperHelper();
            using (IDbConnection conn = dapper.GetConn())
            {
                IDbTransaction tran = null;
                try
                {
                    dapper.OpenConn(conn);//打开连接
                    tran = dapper.BeginTransaction(conn);//开启事务
                    //循环处理数据库操作
                    foreach (var item in tranDic)
                    {
                        switch (item.Key)
                        {
                            case 1://新增
                                dapper.ExecuteNonQuery(item.Value, conn, tran);
                                break;
                            case 2://删除
                                dapper.ExecuteNonQuery(item.Value, conn, tran);
                                break;
                            case 3://修改
                                dapper.ExecuteNonQuery(item.Value, conn, tran);
                                break;
                            default:
                                break;
                        }
                    }
                    dapper.Commit(tran);//提交事务
                    return true;
                }
                catch (Exception)//异常回滚
                {
                    dapper.Rollback(tran);
                    return false;
                }
                finally
                {
                    if (conn != null)
                    {
                        dapper.DisposeConn(conn);//销毁连接
                    }
                    if (tran != null)
                    {
                        dapper.Dispose(tran);//销毁事务
                    }
                }
            }
        }
        /// 
        /// 事务操作(已开启)
        /// 
        /// 1:新增,2:删除,3:修改
        /// 
        public bool TranEntity(Dictionary tranDic, IDbConnection conn, IDbTransaction tran)
        {
            if (conn == null || tran == null) return false;
            try
            {
                //循环处理数据库操作
                foreach (var item in tranDic)
                {
                    dapper.ExecuteNonQuery(item.Value, conn, tran);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        #endregion
        /// 
        /// 处理sql
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public string DisposeSql(int id = 0, Dictionary? param = null, T? entity = null, dynamic[]? ids = null, int type = 0)
        {
            sqlStruct = new SqlStruct();
            sqlStruct.Id = id;
            sqlStruct.Param = param;
            sqlStruct.Entity = entity;
            sqlStruct.Ids = ids;
            switch (type)
            {
                case 1:
                    sqlStruct.IsReturnId = true;
                    break;
                case 2:
                    sqlStruct.IsDelete = true;
                    break;
                case 3:
                    sqlStruct.IsUpdate = true;
                    break;
                default: break;
            }
            string sql = SqlHelper.GetSql(sqlStruct);
            return sql;
        }
    }
}

2.最后获取sql是因为dapper直接操作sql语句,每次都写sql我个人感觉比较麻烦,所以根据不同场景区分了一些通用的sql.在common创建SqlHelper:

using Project.TM.WCore.Model.Struct;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;
namespace Project.TM.WCore.Common
{
    /// 
    /// 获取操作数据sql
    /// 
    /// 
    public static class SqlHelper where T : class, new()
    {
        /// 
        /// 实体结构对象
        /// 
        static TableAttribute TableAttribute { get; set; }
        /// 
        /// sql拼接参数结构体
        /// 
        /// 
        /// 
        public static string GetSql(SqlStruct sqlStruct)
        {
            TableAttribute = (TableAttribute)typeof(T).GetCustomAttributes(typeof(TableAttribute), true)[0];
            string sql = string.Empty;
            if (sqlStruct.Id != 0 && !sqlStruct.IsDelete)//根据id查询
            {
                sql = GetById(sqlStruct);
            }
            else if (sqlStruct.Entity != null && !sqlStruct.IsReturnId && !sqlStruct.IsUpdate)//新增
            {
                sql = AddNew(sqlStruct);
            }
            else if (sqlStruct.Entity != null && sqlStruct.IsReturnId)//新增并返回id
            {
                sql = AddNewReturnId(sqlStruct);
            }
            else if ((sqlStruct.Id != 0 && sqlStruct.IsDelete))//删除
            {
                sql = Delete(sqlStruct);
            }
            else if (sqlStruct.Ids != null && sqlStruct.Ids.Count() > 0)//批删
            {
                sql = DeleteMany(sqlStruct);
            }
            else if (sqlStruct.Param?.Count > 0 && sqlStruct.IsDelete)//多条件删除
            {
                sql = DeleteParam(sqlStruct);
            }
            else if (sqlStruct.Entity != null && sqlStruct.IsUpdate)//更新
            {
                sql = Update(sqlStruct);
            }
            else if (sqlStruct.Param?.Count > 0&&!sqlStruct.IsDelete)//多条件查询
            {
                sql = QueryMany(sqlStruct);
            }
            else//直接查询
            {
                sql = $"select * from {TableAttribute.Name}";
            }
            return sql+";";
        }
        /// 
        /// 多条件查询
        /// 
        /// 
        /// 
        private static string QueryMany(SqlStruct sqlStruct)
        {
            string sql = $"SELECT * FROM {TableAttribute.Name}  WHERE 1=1";
            if (sqlStruct.Param?.FirstOrDefault(p => p.Key == true).Value != null)//直接匹配
            {
                foreach (var item in sqlStruct.Param.FirstOrDefault(p => p.Key == true).Value)
                {
                    sql += $" AND {item.Key} = '{item.Value}'";
                }
            }
            if (sqlStruct.Param?.FirstOrDefault(p => p.Key == false).Value != null)//模糊匹配
            {
                sql += " AND (";
                foreach (var item in sqlStruct.Param?.FirstOrDefault(p => p.Key == false).Value)
                {
                    sql += $" {item.Key} LIKE '%{item.Value}%' OR";
                }
                sql = sql.Substring(0, sql.Length - 2) + ")";
            }
            return sql;
        }
        /// 
        /// 更新
        /// 
        /// 
        /// 
        private static string Update(SqlStruct sqlStruct)
        {
            string sql = $"update {TableAttribute.Name} set";
            EntityManage entityManage = GetEntity(sqlStruct.Entity);
            foreach (var item in entityManage.keyValuePairs)
            {
                if (item.Key == "Createtime" || item.Key == "Creator" || item.Key == "Id")
                {
                    continue;
                }
                if (entityManage.ints.Contains(item.Key))
                {
                    sql += $" {item.Key} = {item.Value} ,";
                }
                else
                {
                    sql += $" {item.Key} = '{item.Value}' ,";
                }
            }
            sql = sql.Substring(0, sql.Length - 1);
            sql += $" where id = {entityManage.keyValuePairs.Where(p => p.Key == "Id").FirstOrDefault().Value}";
            return sql;
        }
        /// 
        /// 多条件删除
        /// 
        /// 
        /// 
        private static string DeleteParam(SqlStruct sqlStruct)
        {
            string sql = $"Delete From {TableAttribute.Name}  where 1 = 1";
            if (sqlStruct.Param?.FirstOrDefault(p => p.Key == true).Value != null)//直接匹配
            {
                foreach (var item in sqlStruct.Param.FirstOrDefault(p => p.Key == true).Value)
                {
                    sql += $" AND {item.Key} = '{item.Value}'";
                }
            }
            if (sqlStruct.Param?.FirstOrDefault(p => p.Key == false).Value != null)//模糊匹配
            {
                sql += " AND (";
                foreach (var item in sqlStruct.Param?.FirstOrDefault(p => p.Key == false).Value)
                {
                    sql += $" {item.Key} LIKE '%{item.Value}%' OR";
                }
                sql = sql.Substring(0, sql.Length - 2) + ")";
            }
            return sql;
        }
        /// 
        /// 批删
        /// 
        /// 
        /// 
        private static string DeleteMany(SqlStruct sqlStruct)
        {
            string sql = $"Delete {TableAttribute.Name}  where ";
            for (int i = 0; i  0)
            {
                for (int i = 0; i  

UserDal继承基类IbasicDal,这样逻辑层repository实例化访问层dal就能直接访问基类的方法

创建业务层并继承于抽象层

其实抽象层和逻辑层都是基于三层架构的业务逻辑层(BLL)扩展来的,因为我们用到控制反转,所以拆分为两层,浅谈控制反转(IoC)_米碎师兄的博客-CSDN博客

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

同样为抽象层(以下简称IR)和逻辑层(以下简称R)创建了基类,别问,问就是省事。

1.创建IR的基类IBasicsRepository
namespace Project.TM.WCore.IRepository
{
    /// 
    /// 接口抽象类
    /// 
    /// 
    public  interface IBasicsRepository
    {
        /// 
        /// 分页查
        /// 
        /// 
        /// 
        /// 
        dynamic? GetPageList(int index, int size);
        /// 
        /// 列表查
        /// 
        /// 
        dynamic? GetList();
        /// 
        /// 多条件查
        /// 
        /// 
        /// 
        dynamic? GetListByParam(Dictionary? param);
        /// 
        /// 根据id查询
        /// 
        /// 
        /// 
        dynamic? GetListById(int id);
        /// 
        /// 新增
        /// 
        /// 
        /// 
        bool Add(dynamic? entity);
        /// 
        /// 批增
        /// 
        /// 
        /// 
        bool AddList(dynamic? entityList);
        /// 
        /// 删除
        /// 
        /// 
        /// 
        bool Delete(int id);
        /// 
        /// 批删
        /// 
        /// 
        /// 
        bool Deletes(dynamic[]? ids);
        /// 
        /// 编辑
        /// 
        /// 
        /// 
        bool Edit(dynamic? entity);
    }
}
2.创建IUserRepository并继承自IBasicsRepository

一般没什么特殊业务这里是不用写代码的

using Project.TM.WCore.Model.Entity.JCXX;
namespace Project.TM.WCore.IRepository.JCXX
{
    /// 
    /// 用户抽象
    /// 
    public interface IUserRepository:IBasicsRepository
    {
        /// 
        /// 获取验证码
        /// 
        /// 
        /// 
        List RegisterGet(UserEntity entity);
    }
}
3.创建R层的基类BasicsRepository并继承IR层的IBasicsRepository并实现

这里为了方便不想每次都写增删改查,直接用反射根据方法名称调用dal

using Project.TM.WCore.IRepository;
using System.Reflection;
namespace Project.TM.WCore.Repository
{
    /// 
    /// 基类
    /// 
    public abstract class BasicsRepository: IBasicsRepository
    {
        /// 
        /// 参数
        /// 
        public Dictionary? param = null;
        /// 
        /// 当前操作dal对象
        /// 
        public dynamic? thisDal = null;
        /// 
        /// 新增
        /// 
        /// 
        /// 
        public virtual bool Add(dynamic? entity)
        {
            var thisDalType = thisDal?.GetType();
            MethodInfo method = thisDalType.GetMethod("Add");
            return method.Invoke(thisDal, new object[] { entity });
        }
        public virtual bool AddList(dynamic? entityList)
        {
            throw new NotImplementedException();
        }
        public virtual bool Delete(int id)
        {
            throw new NotImplementedException();
        }
        public virtual bool Deletes(dynamic[]? ids)
        {
            throw new NotImplementedException();
        }
        public virtual bool Edit(dynamic? entity)
        {
            throw new NotImplementedException();
        }
        /// 
        /// 查询
        /// 
        /// 
        public virtual dynamic GetList()
        {
            var thisDalType = thisDal?.GetType();
            MethodInfo method = thisDalType.GetMethod("GetList");
            return method.Invoke(thisDal, new object[] {  });
        }
        public virtual dynamic GetListById(int id)
        {
            throw new NotImplementedException();
        }
        /// 
        /// 条件查询
        /// 
        /// 
        /// 
        public virtual dynamic GetListByParam(Dictionary? param)
        {
            var thisDalType = thisDal?.GetType();
            MethodInfo method = thisDalType.GetMethod("GetListByParam");
            return method.Invoke(thisDal, new object[] { param });
        }
        public virtual dynamic GetPageList(int index, int size)
        {
            throw new NotImplementedException();
        }
    }
}
4.创建UserRepository并继承自BasicsRepository和IUserRepository

一样没什么特殊业务这里也不用写代码,但是构造函数要初始化一下dal

using Project.TM.WCore.DAL.JCXX;
using Project.TM.WCore.IRepository.JCXX;
using Project.TM.WCore.Model.Entity.JCXX;
namespace Project.TM.WCore.Repository.JCXX
{
    /// 
    /// 用户实现
    /// 
    public class UserRepository : BasicsRepository,IUserRepository
    {
        /// 
        /// 构造函数
        /// 
        public UserRepository()
        {
            thisDal = new UserDal();
        }
        /// 
        /// 注册获取信息
        /// 
        /// 
        /// 
        /// 
        public List RegisterGet(UserEntity entity)
        {
            return null;
        }
    }
}
创建Api控制器方法
1.同样创建一个基类BasicsController 和控制器LoginController

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

 2.基类存放一些公用的变量和方法
using Microsoft.AspNetCore.Mvc;
using Project.TM.WCore.IRepository.JCXX;
using System.Reflection;
namespace Project.TM.WCore.API.Controllers
{
    /// 
    /// Controller基类
    /// 
    [ApiController]
    [Route("api/[controller]/[action]")]
    public abstract class BasicsController: ControllerBase
    {
        //方案1:每个repository都在这里初始化,然后分布到对应的控制器去调用
        /// 
        /// 用户信息
        /// 
        public IUserRepository? _userRepository = null;
        //方案2:定义一个动态的存放repository的对象,每次调用接口给这个repository赋值
        /// 
        /// 当前控制器操作对象
        /// 
        public dynamic? thisRepostory = null;
        public object[]? methodParam;
        /// 
        /// 必选参数
        /// 
        public Dictionary? mustParam = null;
        /// 
        /// 可选参数
        /// 
        public Dictionary? minorParam = null;
        /// 
        /// 参数汇总
        /// 
        public Dictionary? param = null;
        /// 
        /// 多条件查询
        /// 
        /// 必选条件
        /// 可选条件
        /// 
        [ApiExplorerSettings(IgnoreApi = true)]
        public virtual dynamic GetListByParam(Dictionary param)
        {
            // 获取 MyClass 类型
            var thisRepostoryType = thisRepostory?.GetType();
            MethodInfo method = thisRepostoryType.GetMethod("GetListByParam");
            return method.Invoke(thisRepostory, new object[] { param });
        }
        /// 
        /// 动态方法操作
        /// 
        /// 
        /// 
        [ApiExplorerSettings(IgnoreApi = true)]
        public dynamic Method(string? MethodName)
        {
            var thisRepostoryType = thisRepostory?.GetType();
            MethodInfo method = thisRepostoryType.GetMethod(MethodName);
            var methodResult =  method.Invoke(thisRepostory, methodParam);
            methodParam = new object[] { };//清空参数
            return methodResult;
        }
    }
}

3.登录注册方法创建

 这块代码有点多,主要为了实现登录验证和Jwt验证JWT是什么_IBLiplus的博客-CSDN博客

1.依赖注入配置

1.nuget:

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

2.program 配置

        //Autofac依赖注入
        builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
        //注册依赖
        builder.Host.ConfigureContainer(containerBuilder =>
        {
            containerBuilder.RegisterType().As();
            //在这里写注入代码
            containerBuilder.RegisterType().As();//用户
            containerBuilder.RegisterType().As();//菜单
        });
2.Jwt配置

1.nuget

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

2.创建jwt实体

.Net初学 创建一个巨简单的.Net7 WebApi后端框架

namespace Project.TM.WCore.Model.Entity.PubLic
{
    public class JwtSettings
    {
        /// 
        /// 发行人
        /// 
        public string? Issuer { get; set; }
        /// 
        /// 受众人
        /// 
        public string? Audience { get; set; }
        /// 
        /// 加密用的key
        /// 
        public string? SecurityKey { get ; set; }
        /// 
        /// 时间
        /// 
        public double Expires { get; set; }
    }
}

2.program配置

 //jwt配置
 var jwtSection = configuration.GetSection("JwtConfig");
 JwtSettings jwtSettings = jwtSection.Get();
 //添加JWT服务
 builder.Services.Configure(jwtSection);
 JwtSettings settings = new JwtSettings();
 builder.Configuration.Bind("JwtConfig", settings);
 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
     .AddJwtBearer(options =>
 {
     options.TokenValidationParameters = new TokenValidationParameters()
     {
         //验证发行人
         ValidateIssuer = true,
         ValidIssuer = jwtSettings?.Issuer,
         验证受众人
         ValidateAudience = true,
         ValidAudience = jwtSettings?.Audience, // 受众
         //验证token声明周期
         ValidateLifetime = true,
         //验证签名
         ValidateIssuerSigningKey = true,
         IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings?.SecurityKey)),// 密钥
         // 是否要求Token的Claims中必须包含Expires
         RequireExpirationTime = true,
         // 允许服务器时间偏移量(默认300秒)
         // 即我们配置的过期时间加上这个允许偏移的时间值,才是真正过期的时间(过期时间 +偏移值)
         // 也可以设置为0,ClockSkew = TimeSpan.Zero
         ClockSkew = TimeSpan.FromSeconds(jwtSettings.Expires)
     };
     //鉴权验证
     options.Events = new JwtBearerEvents()
     {
         OnChallenge = context =>
         {
             context.HandleResponse();
             context.Response.StatusCode = StatusCodes.Status200OK;
             context.Response.ContentType = "application/json; charset=utf-8";
             string resp = JsonSerializer.Serialize(new { code = 401, message = "身份证认证失败" });
             context.Response.WriteAsync(resp);
             return Task.FromResult(0);
         },
         OnAuthenticationFailed = context =>
         {
             if (context.Exception.GetType() == typeof(SecurityTokenException))
             {
                 //JWT Token超时
                 context.Response.Headers.Add("act", "expired");
             }
             return Task.CompletedTask;
         }
     };
 });
3.编写控制器方法 
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using Project.TM.WCore.Cache;
using Project.TM.WCore.Common;
using Project.TM.WCore.IRepository.JCXX;
using Project.TM.WCore.Model.Entity.JCXX;
using Project.TM.WCore.Model.Entity.PubLic;
using Project.TM.WCore.Model.Enum;
using Project.TM.WCore.Model.Response;
using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
namespace Project.TM.WCore.API.Controllers.JCXX
{
    /// 
    /// 登录控制器
    /// 
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class LoginController : BasicsController
    {
        /// 
        /// 构造函数
        /// 
        /// 
        public LoginController(IUserRepository userRepository)
        {
            if (_userRepository != null) return;
            _userRepository = userRepository;
            thisRepostory = userRepository;
        }
        /// 
        /// 登录 允许匿名
        /// 
        /// 
        /// 
        [HttpPost]
        public IActionResult Login([FromBody] UserEntity entity)
        {
            JsonResult jsonResult;//返回结果
            if (string.IsNullOrWhiteSpace(entity.UserName) || string.IsNullOrWhiteSpace(entity.Password))
            {
                jsonResult = new JsonResult(new ReturnResponse { Code = ReturnCode.Fail, Message = "用户名或密码错误", Data = new UserResponse() });
                return jsonResult;
            }
            //查询用户信息
            minorParam = new Dictionary
            {
                {"UserName",entity.UserName },
                {"Name",entity.UserName },
                {"Contact",entity.UserName },
                {"Email",entity.UserName }
            };
            param = new Dictionary
            {
                { true,mustParam},
                { false,minorParam}
            };
            //var user = _userRepository.GetListByParam(null, minorParam);
            var user = GetListByParam(param);
            if (user == null || user?.Count  0)
            {
                return new JsonResult(new ReturnResponse { Code = ReturnCode.OK, Message = "当前手机号或邮箱已注册过,请更换" });
            }
            UserEntity newUserEntity = new UserEntity()
            {
                UserName = entity.Contact,
                Password = MD5Helper.Md5Encrypt32(entity.Password),
                Email = entity.Email,
                Contact = entity.Contact,
                Creator = "注册",
                Createtime = DateTime.Now,
                Updatetime = DateTime.Now,
                Isuse = true,
                Sex = true
            };
            bool result = _userRepository.Add(newUserEntity);
            return new JsonResult(new ReturnResponse { Code = ReturnCode.Created, Data = result });
        }
        /// 
        /// 发送验证码
        /// 
        /// 
        /// 
        [HttpPost]
        public IActionResult SendCode(UserEntity entity)
        {
            List userEntity = _userRepository.RegisterGet(entity);
            if (userEntity.Count > 0)
            {
                return new JsonResult(new ReturnResponse { Code = ReturnCode.OK, Message = "当前手机号或邮箱已注册过,请更换" });
            }
            int returncode = PhoneNo(entity.Contact);
            if (returncode != 0)
            {
                return new JsonResult(new ReturnResponse
                {
                    Code = ReturnCode.Created,
                    Data = new UserResponse
                    {
                        Captcha = returncode
                    }
                });
            }
            return new JsonResult(new ReturnResponse { Code = ReturnCode.Fail, Message = "验证码发送失败" });
        }
        /// 
        /// 实现发送验证码
        /// 
        /// 手机号
        /// 验证码
        [ApiExplorerSettings(IgnoreApi = true)]
        public static int PhoneNo(string phoneno)
        {
            string account = "C38910992";//查看用户名 登录用户中心->验证码通知短信>产品总览->API接口信息->APIID
            string password = "fbb1c64c267100f784276d9101bdce48"; //查看密码 登录用户中心->验证码通知短信>产品总览->API接口信息->APIKEY
            string mobile = phoneno;
            Random rad = new Random();
            int mobile_code = rad.Next(1000, 10000);
            string content = "您的验证码是:" + mobile_code + " 。请不要把验证码泄露给其他人。";
            string postStrTpl = "account={0}&password={1}&mobile={2}&content={3}";
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] postData = encoding.GetBytes(string.Format(postStrTpl, account, password, mobile, content));
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(AuthCodeProvider.GetPostUrl());
            myRequest.Method = "POST";
            myRequest.ContentType = "application/x-www-form-urlencoded";
            myRequest.ContentLength = postData.Length;
            Stream newStream = myRequest.GetRequestStream();
            newStream.Write(postData, 0, postData.Length);
            newStream.Flush();
            newStream.Close();
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
            if (myResponse.StatusCode == HttpStatusCode.OK)
            {
                StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
                //code状态返回值;msg查询结果描述
                string res = reader.ReadToEnd();
                int len1 = res.IndexOf("");
                int len2 = res.IndexOf("");
                string code = res.Substring((len2 + 6), (len1 - len2 - 6));
                int len3 = res.IndexOf("");
                int len4 = res.IndexOf("");
                string msg = res.Substring((len4 + 5), (len3 - len4 - 5));
                if (msg == "提交成功")
                {
                    return mobile_code;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }
        /// 
        /// 获取JWT.Token
        /// 
        /// 
        [ApiExplorerSettings(IgnoreApi = true)]
        private string GetToken(UserEntity entity)
        {
            AuthInfo authInfo = new AuthInfo()
            {
                UserName = entity.UserName,
                IsAdmin = true,
                ExpirationTime = 600
            };
            //密钥
            const string secret = "To Live is to change the world";
            //secret需要加密
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
            var token = encoder.Encode(authInfo, secret);
            //验证token是否为空
            if (string.IsNullOrWhiteSpace(token)) return "";
            return token;
        }
        [ApiExplorerSettings(IgnoreApi = true)]
        private string GetTokenNew(UserEntity entity)
        {
            var userData = new
            {
                Name = entity.UserName,
                CreatedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            };
            // 设置序列化首字母小写
            JsonSerializerOptions jso = new JsonSerializerOptions()
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            };
            string json = JsonSerializer.Serialize(userData, jso);
            var claims = new Claim[]
            {
                // 注意不能放入密码等敏感信息
                new Claim("user", json),
                // 也可以增加一些JWT预定义的claim
                new Claim(ClaimTypes.Name, "admin")
            };
            var jwtSet = SettingProvider.GetJwtSetting();
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSet?.SecurityKey));
            var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            DateTime now = DateTime.Now;
            DateTime exp = DateTime.Now.AddSeconds(jwtSet.Expires);
            var token = new JwtSecurityToken(
                issuer: jwtSet.Issuer,    // 发行人
                audience: jwtSet.Audience,//受众人
                                          //claims: claims,                 // 具体声明信息,注意不能放入敏感信息,这里客户端可以解密查看
                notBefore: now,                 // 有效期开始时间
                expires: exp,                   // 有效期结束时间
                signingCredentials: signingCredentials);
            string str = new JwtSecurityTokenHandler().WriteToken(token);
            return str;
        }
    }
}

完成测试

 成功

.Net初学 创建一个巨简单的.Net7 WebApi后端框架到这里框架的创建就完成了, 本人菜鸡,大佬轻喷,班门弄斧,还请海涵


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1859人围观)

还没有评论,来说两句吧...

目录[+]