| | |
| | | }); |
| | | } |
| | | } |
| | | //深拷贝 |
| | | function deepClone(source) { |
| | | if (typeof source !== 'object' || source == null) { |
| | | return source; |
| | | } |
| | | const target = Array.isArray(source) ? [] : {}; |
| | | for (const key in source) { |
| | | if (Object.prototype.hasOwnProperty.call(source, key)) { |
| | | if (typeof source[key] === 'object' && source[key] !== null) { |
| | | target[key] = deepClone(source[key]); |
| | | } else { |
| | | target[key] = source[key]; |
| | | } |
| | | } |
| | | } |
| | | return target; |
| | | } |
| | | /** |
| | | * 将表单赋值为指定的对象 |
| | | * @param {Object} data - 包含表单数据的对象 |
| | | * @param {String} formSelector - 表单的选择器,例如 '#myForm' 或 '.myForm' |
| | | */ |
| | | function setFormData(data, formSelector) { |
| | | var $form = $(formSelector); |
| | | |
| | | $.each(data, function(key, value) { |
| | | var $field = $form.find('[name=' + key + ']'); |
| | | |
| | | if ($field.length > 0) { |
| | | var fieldType = $field.attr('type'); |
| | | |
| | | switch (fieldType) { |
| | | case 'checkbox': |
| | | if (Array.isArray(value)) { |
| | | $field.each(function() { |
| | | $(this).prop('checked', value.includes($(this).val())); |
| | | }); |
| | | } else { |
| | | $field.prop('checked', value); |
| | | } |
| | | break; |
| | | case 'radio': |
| | | $field.filter('[value=' + value + ']').prop('checked', true); |
| | | break; |
| | | default: |
| | | $field.val(value); |
| | | break; |
| | | } |
| | | } |
| | | }); |
| | | } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | | namespace Utility.Entity |
| | | { |
| | | public class ApiResponse<T> |
| | | { |
| | | public int code { get; set; } |
| | | public string msg { get; set; } |
| | | public T data { get; set; } |
| | | |
| | | public ApiResponse(int code, string message, T data) |
| | | { |
| | | this.code = code; |
| | | this.msg = message; |
| | | this.data = data; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.Text; |
| | | |
| | | |
| | | namespace Utility |
| | | { |
| | | /// <summary> |
| | | /// 系统错误码 |
| | | /// </summary> |
| | | [ErrorCodeType] |
| | | [Description("系统错误码")] |
| | | public enum ErrorCodeEnum |
| | | { |
| | | /// <summary> |
| | | /// 验证码错误 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("验证码错误")] |
| | | D0008, |
| | | |
| | | /// <summary> |
| | | /// 账号不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("账号不存在")] |
| | | D0009, |
| | | |
| | | /// <summary> |
| | | /// 密码不正确 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("密码不正确")] |
| | | D1000, |
| | | |
| | | /// <summary> |
| | | /// 非法操作!禁止删除自己 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("非法操作,禁止删除自己")] |
| | | D1001, |
| | | |
| | | /// <summary> |
| | | /// 记录不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("记录不存在")] |
| | | D1002, |
| | | |
| | | /// <summary> |
| | | /// 账号已存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("账号已存在")] |
| | | D1003, |
| | | |
| | | /// <summary> |
| | | /// 旧密码不匹配 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("旧密码输入错误")] |
| | | D1004, |
| | | |
| | | /// <summary> |
| | | /// 测试数据禁止更改admin密码 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("测试数据禁止更改用户【admin】密码")] |
| | | D1005, |
| | | |
| | | /// <summary> |
| | | /// 数据已存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("数据已存在")] |
| | | D1006, |
| | | |
| | | /// <summary> |
| | | /// 数据不存在或含有关联引用,禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("数据不存在或含有关联引用,禁止删除")] |
| | | D1007, |
| | | |
| | | /// <summary> |
| | | /// 禁止为管理员分配角色 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止为管理员分配角色")] |
| | | D1008, |
| | | |
| | | /// <summary> |
| | | /// 重复数据或记录含有不存在数据 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("重复数据或记录含有不存在数据")] |
| | | D1009, |
| | | |
| | | /// <summary> |
| | | /// 禁止为超级管理员角色分配权限 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止为超级管理员角色分配权限")] |
| | | D1010, |
| | | |
| | | /// <summary> |
| | | /// 非法操作,未登录 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("非法操作,未登录")] |
| | | D1011, |
| | | |
| | | /// <summary> |
| | | /// Id不能为空 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("Id不能为空")] |
| | | D1012, |
| | | |
| | | /// <summary> |
| | | /// 所属机构不在自己的数据范围内 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("没有权限操作该数据")] |
| | | D1013, |
| | | |
| | | /// <summary> |
| | | /// 禁止删除超级管理员 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止删除超级管理员")] |
| | | D1014, |
| | | |
| | | /// <summary> |
| | | /// 禁止修改超级管理员状态 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止修改超级管理员状态")] |
| | | D1015, |
| | | |
| | | /// <summary> |
| | | /// 没有权限 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("没有权限")] |
| | | D1016, |
| | | |
| | | /// <summary> |
| | | /// 账号已冻结 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("账号已冻结")] |
| | | D1017, |
| | | |
| | | /// <summary> |
| | | /// 禁止删除管理员 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止删除管理员")] |
| | | D1018, |
| | | |
| | | /// <summary> |
| | | /// 禁止删除系统管理员角色 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止删除系统管理员角色")] |
| | | D1019, |
| | | |
| | | /// <summary> |
| | | /// 禁止修改系统管理员角色 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止修改系统管理员角色")] |
| | | D1020, |
| | | |
| | | /// <summary> |
| | | /// 禁止为系统管理员角色分配权限 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止为系统管理员角色分配权限")] |
| | | D1021, |
| | | |
| | | /// <summary> |
| | | /// 禁止为超级管理员分配角色 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止为超级管理员分配角色")] |
| | | D1022, |
| | | |
| | | /// <summary> |
| | | /// 禁止删除默认租户 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止删除默认租户")] |
| | | D1023, |
| | | |
| | | /// <summary> |
| | | /// 已将其他地方登录账号下线 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已将其他地方登录账号下线")] |
| | | D1024, |
| | | |
| | | /// <summary> |
| | | /// 父机构不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("父机构不存在")] |
| | | D2000, |
| | | |
| | | /// <summary> |
| | | /// 当前机构Id不能与父机构Id相同 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("当前机构Id不能与父机构Id相同")] |
| | | D2001, |
| | | |
| | | /// <summary> |
| | | /// 已有相同组织机构,编码或名称相同 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已有相同组织机构,编码或名称相同")] |
| | | D2002, |
| | | |
| | | /// <summary> |
| | | /// 没有权限操作机构 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("没有权限操作机构")] |
| | | D2003, |
| | | |
| | | /// <summary> |
| | | /// 该机构下有用户禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该机构下有用户禁止删除")] |
| | | D2004, |
| | | |
| | | /// <summary> |
| | | /// 附属机构下有用户禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("附属机构下有用户禁止删除")] |
| | | D2005, |
| | | |
| | | /// <summary> |
| | | /// 只能增加下级机构 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("只能增加下级机构")] |
| | | D2006, |
| | | |
| | | /// <summary> |
| | | /// 下级机构下有用户禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("下级机构下有用户禁止删除")] |
| | | D2007, |
| | | |
| | | /// <summary> |
| | | /// 租户默认机构禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("租户默认机构禁止删除")] |
| | | D2008, |
| | | |
| | | /// <summary> |
| | | /// 字典类型不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("字典类型不存在")] |
| | | D3000, |
| | | |
| | | /// <summary> |
| | | /// 字典类型已存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("字典类型已存在,名称或编码重复")] |
| | | D3001, |
| | | |
| | | /// <summary> |
| | | /// 字典类型下面有字典值禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("字典类型下面有字典值禁止删除")] |
| | | D3002, |
| | | |
| | | /// <summary> |
| | | /// 字典值已存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("字典值已存在,名称或编码重复")] |
| | | D3003, |
| | | |
| | | /// <summary> |
| | | /// 字典值不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("字典值不存在")] |
| | | D3004, |
| | | |
| | | /// <summary> |
| | | /// 字典状态错误 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("字典状态错误")] |
| | | D3005, |
| | | |
| | | /// <summary> |
| | | /// 菜单已存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("菜单已存在")] |
| | | D4000, |
| | | |
| | | /// <summary> |
| | | /// 路由地址为空 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("路由地址为空")] |
| | | D4001, |
| | | |
| | | /// <summary> |
| | | /// 打开方式为空 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("打开方式为空")] |
| | | D4002, |
| | | |
| | | /// <summary> |
| | | /// 权限标识格式为空 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("权限标识格式为空")] |
| | | D4003, |
| | | |
| | | /// <summary> |
| | | /// 权限标识格式错误 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("权限标识格式错误 如xxx:xxx")] |
| | | D4004, |
| | | |
| | | /// <summary> |
| | | /// 权限不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("权限不存在")] |
| | | D4005, |
| | | |
| | | /// <summary> |
| | | /// 父级菜单不能为当前节点,请重新选择父级菜单 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("父级菜单不能为当前节点,请重新选择父级菜单")] |
| | | D4006, |
| | | |
| | | /// <summary> |
| | | /// 不能移动根节点 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("不能移动根节点")] |
| | | D4007, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名或同编码应用 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名或同编码应用")] |
| | | D5000, |
| | | |
| | | /// <summary> |
| | | /// 默认激活系统只能有一个 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("默认激活系统只能有一个")] |
| | | D5001, |
| | | |
| | | /// <summary> |
| | | /// 该应用下有菜单禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该应用下有菜单禁止删除")] |
| | | D5002, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名或同编码应用 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名或同编码应用")] |
| | | D5003, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名或同编码职位 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名或同编码职位")] |
| | | D6000, |
| | | |
| | | /// <summary> |
| | | /// 该职位下有用户禁止删除 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该职位下有用户禁止删除")] |
| | | D6001, |
| | | |
| | | /// <summary> |
| | | /// 通知公告状态错误 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("通知公告状态错误")] |
| | | D7000, |
| | | |
| | | /// <summary> |
| | | /// 通知公告删除失败 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("通知公告删除失败")] |
| | | D7001, |
| | | |
| | | /// <summary> |
| | | /// 通知公告编辑失败 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("通知公告编辑失败,类型必须为草稿")] |
| | | D7002, |
| | | |
| | | /// <summary> |
| | | /// 通知公告操作失败,非发布者不能进行操作 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("通知公告操作失败,非发布者不能进行操作")] |
| | | D7003, |
| | | |
| | | /// <summary> |
| | | /// 文件不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("文件不存在")] |
| | | D8000, |
| | | |
| | | /// <summary> |
| | | /// 不允许的文件类型 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("不允许的文件类型")] |
| | | D8001, |
| | | |
| | | /// <summary> |
| | | /// 文件超过允许大小 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("文件超过允许大小")] |
| | | D8002, |
| | | |
| | | /// <summary> |
| | | /// 文件后缀错误 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("文件后缀错误")] |
| | | D8003, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名或同编码参数配置 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名或同编码参数配置")] |
| | | D9000, |
| | | |
| | | /// <summary> |
| | | /// 禁止删除系统参数 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止删除系统参数")] |
| | | D9001, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名任务调度 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名任务调度")] |
| | | D1100, |
| | | |
| | | /// <summary> |
| | | /// 任务调度不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("任务调度不存在")] |
| | | D1101, |
| | | |
| | | /// <summary> |
| | | /// 演示环境禁止修改数据 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("演示环境禁止修改数据")] |
| | | D1200, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名的租户 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名的租户")] |
| | | D1300, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名的租户管理员 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名的租户管理员")] |
| | | D1301, |
| | | |
| | | /// <summary> |
| | | /// 该表代码模板已经生成过 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该表代码模板已经生成过")] |
| | | D1400, |
| | | |
| | | /// <summary> |
| | | /// 该类型不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该类型不存在")] |
| | | D1501, |
| | | |
| | | /// <summary> |
| | | /// 该字段不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该字段不存在")] |
| | | D1502, |
| | | |
| | | /// <summary> |
| | | /// 该类型不是枚举类型 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该类型不是枚举类型")] |
| | | D1503, |
| | | |
| | | /// <summary> |
| | | /// 该实体不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("该实体不存在")] |
| | | D1504, |
| | | |
| | | /// <summary> |
| | | /// 父菜单不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("父菜单不存在")] |
| | | D1505, |
| | | |
| | | /// <summary> |
| | | /// 父资源不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("父资源不存在")] |
| | | D1600, |
| | | |
| | | /// <summary> |
| | | /// 当前资源Id不能与父资源Id相同 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("当前资源Id不能与父资源Id相同")] |
| | | D1601, |
| | | |
| | | /// <summary> |
| | | /// 已有相同编码或名称 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已有相同编码或名称")] |
| | | D1602, |
| | | |
| | | /// <summary> |
| | | /// 脚本代码不能为空 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("脚本代码不能为空")] |
| | | D1701, |
| | | |
| | | /// <summary> |
| | | /// 脚本代码中的作业类,需要定义 [JobDetail] 特性 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("脚本代码中的作业类,需要定义 [JobDetail] 特性")] |
| | | D1702, |
| | | |
| | | /// <summary> |
| | | /// 作业编号需要与脚本代码中的作业类 [JobDetail('jobId')] 一致 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("作业编号需要与脚本代码中的作业类 [JobDetail('jobId')] 一致")] |
| | | D1703, |
| | | |
| | | /// <summary> |
| | | /// 禁止修改作业编号 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止修改作业编号")] |
| | | D1704, |
| | | |
| | | /// <summary> |
| | | /// 已存在同名或同编码项目 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在同名或同编码项目")] |
| | | xg1000, |
| | | |
| | | /// <summary> |
| | | /// 已存在相同证件号码人员 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已存在相同证件号码人员")] |
| | | xg1001, |
| | | |
| | | /// <summary> |
| | | /// 检测数据不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("检测数据不存在")] |
| | | xg1002, |
| | | |
| | | /// <summary> |
| | | /// 请添加数据列 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("请添加数据列")] |
| | | db1000, |
| | | |
| | | /// <summary> |
| | | /// 数据表不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("数据表不存在")] |
| | | db1001, |
| | | |
| | | /// <summary> |
| | | /// 数据表不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("不允许添加相同字段名")] |
| | | db1002, |
| | | |
| | | /// <summary> |
| | | /// 父节点不存在 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("父节点不存在")] |
| | | R2000, |
| | | |
| | | /// <summary> |
| | | /// 当前节点Id不能与父节点Id相同 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("当前节点Id不能与父节点Id相同")] |
| | | R2001, |
| | | |
| | | /// <summary> |
| | | /// 已有相同编码或名称 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("已有相同编码或名称")] |
| | | R2002, |
| | | |
| | | /// <summary> |
| | | /// 默认租户状态禁止修改 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("默认租户状态禁止修改")] |
| | | Z1001, |
| | | |
| | | /// <summary> |
| | | /// 禁止创建此类型的数据库 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("禁止创建此类型的数据库")] |
| | | Z1002, |
| | | |
| | | /// <summary> |
| | | /// 租户已禁用 |
| | | /// </summary> |
| | | [ErrorCodeItemMetadata("租户已禁用")] |
| | | Z1003, |
| | | } |
| | | } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | public enum ResponseEnum |
| | | { |
| | | Sucess = 0, |
| | | |
| | | Fail = 1, |
| | | |
| | | Error = 2, |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Http; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Runtime.Serialization; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | public class AppFriendlyException : Exception |
| | | { |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | public AppFriendlyException() : base() |
| | | { |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="message"></param> |
| | | /// <param name="errorCode"></param> |
| | | public AppFriendlyException(string message, object errorCode) : base(message) |
| | | { |
| | | ErrorMessage = message; |
| | | ErrorCode = OriginErrorCode = errorCode; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="message"></param> |
| | | /// <param name="errorCode"></param> |
| | | /// <param name="innerException"></param> |
| | | public AppFriendlyException(string message, object errorCode, Exception innerException) : base(message, innerException) |
| | | { |
| | | ErrorMessage = message; |
| | | ErrorCode = OriginErrorCode = errorCode; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="info"></param> |
| | | /// <param name="context"></param> |
| | | public AppFriendlyException(SerializationInfo info, StreamingContext context) : base(info, context) |
| | | { |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 错误码 |
| | | /// </summary> |
| | | public object ErrorCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 错误码(没被复写过的 ErrorCode ) |
| | | /// </summary> |
| | | public object OriginErrorCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 错误消息(支持 Object 对象) |
| | | /// </summary> |
| | | public object ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 状态码 |
| | | /// </summary> |
| | | public int StatusCode { get; set; } = StatusCodes.Status500InternalServerError; |
| | | |
| | | /// <summary> |
| | | /// 是否是数据验证异常 |
| | | /// </summary> |
| | | public bool ValidationException { get; set; } = false; |
| | | |
| | | /// <summary> |
| | | /// 额外数据 |
| | | /// </summary> |
| | | public new object Data { get; set; } |
| | | } |
| | | } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | |
| | | /// <summary> |
| | | /// 异常元数据特性 |
| | | /// </summary> |
| | | [AttributeUsage(AttributeTargets.Field)] |
| | | public sealed class ErrorCodeItemMetadataAttribute : Attribute |
| | | { |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="errorMessage">错误消息</param> |
| | | /// <param name="args">格式化参数</param> |
| | | public ErrorCodeItemMetadataAttribute(string errorMessage, params object[] args) |
| | | { |
| | | ErrorMessage = errorMessage; |
| | | Args = args; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 错误消息 |
| | | /// </summary> |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 错误码 |
| | | /// </summary> |
| | | public object ErrorCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 格式化参数 |
| | | /// </summary> |
| | | public object[] Args { get; set; } |
| | | } |
| | | } |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | /// <summary> |
| | | /// 错误代码类型特性 |
| | | /// </summary> |
| | | [AttributeUsage(AttributeTargets.Enum)] |
| | | public sealed class ErrorCodeTypeAttribute : Attribute |
| | | { |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.DataProtection.KeyManagement; |
| | | using Microsoft.AspNetCore.Http; |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel.DataAnnotations; |
| | | using System.Linq; |
| | | using System.Reflection; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | /// <summary> |
| | | /// 抛异常静态类 |
| | | /// </summary> |
| | | public static class Oops |
| | | { |
| | | |
| | | /// <summary> |
| | | /// 错误代码类型 |
| | | /// </summary> |
| | | private static readonly IEnumerable<Type> ErrorCodeTypes; |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | static Oops() |
| | | { |
| | | ErrorCodeTypes = GetErrorCodeTypes(); |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出业务异常信息 |
| | | /// </summary> |
| | | /// <param name="errorMessage">异常消息</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Bah(string errorMessage, params object[] args) |
| | | { |
| | | var friendlyException = Oh(errorMessage, typeof(ValidationException), args); |
| | | friendlyException.StatusCode = StatusCodes.Status400BadRequest; |
| | | friendlyException.ValidationException = true; |
| | | return friendlyException; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出业务异常信息 |
| | | /// </summary> |
| | | /// <param name="errorCode">错误码</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Bah(object errorCode, params object[] args) |
| | | { |
| | | var friendlyException = Oh(errorCode, typeof(ValidationException), args); |
| | | friendlyException.StatusCode = StatusCodes.Status400BadRequest; |
| | | friendlyException.ValidationException = true; |
| | | return friendlyException; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出字符串异常 |
| | | /// </summary> |
| | | /// <param name="errorMessage">异常消息</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Oh(string errorMessage, params object[] args) |
| | | { |
| | | var friendlyException = new AppFriendlyException(errorMessage, default); |
| | | |
| | | friendlyException.StatusCode = StatusCodes.Status400BadRequest; |
| | | friendlyException.ValidationException = true; |
| | | return friendlyException; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出字符串异常 |
| | | /// </summary> |
| | | /// <param name="errorMessage">异常消息</param> |
| | | /// <param name="exceptionType">具体异常类型</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Oh(string errorMessage, Type exceptionType, params object[] args) |
| | | { |
| | | var exceptionMessage = string.Format(errorMessage, args); |
| | | return new AppFriendlyException(exceptionMessage, default, |
| | | Activator.CreateInstance(exceptionType, new object[] { exceptionMessage }) as Exception); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出字符串异常 |
| | | /// </summary> |
| | | /// <typeparam name="TException">具体异常类型</typeparam> |
| | | /// <param name="errorMessage">异常消息</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Oh<TException>(string errorMessage, params object[] args) |
| | | where TException : class |
| | | { |
| | | return Oh(errorMessage, typeof(TException), args); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出错误码异常 |
| | | /// </summary> |
| | | /// <param name="errorCode">错误码</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Oh(object errorCode, params object[] args) |
| | | { |
| | | var (ErrorCode, Message) = GetErrorCodeMessage(errorCode, args); |
| | | var friendlyException = new AppFriendlyException(Message, errorCode) { ErrorCode = ErrorCode }; |
| | | |
| | | friendlyException.StatusCode = StatusCodes.Status400BadRequest; |
| | | friendlyException.ValidationException = true; |
| | | return friendlyException; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出错误码异常 |
| | | /// </summary> |
| | | /// <param name="errorCode">错误码</param> |
| | | /// <param name="exceptionType">具体异常类型</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Oh(object errorCode, Type exceptionType, params object[] args) |
| | | { |
| | | var (ErrorCode, Message) = GetErrorCodeMessage(errorCode, args); |
| | | return new AppFriendlyException(Message, errorCode, |
| | | Activator.CreateInstance(exceptionType, new object[] { Message }) as Exception) |
| | | { ErrorCode = ErrorCode }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 抛出错误码异常 |
| | | /// </summary> |
| | | /// <typeparam name="TException">具体异常类型</typeparam> |
| | | /// <param name="errorCode">错误码</param> |
| | | /// <param name="args">String.Format 参数</param> |
| | | /// <returns>异常实例</returns> |
| | | public static AppFriendlyException Oh<TException>(object errorCode, params object[] args) |
| | | where TException : class |
| | | { |
| | | return Oh(errorCode, typeof(TException), args); |
| | | } |
| | | /// <summary> |
| | | /// 获取错误码消息 |
| | | /// </summary> |
| | | /// <param name="errorCode"></param> |
| | | /// <param name="args"></param> |
| | | /// <returns></returns> |
| | | private static (object ErrorCode, string Message) GetErrorCodeMessage(object errorCode, params object[] args) |
| | | { |
| | | string errorMessage = ""; |
| | | (errorCode, errorMessage) = HandleEnumErrorCode(errorCode); |
| | | return (errorCode, errorMessage); |
| | | } |
| | | /// <summary> |
| | | /// 处理枚举类型错误码 |
| | | /// </summary> |
| | | /// <param name="errorCode">错误码</param> |
| | | /// <returns></returns> |
| | | private static (object ErrorCode, string Message) HandleEnumErrorCode(object errorCode) |
| | | { |
| | | string errorMessage = ""; |
| | | // 获取类型 |
| | | var errorType = errorCode.GetType(); |
| | | |
| | | // 判断是否是内置枚举类型,如果是解析特性 |
| | | if (ErrorCodeTypes.Any(u => u == errorType)) |
| | | { |
| | | var fieldinfo = errorType.GetField(Enum.GetName(errorType, errorCode)); |
| | | if (fieldinfo.IsDefined(typeof(ErrorCodeItemMetadataAttribute), true)) |
| | | { |
| | | var info = GetErrorCodeItemInformation(fieldinfo); |
| | | errorCode = info.Key; |
| | | errorMessage = info.Value; |
| | | } |
| | | } |
| | | |
| | | return (errorCode, errorMessage); |
| | | } |
| | | /// <summary> |
| | | /// 获取错误代码信息 |
| | | /// </summary> |
| | | /// <param name="fieldInfo">字段对象</param> |
| | | /// <returns>(object key, object value)</returns> |
| | | private static (object Key, string Value) GetErrorCodeItemInformation(FieldInfo fieldInfo) |
| | | { |
| | | var errorCodeItemMetadata = fieldInfo.GetCustomAttribute<ErrorCodeItemMetadataAttribute>(); |
| | | return (errorCodeItemMetadata.ErrorCode ?? fieldInfo.Name, string.Format(errorCodeItemMetadata.ErrorMessage, errorCodeItemMetadata.Args)); |
| | | } |
| | | /// <summary> |
| | | /// 获取错误代码类型 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | private static IEnumerable<Type> GetErrorCodeTypes() |
| | | { |
| | | var typesWithErrorCodeTypeAttribute = AppDomain.CurrentDomain |
| | | .GetAssemblies() |
| | | .SelectMany(assembly => assembly.GetTypes()) |
| | | .Where(type => type.IsEnum && type.GetCustomAttribute<ErrorCodeTypeAttribute>() != null) |
| | | .ToList(); |
| | | return typesWithErrorCodeTypeAttribute; |
| | | |
| | | } |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using Microsoft.AspNetCore.Mvc.Filters; |
| | | using Newtonsoft.Json; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using Utility.Entity; |
| | | |
| | | namespace Utility |
| | | { |
| | | public class ApiResponseActionFilter: IAsyncActionFilter |
| | | { |
| | | public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) |
| | | { |
| | | // 在执行动作之前的逻辑 |
| | | var resultContext = await next(); // 执行动作方法并获取执行结果 |
| | | |
| | | // 在执行动作之后的逻辑 |
| | | if (resultContext.Result is ObjectResult objectResult) |
| | | { |
| | | var apiResponse = new ApiResponse<object>( |
| | | context.HttpContext.Response.StatusCode, |
| | | context.HttpContext.Response.StatusCode == 200 ? "请求成功" : "错误", |
| | | objectResult.Value |
| | | ); |
| | | |
| | | var json = JsonConvert.SerializeObject(apiResponse); |
| | | context.HttpContext.Response.ContentType = "application/json"; |
| | | context.HttpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(json); |
| | | |
| | | await context.HttpContext.Response.WriteAsync(json); |
| | | } |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Builder; |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Mvc.Controllers; |
| | | using Newtonsoft.Json; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using Utility.Entity; |
| | | |
| | | namespace Utility.Extension |
| | | { |
| | | public class ApiResponseMiddleware : IMiddleware |
| | | { |
| | | public ApiResponseMiddleware() |
| | | { |
| | | |
| | | } |
| | | |
| | | public async Task InvokeAsync(HttpContext context, RequestDelegate next) |
| | | { |
| | | if (ShouldApplyApiResponseMiddleware(context)) |
| | | { |
| | | // 捕获响应 |
| | | var originalBodyStream = context.Response.Body; |
| | | |
| | | using (var responseBody = new MemoryStream()) |
| | | { |
| | | context.Response.Body = responseBody; |
| | | |
| | | await next(context); |
| | | // 读取响应内容 |
| | | context.Response.Body.Seek(0, SeekOrigin.Begin); |
| | | var body = await new StreamReader(context.Response.Body).ReadToEndAsync(); |
| | | context.Response.Body.Seek(0, SeekOrigin.Begin); |
| | | |
| | | // 反序列化响应内容 |
| | | object data = null; |
| | | if (!string.IsNullOrEmpty(body)) |
| | | { |
| | | try |
| | | { |
| | | data = JsonConvert.DeserializeObject<object>(body); |
| | | } |
| | | catch (JsonException) |
| | | { |
| | | // 如果响应不是有效的JSON格式,直接将其作为字符串数据处理 |
| | | data = body; |
| | | } |
| | | } |
| | | |
| | | var apiResponse = new ApiResponse<object>( |
| | | code: context.Response.StatusCode == StatusCodes.Status200OK ? (int)ResponseEnum.Sucess : (int)ResponseEnum.Fail, |
| | | message: context.Response.StatusCode == StatusCodes.Status200OK ? "请求成功" : "", |
| | | data: data |
| | | ); |
| | | |
| | | var json = JsonConvert.SerializeObject(apiResponse); |
| | | context.Response.ContentType = "application/json"; |
| | | context.Response.ContentLength = Encoding.UTF8.GetByteCount(json); |
| | | |
| | | context.Response.Body = originalBodyStream; |
| | | await context.Response.WriteAsync(json); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | await next(context); |
| | | } |
| | | } |
| | | private bool ShouldApplyApiResponseMiddleware(HttpContext context) |
| | | { |
| | | // 获取当前处理请求的控制器信息 |
| | | var controllerActionDescriptor = context.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>(); |
| | | if (controllerActionDescriptor != null) |
| | | { |
| | | // 判断控制器是否带有 ResponseAttribute 特性 |
| | | return controllerActionDescriptor.ControllerTypeInfo.IsDefined(typeof(UnifyResponseAttribute), inherit: true); |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | public static class ApiResponse |
| | | { |
| | | public static void UseApiResponse(this IApplicationBuilder app) |
| | | { |
| | | app.UseMiddleware<ApiResponseMiddleware>(); |
| | | } |
| | | } |
| | | |
| | | public class UnifyResponseAttribute : Attribute |
| | | { |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Builder; |
| | | using System; |
| | | using Serilog; |
| | | using Serilog.Events; |
| | | using System.IO; |
| | | using System.Net; |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Http.Headers; |
| | | using System.Runtime.CompilerServices; |
| | | using Utility.Tools; |
| | | using System.Security.Claims; |
| | | using System.IdentityModel.Tokens.Jwt; |
| | | using System.Linq; |
| | | |
| | | namespace Utility |
| | | { |
| | | public static class ApplicationBuilderExtensions |
| | | { |
| | | /// <summary> |
| | | /// 添加使用Serilog请求日志 |
| | | /// </summary> |
| | | /// <param name="app"></param> |
| | | /// <returns></returns> |
| | | public static IApplicationBuilder UseSerilogRequestLogging(this IApplicationBuilder app) |
| | | { |
| | | //允许body重用 |
| | | app.Use(next => context => |
| | | { |
| | | context.Request.EnableBuffering(); |
| | | return next(context); |
| | | }); |
| | | |
| | | // 添加使用Serilog记录请求日志 |
| | | app.UseSerilogRequestLogging(options => |
| | | { |
| | | // 请求日志输出模板 |
| | | options.MessageTemplate = "\n {RequestMethod}={_RequestPath} | 状态={StatusCode} | 时间={Elapsed}ms | 操作人={_UserName} \n 请求内容={_RequestBody} \n 返回结果={_ResponseBody}"; |
| | | |
| | | // 发出调试级别事件而不是默认事件,将请求日志记录到:Debug日志 |
| | | options.GetLevel = (httpContext, elapsed, ex) => |
| | | { |
| | | var method = httpContext.Request.Method.ToLower(); |
| | | if (method == "options") |
| | | return LogEventLevel.Debug; |
| | | return LogEventLevel.Information; |
| | | }; |
| | | |
| | | // 将其他属性附加到请求完成事件,将请求属性附加可以在模板中使用 |
| | | options.EnrichDiagnosticContext = (diagnosticContext, httpContext) => |
| | | { |
| | | diagnosticContext.Set("_RequestPath", WebUtility.UrlDecode(httpContext.Request.Path + httpContext.Request.QueryString)); |
| | | var token = httpContext.Request.Headers["Token"].ToString(); |
| | | if (!string.IsNullOrEmpty(token)) |
| | | { |
| | | var handler = new JwtSecurityTokenHandler(); |
| | | var jwtToken = handler.ReadJwtToken(token); |
| | | var claim = jwtToken.Payload.Claims.FirstOrDefault(s => s.Type == "LoginName"); |
| | | //foreach (var claim in jwtToken.Payload.Claims) |
| | | //{ |
| | | // Console.WriteLine($"{claim.Type}: {claim.Value}"); |
| | | //} |
| | | if (claim != null) |
| | | diagnosticContext.Set("_UserName", claim.Value); |
| | | else |
| | | diagnosticContext.Set("_UserName", ""); |
| | | } |
| | | //请求body |
| | | var requestContent = "{}"; |
| | | var method = httpContext.Request.Method.ToLower(); |
| | | if (method == "post" || method == "put") |
| | | { |
| | | httpContext.Request.Body.Position = 0; |
| | | var requestReader = new StreamReader(httpContext.Request.Body); |
| | | if (requestReader.BaseStream.Length != 0) |
| | | requestContent = requestReader.ReadToEnd(); |
| | | } |
| | | diagnosticContext.Set("_RequestBody", requestContent); |
| | | diagnosticContext.Set("_Service", AppDomain.CurrentDomain.FriendlyName); |
| | | }; |
| | | }); |
| | | |
| | | return app; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | using Serilog.Events; |
| | | using Serilog; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | using Microsoft.Extensions.DependencyInjection; |
| | | using Microsoft.Extensions.Logging; |
| | | |
| | | namespace Wms |
| | | { |
| | | public static class LogExtends |
| | | { |
| | | //const string infoPath = "Logs/Information.log"; |
| | | //const string warnPath = "Logs/Warning.log"; |
| | | //const string errorPath = "Logs/Error.log"; |
| | | //const string fatalPath = "Logs/Fatal.log"; |
| | | //const string template = "时间: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}来源: {SourceContext}{NewLine}内容: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}"; |
| | | |
| | | //// 可以将日志输出到控制台、文件、数据库、ES等 |
| | | //public static void AddSerilog(this IServiceCollection c) |
| | | //{ |
| | | // Log.Logger = new LoggerConfiguration() |
| | | // .MinimumLevel.Information() |
| | | // .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 排除Dotnet自带的日志 |
| | | // .Enrich.FromLogContext() |
| | | // .WriteTo.Console(outputTemplate: template) |
| | | // .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Information).WriteTo.Async(congfig => congfig.File( |
| | | // infoPath, |
| | | // rollingInterval: RollingInterval.Day, |
| | | // fileSizeLimitBytes: 1024 * 1024 * 10, //默认1GB |
| | | // retainedFileCountLimit: 100, //保留最近多少个文件,默认31个 |
| | | // rollOnFileSizeLimit: true, //超过文件大小时,自动创建新文件 |
| | | // shared: true, |
| | | // outputTemplate: template) |
| | | // )) |
| | | |
| | | // .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Warning).WriteTo.Async(congfig => congfig.File( |
| | | // warnPath, |
| | | // rollingInterval: RollingInterval.Day, |
| | | // fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | // retainedFileCountLimit: 100, |
| | | // rollOnFileSizeLimit: true, |
| | | // shared: true, |
| | | // outputTemplate: template) |
| | | // )) |
| | | |
| | | // .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Error).WriteTo.Async(congfig => congfig.File( |
| | | // errorPath, |
| | | // rollingInterval: RollingInterval.Day, |
| | | // fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | // retainedFileCountLimit: 100, |
| | | // rollOnFileSizeLimit: true, |
| | | // shared: true, |
| | | // outputTemplate: template) |
| | | // )) |
| | | |
| | | // .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Fatal).WriteTo.Async(congfig => congfig.File( |
| | | // fatalPath, |
| | | // rollingInterval: RollingInterval.Day, |
| | | // fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | // retainedFileCountLimit: 100, |
| | | // rollOnFileSizeLimit: true, |
| | | // shared: true, |
| | | // outputTemplate: template) |
| | | // )).CreateLogger(); |
| | | |
| | | // // 注入到容器 |
| | | // c.AddLogging(opt => |
| | | // { |
| | | // opt.ClearProviders(); |
| | | // opt.AddSerilog(dispose: true); |
| | | // }); |
| | | //} |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using Microsoft.AspNetCore.Mvc.Filters; |
| | | using Newtonsoft.Json; |
| | | using Serilog; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | public class RequestAuditLogFilter : IResultFilter |
| | | { |
| | | private readonly IDiagnosticContext _diagnosticContext; |
| | | |
| | | public RequestAuditLogFilter(IDiagnosticContext diagnosticContext) { _diagnosticContext = diagnosticContext; } |
| | | |
| | | public void OnResultExecuted(ResultExecutedContext context) |
| | | { |
| | | var result = context.Result as ObjectResult; |
| | | var resultJson = JsonConvert.SerializeObject(result?.Value); |
| | | _diagnosticContext.Set("_ResponseBody", resultJson); |
| | | } |
| | | |
| | | public void OnResultExecuting(ResultExecutingContext context) { } |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.Extensions.Configuration; |
| | | using Microsoft.Extensions.DependencyInjection; |
| | | using Serilog.Events; |
| | | using Serilog; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | using Serilog.Sinks.SystemConsole.Themes; |
| | | using Serilog.Filters; |
| | | |
| | | namespace Utility |
| | | { |
| | | public static class ServiceCollectionExtensions |
| | | { |
| | | const string template = "时间: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}来源: {SourceContext}{NewLine}内容: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}"; |
| | | /// <summary> |
| | | /// 添加配置Serilog |
| | | /// </summary> |
| | | /// <param name="services"></param> |
| | | /// <param name="configuration"></param> |
| | | /// <returns></returns> |
| | | public static IServiceCollection AddConfigSerilog(this IServiceCollection services) |
| | | { |
| | | // 创建Serilog记录日志 |
| | | Log.Logger = new LoggerConfiguration() |
| | | .MinimumLevel.Information() |
| | | .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 排除Dotnet自带的日志 |
| | | //.MinimumLevel.Verbose() |
| | | //.MinimumLevel.Override("System", LogEventLevel.Debug) |
| | | //.MinimumLevel.Override("Microsoft", LogEventLevel.Debug) |
| | | //.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Error) |
| | | //.MinimumLevel.Override("Microsoft.AspNetCore.Cors.Infrastructure.CorsService", LogEventLevel.Error) |
| | | //.MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Error) |
| | | //.MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Error) |
| | | // 全部日志写入到Console |
| | | .WriteTo.Console() |
| | | .WriteTo.Async(c => c.Console( |
| | | theme: AnsiConsoleTheme.Literate, |
| | | outputTemplate: template)) |
| | | // Information日志写入到文件 |
| | | .WriteTo.Async(c => c.File( |
| | | path: "Logs/Information_.txt", |
| | | rollingInterval: RollingInterval.Day, |
| | | fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | retainedFileCountLimit: 100, |
| | | outputTemplate: template, |
| | | restrictedToMinimumLevel: LogEventLevel.Information)) |
| | | // Debug日志写入到文件 |
| | | //.WriteTo.Async(c => c.File( |
| | | // path: "Logs/Debug.txt", |
| | | // rollingInterval: RollingInterval.Day, |
| | | // fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | // retainedFileCountLimit: 100, |
| | | // outputTemplate: template, |
| | | // restrictedToMinimumLevel: LogEventLevel.Debug)) |
| | | // Warning日志写入到文件 |
| | | .WriteTo.Async(c => c.File( |
| | | path: "Logs/Warning_.txt", |
| | | rollingInterval: RollingInterval.Day, |
| | | fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | retainedFileCountLimit: 100, |
| | | outputTemplate: template, |
| | | restrictedToMinimumLevel: LogEventLevel.Warning)) |
| | | // Error日志写入到文件 |
| | | .WriteTo.Async(c => c.File( |
| | | path: "Logs/Error_.txt", |
| | | rollingInterval: RollingInterval.Day, |
| | | fileSizeLimitBytes: 1024 * 1024 * 10, |
| | | retainedFileCountLimit: 1000, |
| | | outputTemplate: template, |
| | | restrictedToMinimumLevel: LogEventLevel.Error)) |
| | | .CreateLogger(); |
| | | |
| | | services.AddSerilog(); |
| | | |
| | | return services; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Http; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using System.Threading.Tasks; |
| | | using System; |
| | | using System.Text.Json; |
| | | using Microsoft.AspNetCore.Builder; |
| | | using Microsoft.Extensions.Logging; |
| | | using Utility.Entity; |
| | | using Newtonsoft.Json; |
| | | |
| | | namespace Utility |
| | | { |
| | | public class CustomerExceptionMiddleware |
| | | { |
| | | private readonly RequestDelegate _next; |
| | | private readonly ILogger<CustomerExceptionMiddleware> _logger; |
| | | |
| | | public CustomerExceptionMiddleware(RequestDelegate next, ILogger<CustomerExceptionMiddleware> logger) |
| | | { |
| | | _next = next; |
| | | _logger = logger; |
| | | } |
| | | |
| | | public async Task Invoke(HttpContext context) |
| | | { |
| | | try |
| | | { |
| | | await _next(context); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogError(ex, ex.Message); |
| | | context.Response.ContentType = "application/json"; |
| | | context.Response.StatusCode = StatusCodes.Status500InternalServerError; |
| | | var result = "系统异常,请联系管理员"; |
| | | if (ex is AppFriendlyException) |
| | | result = ex.Message; |
| | | var apiResponse = new ApiResponse<object>( |
| | | code: (int)ResponseEnum.Error, |
| | | message: result, |
| | | data: result |
| | | ); |
| | | |
| | | await context.Response.WriteAsync(JsonConvert.SerializeObject(apiResponse)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 静态类 |
| | | /// </summary> |
| | | public static class ExceptionMiddlewareExtension |
| | | { |
| | | /// <summary> |
| | | /// 静态方法 |
| | | /// </summary> |
| | | /// <param name="app">要进行扩展的类型</param> |
| | | public static void UseExceptionMiddleware(this IApplicationBuilder app) |
| | | { |
| | | app.UseMiddleware(typeof(CustomerExceptionMiddleware)); |
| | | } |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | using Microsoft.AspNetCore.Mvc.Filters; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | |
| | | namespace Utility |
| | | { |
| | | public interface IUnitOfWork |
| | | { |
| | | /// <summary> |
| | | /// 开启工作单元处理 |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <param name="unitOfWork"></param> |
| | | void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork); |
| | | |
| | | /// <summary> |
| | | /// 提交工作单元处理 |
| | | /// </summary> |
| | | /// <param name="resultContext"></param> |
| | | /// <param name="unitOfWork"></param> |
| | | void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork); |
| | | |
| | | /// <summary> |
| | | /// 回滚工作单元处理 |
| | | /// </summary> |
| | | /// <param name="resultContext"></param> |
| | | /// <param name="unitOfWork"></param> |
| | | void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork); |
| | | |
| | | /// <summary> |
| | | /// 执行完毕(无论成功失败) |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <param name="resultContext"></param> |
| | | void OnCompleted(FilterContext context, FilterContext resultContext); |
| | | } |
| | | } |
New file |
| | |
| | | using Microsoft.AspNetCore.Mvc.Controllers; |
| | | using Microsoft.AspNetCore.Mvc.Filters; |
| | | using Microsoft.Extensions.DependencyInjection; |
| | | using Microsoft.Extensions.Logging; |
| | | using System; |
| | | using System.Reflection; |
| | | using System.Threading.Tasks; |
| | | using System.Transactions; |
| | | |
| | | namespace Utility |
| | | { |
| | | /// <summary> |
| | | /// 工作单元配置特性 |
| | | /// </summary> |
| | | [AttributeUsage(AttributeTargets.Method)] |
| | | public sealed class UnitOfWorkAttribute : Attribute, IAsyncActionFilter, IAsyncPageFilter, IOrderedFilter |
| | | { |
| | | /// <summary> |
| | | /// 确保事务可用 |
| | | /// <para>此方法为了解决静态类方式操作数据库的问题</para> |
| | | /// </summary> |
| | | public bool EnsureTransaction { get; set; } = false; |
| | | |
| | | /// <summary> |
| | | /// 是否使用分布式环境事务 |
| | | /// </summary> |
| | | public bool UseAmbientTransaction { get; set; } = false; |
| | | |
| | | /// <summary> |
| | | /// 分布式环境事务范围 |
| | | /// </summary> |
| | | /// <remarks><see cref="UseAmbientTransaction"/> 为 true 有效</remarks> |
| | | public TransactionScopeOption TransactionScope { get; set; } = TransactionScopeOption.Required; |
| | | |
| | | /// <summary> |
| | | /// 分布式环境事务隔离级别 |
| | | /// </summary> |
| | | /// <remarks><see cref="UseAmbientTransaction"/> 为 true 有效</remarks> |
| | | public IsolationLevel TransactionIsolationLevel { get; set; } = IsolationLevel.ReadCommitted; |
| | | |
| | | /// <summary> |
| | | /// 分布式环境事务超时时间 |
| | | /// </summary> |
| | | /// <remarks>单位秒</remarks> |
| | | public int TransactionTimeout { get; set; } = 0; |
| | | |
| | | /// <summary> |
| | | /// 支持分布式环境事务异步流 |
| | | /// </summary> |
| | | /// <remarks><see cref="UseAmbientTransaction"/> 为 true 有效</remarks> |
| | | public TransactionScopeAsyncFlowOption TransactionScopeAsyncFlow { get; set; } = TransactionScopeAsyncFlowOption.Enabled; |
| | | |
| | | /// <summary> |
| | | /// MiniProfiler 分类名 |
| | | /// </summary> |
| | | private const string MiniProfilerCategory = "unitOfWork"; |
| | | |
| | | /// <summary> |
| | | /// 过滤器排序 |
| | | /// </summary> |
| | | private const int FilterOrder = 9999; |
| | | |
| | | /// <summary> |
| | | /// 排序属性 |
| | | /// </summary> |
| | | public int Order => FilterOrder; |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | public UnitOfWorkAttribute() |
| | | { |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | /// <param name="ensureTransaction"></param> |
| | | public UnitOfWorkAttribute(bool ensureTransaction) |
| | | { |
| | | EnsureTransaction = ensureTransaction; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 拦截请求 |
| | | /// </summary> |
| | | /// <param name="context">动作方法上下文</param> |
| | | /// <param name="next">中间件委托</param> |
| | | /// <returns></returns> |
| | | public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) |
| | | { |
| | | // 获取动作方法描述器 |
| | | var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; |
| | | var method = actionDescriptor.MethodInfo; |
| | | |
| | | // 创建分布式环境事务 |
| | | (var transactionScope, var logger) = CreateTransactionScope(context); |
| | | |
| | | try |
| | | { |
| | | // 打印工作单元开始消息 |
| | | Console.WriteLine("Beginning (Ambient)"); |
| | | // 开始事务 |
| | | BeginTransaction(context, method, out var _unitOfWork, out var unitOfWorkAttribute); |
| | | |
| | | // 获取执行 Action 结果 |
| | | var resultContext = await next(); |
| | | |
| | | // 提交事务 |
| | | CommitTransaction(context, _unitOfWork, unitOfWorkAttribute, resultContext); |
| | | |
| | | // 提交分布式环境事务 |
| | | if (resultContext.Exception == null) |
| | | { |
| | | transactionScope?.Complete(); |
| | | |
| | | // 打印事务提交消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Completed (Ambient)"); |
| | | } |
| | | else |
| | | { |
| | | // 打印事务回滚消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)"); |
| | | |
| | | logger.LogError(resultContext.Exception, "Transaction Failed."); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | logger.LogError(ex, "Transaction Failed."); |
| | | |
| | | // 打印事务回滚消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)"); |
| | | |
| | | throw; |
| | | } |
| | | finally |
| | | { |
| | | transactionScope?.Dispose(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 模型绑定拦截 |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <returns></returns> |
| | | public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) |
| | | { |
| | | return Task.CompletedTask; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 拦截请求 |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <param name="next"></param> |
| | | /// <returns></returns> |
| | | public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) |
| | | { |
| | | // 获取动作方法描述器 |
| | | var method = context.HandlerMethod?.MethodInfo; |
| | | // 处理 Blazor Server |
| | | if (method == null) |
| | | { |
| | | _ = await next.Invoke(); |
| | | return; |
| | | } |
| | | |
| | | // 创建分布式环境事务 |
| | | (var transactionScope, var logger) = CreateTransactionScope(context); |
| | | |
| | | try |
| | | { |
| | | // 打印工作单元开始消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Beginning (Ambient)"); |
| | | |
| | | // 开始事务 |
| | | BeginTransaction(context, method, out var _unitOfWork, out var unitOfWorkAttribute); |
| | | |
| | | // 获取执行 Action 结果 |
| | | var resultContext = await next.Invoke(); |
| | | |
| | | // 提交事务 |
| | | CommitTransaction(context, _unitOfWork, unitOfWorkAttribute, resultContext); |
| | | |
| | | // 提交分布式环境事务 |
| | | if (resultContext.Exception == null) |
| | | { |
| | | transactionScope?.Complete(); |
| | | |
| | | // 打印事务提交消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Completed (Ambient)"); |
| | | } |
| | | else |
| | | { |
| | | // 打印事务回滚消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)"); |
| | | |
| | | logger.LogError(resultContext.Exception, "Transaction Failed."); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | logger.LogError(ex, "Transaction Failed."); |
| | | |
| | | // 打印事务回滚消息 |
| | | if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)"); |
| | | |
| | | throw; |
| | | } |
| | | finally |
| | | { |
| | | transactionScope?.Dispose(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 创建分布式环境事务 |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <returns></returns> |
| | | private (TransactionScope, ILogger) CreateTransactionScope(FilterContext context) |
| | | { |
| | | // 是否启用分布式环境事务 |
| | | var transactionScope = UseAmbientTransaction |
| | | ? new TransactionScope(TransactionScope, |
| | | new TransactionOptions { IsolationLevel = TransactionIsolationLevel, Timeout = TransactionTimeout > 0 ? TimeSpan.FromSeconds(TransactionTimeout) : default } |
| | | , TransactionScopeAsyncFlow) |
| | | : default; |
| | | |
| | | // 创建日志记录器 |
| | | var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<UnitOfWorkAttribute>>(); |
| | | |
| | | return (transactionScope, logger); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 开始事务 |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <param name="method"></param> |
| | | /// <param name="_unitOfWork"></param> |
| | | /// <param name="unitOfWorkAttribute"></param> |
| | | private static void BeginTransaction(FilterContext context, MethodInfo method, out IUnitOfWork _unitOfWork, out UnitOfWorkAttribute unitOfWorkAttribute) |
| | | { |
| | | // 解析工作单元服务 |
| | | _unitOfWork = context.HttpContext.RequestServices.GetRequiredService<IUnitOfWork>(); |
| | | |
| | | // 获取工作单元特性 |
| | | unitOfWorkAttribute = method.GetCustomAttribute<UnitOfWorkAttribute>(); |
| | | |
| | | // 调用开启事务方法 |
| | | _unitOfWork.BeginTransaction(context, unitOfWorkAttribute); |
| | | |
| | | // 打印工作单元开始消息 |
| | | if (!unitOfWorkAttribute.UseAmbientTransaction) Console.WriteLine("Beginning"); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 提交事务 |
| | | /// </summary> |
| | | /// <param name="context"></param> |
| | | /// <param name="_unitOfWork"></param> |
| | | /// <param name="unitOfWorkAttribute"></param> |
| | | /// <param name="resultContext"></param> |
| | | private static void CommitTransaction(FilterContext context, IUnitOfWork _unitOfWork, UnitOfWorkAttribute unitOfWorkAttribute, FilterContext resultContext) |
| | | { |
| | | // 获取动态结果上下文 |
| | | dynamic dynamicResultContext = resultContext; |
| | | |
| | | if (dynamicResultContext.Exception == null) |
| | | { |
| | | // 调用提交事务方法 |
| | | _unitOfWork.CommitTransaction(resultContext, unitOfWorkAttribute); |
| | | } |
| | | else |
| | | { |
| | | // 调用回滚事务方法 |
| | | _unitOfWork.RollbackTransaction(resultContext, unitOfWorkAttribute); |
| | | } |
| | | |
| | | // 调用执行完毕方法 |
| | | _unitOfWork.OnCompleted(context, resultContext); |
| | | |
| | | // 打印工作单元结束消息 |
| | | if (!unitOfWorkAttribute.UseAmbientTransaction) Console.WriteLine("Ending"); |
| | | } |
| | | } |
| | | } |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <TargetFramework>netcoreapp3.1</TargetFramework> |
| | |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="Autofac" Version="8.0.0" /> |
| | | <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.32" /> |
| | | <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" /> |
| | | <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" /> |
| | | <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> |
| | | <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> |
| | | <PackageReference Include="System.Drawing.Common" Version="5.0.3" /> |
| | | <PackageReference Include="Serilog" Version="4.0.0" /> |
| | | <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" /> |
| | | <PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" /> |
| | | <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> |
| | | <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> |
| | | <PackageReference Include="System.Drawing.Common" Version="6.0.0" /> |
| | | <PackageReference Include="ZXing.Net" Version="0.16.7" /> |
| | | </ItemGroup> |
| | | |
| | |
| | | using System.Linq; |
| | | using System.Security.Claims; |
| | | using System.Threading.Tasks; |
| | | using Utility; |
| | | using Utility.Extension; |
| | | using Wms.Tools; |
| | | using WMS.IBLL.IBllTaskServer; |
| | | |
| | |
| | | /// <param name="model"></param> |
| | | /// <returns></returns> |
| | | [HttpPost] |
| | | [AllowAnonymous] |
| | | public IActionResult GetTaskSyncList(TaskSyncVm model) |
| | | { |
| | | try |
| | |
| | | using Microsoft.Extensions.Configuration; |
| | | using Microsoft.Extensions.Hosting; |
| | | using Microsoft.Extensions.Logging; |
| | | using Serilog; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | |
| | | { |
| | | public static void Main(string[] args) |
| | | { |
| | | try |
| | | { |
| | | CreateHostBuilder(args).Build().Run(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Log.Fatal(ex, "*** Program Stop ***"); |
| | | } |
| | | finally |
| | | { |
| | | Log.CloseAndFlush(); |
| | | } |
| | | } |
| | | |
| | | public static IHostBuilder CreateHostBuilder(string[] args) => |
| | |
| | | .ConfigureWebHostDefaults(webBuilder => |
| | | { |
| | | webBuilder.UseStartup<Startup>(); |
| | | }).UseServiceProviderFactory(new AutofacServiceProviderFactory()); |
| | | }).UseServiceProviderFactory(new AutofacServiceProviderFactory()) |
| | | .UseSerilog(); |
| | | } |
| | | } |
| | |
| | | using Wms.Tools; |
| | | using WMS.Entity.Context; |
| | | using WMS.IBLL.IDataServer; |
| | | using Serilog; |
| | | using Autofac.Core; |
| | | using Utility; |
| | | using Utility.Extension; |
| | | using Microsoft.Extensions.Options; |
| | | using Microsoft.AspNetCore.Http; |
| | | |
| | | namespace Wms |
| | | { |
| | |
| | | services.AddHostedService<DailyTaskService>(provider => |
| | | new DailyTaskService(url,url2)); |
| | | |
| | | services.AddControllers() |
| | | services.AddControllers(options => { |
| | | options.Filters.Add<RequestAuditLogFilter>(); |
| | | }) |
| | | .AddJsonOptions(options => |
| | | { |
| | | //不使用驼峰样式的key |
| | |
| | | services.AddAutoMapper(typeof(AutoMapperProfile)); // automapper依赖 |
| | | #endregion |
| | | |
| | | //注册serilog |
| | | services.AddConfigSerilog(); |
| | | services.AddScoped<ApiResponseActionFilter>(); |
| | | } |
| | | public void ConfigureContainer(ContainerBuilder builder) |
| | | { |
| | |
| | | c.RoutePrefix = string.Empty; |
| | | }); |
| | | } |
| | | //全局返回规范 |
| | | //app.UseApiResponse();//弃用 改用Filter [ServiceFilter(typeof(ApiResponseActionFilter))] |
| | | app.UseExceptionMiddleware(); |
| | | |
| | | //使用Serilog记录请求日志 |
| | | app.UseSerilogRequestLogging(); |
| | | //app.UseHttpsRedirection(); |
| | | |
| | | app.UseRouting(); |
| | |
| | | app.UseAuthentication(); |
| | | app.UseAuthorization(); |
| | | app.UseCors("MyCors");//跨域 |
| | | |
| | | |
| | | app.UseEndpoints(endpoints => |
| | | { |
| | |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <Compile Remove="Logs\**" /> |
| | | <Compile Remove="ModelVm\**" /> |
| | | <Content Remove="Logs\**" /> |
| | | <Content Remove="ModelVm\**" /> |
| | | <EmbeddedResource Remove="Logs\**" /> |
| | | <EmbeddedResource Remove="ModelVm\**" /> |
| | | <None Remove="Logs\**" /> |
| | | <None Remove="ModelVm\**" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="Autofac" Version="6.5.0" /> |
| | | <PackageReference Include="Autofac" Version="8.0.0" /> |
| | | <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" /> |
| | | <PackageReference Include="AutoMapper" Version="12.0.1" /> |
| | | <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" /> |
| | | <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.32" /> |
| | | <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> |
| | | <PackageReference Include="Serilog" Version="4.0.0" /> |
| | | <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" /> |
| | | <PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" /> |
| | | <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> |
| | | <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> |
| | | <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> |
| | | <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.6" /> |
| | | </ItemGroup> |
| | |
| | | <ProjectReference Include="..\WMS.BLL\WMS.BLL.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Folder Include="Configuration\" /> |
| | | </ItemGroup> |
| | | |
| | | <ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions> |
| | | |
| | | |