feat:增加swagger权限功能

develop
old易 2023-11-17 16:52:57 +08:00
parent 079cb6e313
commit 0210507de1
24 changed files with 884 additions and 18 deletions

View File

@ -58,6 +58,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\New_College.Common\New_College.Common.csproj" />
<ProjectReference Include="..\New_College.Extensions\New_College.Extensions.csproj" /> <ProjectReference Include="..\New_College.Extensions\New_College.Extensions.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -24,6 +24,10 @@ using Essensoft.AspNetCore.Payment.Alipay;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using IdentityModel; using IdentityModel;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Newtonsoft.Json.Converters;
using New_College.Common.Helper;
using System.Text.Encodings.Web;
using System.Text.Unicode;
namespace New_College namespace New_College
{ {
@ -109,6 +113,7 @@ namespace New_College
services.Configure<KestrelServerOptions>(x => x.AllowSynchronousIO = true) services.Configure<KestrelServerOptions>(x => x.AllowSynchronousIO = true)
.Configure<IISServerOptions>(x => x.AllowSynchronousIO = true); .Configure<IISServerOptions>(x => x.AllowSynchronousIO = true);
services.AddControllers(o => services.AddControllers(o =>
{ {
// 全局异常过滤 // 全局异常过滤
@ -117,17 +122,40 @@ namespace New_College
//o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention()); //o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
// 全局路由前缀,统一修改路由 // 全局路由前缀,统一修改路由
o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name))); o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
}) }).AddJsonOptions(
//全局配置Json序列化处理 options =>
.AddNewtonsoftJson(options =>
{ {
//忽略循环引用 //格式化日期时间格式
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; options.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
//不使用驼峰样式的key //数据格式首字母小写
options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //options.JsonSerializerOptions.PropertyNamingPolicy =JsonNamingPolicy.CamelCase;
//设置时间格式 //数据格式原样输出
//options.SerializerSettings.DateFormatString = "yyyy-MM-dd"; options.JsonSerializerOptions.PropertyNamingPolicy = null;
//取消Unicode编码
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
//忽略空值
options.JsonSerializerOptions.IgnoreNullValues = true;
//允许额外符号
options.JsonSerializerOptions.AllowTrailingCommas = true;
//反序列化过程中属性名称是否使用不区分大小写的比较
options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
////忽略循环引用
//options.JsonSerializerOptions.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
////不使用驼峰样式的key
//options.SerializerSettings.ContractResolver = new DefaultContractResolver();
////设置时间格式
//options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
////忽略Model中为null的属性
////options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
////设置本地时间而非UTC时间
//options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
////添加Enum转string
//options.SerializerSettings.Converters.Add(new StringEnumConverter());
////将long类型转为string
//options.SerializerSettings.Converters.Add(new NumberConverter(NumberConverterShip.Int64));
}); });
//全局配置Json序列化处理
_services = services; _services = services;
} }
@ -164,7 +192,7 @@ namespace New_College
// 强制实施 HTTPS 在 ASP.NET Core配合 app.UseHttpsRedirection // 强制实施 HTTPS 在 ASP.NET Core配合 app.UseHttpsRedirection
//app.UseHsts(); //app.UseHsts();
} }
app.UseSwaggerAuthorized();
// 封装Swagger展示 // 封装Swagger展示
app.UseSwaggerMildd(() => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("New_College.Api.index.html")); app.UseSwaggerMildd(() => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("New_College.Api.index.html"));

View File

@ -26,7 +26,7 @@
"Name": "New_College" "Name": "New_College"
} }
}, },
"urls": "http://*:8083", // IIS "urls": "http://*:8082", // IIS
"AllowedHosts": "*", "AllowedHosts": "*",
"AppSettings": { "AppSettings": {
"RedisCachingAOP": { "RedisCachingAOP": {

View File

@ -0,0 +1 @@
[{"CodeRelationship":"0,","Name":"BCVP开发社区","Leader":"老张的哲学","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:47:25","ModifyTime":"2022-04-01 15:47:25","hasChildren":true,"Pid":0,"Id":1},{"CodeRelationship":"0,","Name":"DDD思想社区组织","Leader":"DDD","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:48:08","ModifyTime":"2022-04-01 15:48:08","hasChildren":true,"Pid":0,"Id":2},{"CodeRelationship":"0,1,","Name":"BCVP-北京分部","Leader":"北京","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:48:41","ModifyTime":"2022-04-01 15:48:41","hasChildren":true,"Pid":1,"Id":3},{"CodeRelationship":"0,1,","Name":"BCVP-上海分部","Leader":"上海","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:49:27","ModifyTime":"2022-04-01 15:49:27","hasChildren":true,"Pid":1,"Id":4},{"CodeRelationship":"0,1,","Name":"BCVP-广州分部","Leader":"广州","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:50:23","ModifyTime":"2022-04-01 15:50:44","hasChildren":true,"Pid":1,"Id":5},{"CodeRelationship":"0,1,3,","Name":"前端小组1群","Leader":"--","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:51:43","ModifyTime":"2022-04-01 15:51:43","hasChildren":true,"Pid":3,"Id":6},{"CodeRelationship":"0,1,4,","Name":"后端小组2群","Leader":"--","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 15:58:13","ModifyTime":"2022-04-01 15:58:13","hasChildren":true,"Pid":4,"Id":7},{"CodeRelationship":"0,","Name":"VUE学习联盟","Leader":"vue","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 16:14:21","ModifyTime":"2022-04-01 16:14:21","hasChildren":true,"Pid":0,"Id":8},{"CodeRelationship":"0,8,","Name":"ES指导1组","Leader":"es","OrderSort":0,"Status":true,"IsDeleted":false,"CreateBy":"老张的哲学","CreateTime":"2022-04-01 16:14:47","ModifyTime":"2022-04-01 16:15:00","hasChildren":true,"Pid":8,"Id":9}]
Can't render this file because it contains an unexpected character in line 1 and column 3.

191
New_College.Common/App.cs Normal file
View File

@ -0,0 +1,191 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using New_College.Common.Helper;
using New_College.Common.HttpContextUser;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace New_College.Common;
public class App
{
static App()
{
EffectiveTypes = Assemblies.SelectMany(GetTypes);
}
private static bool _isRun;
/// <summary>是否正在运行</summary>
public static bool IsBuild { get; set; }
public static bool IsRun
{
get => _isRun;
set => _isRun = IsBuild = value;
}
/// <summary>应用有效程序集</summary>
public static readonly IEnumerable<Assembly> Assemblies = RuntimeExtension.GetAllAssemblies();
/// <summary>有效程序集类型</summary>
public static readonly IEnumerable<Type> EffectiveTypes;
/// <summary>优先使用App.GetService()手动获取服务</summary>
public static IServiceProvider RootServices => IsRun || IsBuild ? InternalApp.RootServices : null;
/// <summary>获取Web主机环境是否是开发环境生产环境等</summary>
public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment;
/// <summary>获取泛型主机环境,如,是否是开发环境,生产环境等</summary>
public static IHostEnvironment HostEnvironment => InternalApp.HostEnvironment;
/// <summary>全局配置选项</summary>
public static IConfiguration Configuration => InternalApp.Configuration;
/// <summary>
/// 获取请求上下文
/// </summary>
public static HttpContext HttpContext => RootServices?.GetService<IHttpContextAccessor>()?.HttpContext;
public static IUser User => GetService<IUser>();
#region Service
/// <summary>解析服务提供器</summary>
/// <param name="serviceType"></param>
/// <param name="mustBuild"></param>
/// <param name="throwException"></param>
/// <returns></returns>
public static IServiceProvider GetServiceProvider(Type serviceType, bool mustBuild = false, bool throwException = true)
{
if (App.HostEnvironment == null || App.RootServices != null &&
InternalApp.InternalServices
.Where((u =>
u.ServiceType ==
(serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType)))
.Any((u => u.Lifetime == ServiceLifetime.Singleton)))
return App.RootServices;
//获取请求生存周期的服务
if (HttpContext?.RequestServices != null)
return HttpContext.RequestServices;
if (App.RootServices != null)
{
IServiceScope scope = RootServices.CreateScope();
return scope.ServiceProvider;
}
if (mustBuild)
{
if (throwException)
{
throw new ApplicationException("当前不可用,必须要等到 WebApplication Build后");
}
return default;
}
ServiceProvider serviceProvider = InternalApp.InternalServices.BuildServiceProvider();
return serviceProvider;
}
public static TService GetService<TService>(bool mustBuild = true) where TService : class =>
App.GetService(typeof(TService), null, mustBuild) as TService;
/// <summary>获取请求生存周期的服务</summary>
/// <typeparam name="TService"></typeparam>
/// <param name="serviceProvider"></param>
/// <param name="mustBuild"></param>
/// <returns></returns>
public static TService GetService<TService>(IServiceProvider serviceProvider, bool mustBuild = true)
where TService : class => (serviceProvider ?? App.GetServiceProvider(typeof(TService), mustBuild, false))?.GetService<TService>();
/// <summary>获取请求生存周期的服务</summary>
/// <param name="type"></param>
/// <param name="serviceProvider"></param>
/// <param name="mustBuild"></param>
/// <returns></returns>
public static object GetService(Type type, IServiceProvider serviceProvider = null, bool mustBuild = true) =>
(serviceProvider ?? App.GetServiceProvider(type, mustBuild, false))?.GetService(type);
#endregion
#region private
/// <summary>加载程序集中的所有类型</summary>
/// <param name="ass"></param>
/// <returns></returns>
private static IEnumerable<Type> GetTypes(Assembly ass)
{
Type[] source = Array.Empty<Type>();
try
{
source = ass.GetTypes();
}
catch
{
$@"Error load `{ass.FullName}` assembly.".WriteErrorLine();
}
return source.Where(u => u.IsPublic);
}
#endregion
#region Options
/// <summary>获取配置</summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <returns>TOptions</returns>
public static TOptions GetConfig<TOptions>()
where TOptions : class, IConfigurableOptions
{
TOptions instance = App.Configuration
.GetSection(ConfigurableOptions.GetConfigurationPath(typeof(TOptions)))
.Get<TOptions>();
return instance;
}
/// <summary>获取选项</summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <param name="serviceProvider"></param>
/// <returns>TOptions</returns>
public static TOptions GetOptions<TOptions>(IServiceProvider serviceProvider = null) where TOptions : class, new()
{
IOptions<TOptions> service = App.GetService<IOptions<TOptions>>(serviceProvider ?? App.RootServices, false);
return service?.Value;
}
/// <summary>获取选项</summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <param name="serviceProvider"></param>
/// <returns>TOptions</returns>
public static TOptions GetOptionsMonitor<TOptions>(IServiceProvider serviceProvider = null)
where TOptions : class, new()
{
IOptionsMonitor<TOptions> service =
App.GetService<IOptionsMonitor<TOptions>>(serviceProvider ?? App.RootServices, false);
return service?.CurrentValue;
}
/// <summary>获取选项</summary>
/// <typeparam name="TOptions">强类型选项类</typeparam>
/// <param name="serviceProvider"></param>
/// <returns>TOptions</returns>
public static TOptions GetOptionsSnapshot<TOptions>(IServiceProvider serviceProvider = null)
where TOptions : class, new()
{
IOptionsSnapshot<TOptions> service = App.GetService<IOptionsSnapshot<TOptions>>(serviceProvider, false);
return service?.Value;
}
#endregion
}

View File

@ -0,0 +1,61 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
namespace New_College.Common;
public static class ConfigurableOptions
{
/// <summary>添加选项配置</summary>
/// <typeparam name="TOptions">选项类型</typeparam>
/// <param name="services">服务集合</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddConfigurableOptions<TOptions>(this IServiceCollection services)
where TOptions : class, IConfigurableOptions
{
Type optionsType = typeof(TOptions);
string path = GetConfigurationPath(optionsType);
services.Configure<TOptions>(App.Configuration.GetSection(path));
return services;
}
public static IServiceCollection AddConfigurableOptions(this IServiceCollection services, Type type)
{
string path = GetConfigurationPath(type);
var config = App.Configuration.GetSection(path);
Type iOptionsChangeTokenSource = typeof(IOptionsChangeTokenSource<>);
Type iConfigureOptions = typeof(IConfigureOptions<>);
Type configurationChangeTokenSource = typeof(ConfigurationChangeTokenSource<>);
Type namedConfigureFromConfigurationOptions = typeof(NamedConfigureFromConfigurationOptions<>);
iOptionsChangeTokenSource = iOptionsChangeTokenSource.MakeGenericType(type);
iConfigureOptions = iConfigureOptions.MakeGenericType(type);
configurationChangeTokenSource = configurationChangeTokenSource.MakeGenericType(type);
namedConfigureFromConfigurationOptions = namedConfigureFromConfigurationOptions.MakeGenericType(type);
services.AddOptions();
services.AddSingleton(iOptionsChangeTokenSource,
Activator.CreateInstance(configurationChangeTokenSource, Options.DefaultName, config) ?? throw new InvalidOperationException());
return services.AddSingleton(iConfigureOptions,
Activator.CreateInstance(namedConfigureFromConfigurationOptions, Options.DefaultName, config) ?? throw new InvalidOperationException());
}
/// <summary>获取配置路径</summary>
/// <param name="optionsType">选项类型</param>
/// <returns></returns>
public static string GetConfigurationPath(Type optionsType)
{
var endPath = new[] {"Option", "Options"};
var configurationPath = optionsType.Name;
foreach (var s in endPath)
{
if (configurationPath.EndsWith(s))
{
return configurationPath[..^s.Length];
}
}
return configurationPath;
}
}

View File

@ -0,0 +1,11 @@
namespace New_College.Common;
/// <summary>
/// 应用选项依赖接口 <br/>
/// 自动注入配置文件 <br/>
/// 文件名为Option或Options结尾
/// </summary>
public interface IConfigurableOptions
{
}

View File

@ -12,6 +12,14 @@
/// true表示启动IDS4 /// true表示启动IDS4
/// false表示使用JWT /// false表示使用JWT
public static bool IsUseIds4 = false; public static bool IsUseIds4 = false;
/// <summary>
/// 当前项目是否启用Authing权限方案
/// true表示启动
/// false表示使用JWT
public static bool IsUseAuthing = false;
} }
/// <summary> /// <summary>
@ -24,6 +32,6 @@
/// 如果不需要,尽量留空,不要修改 /// 如果不需要,尽量留空,不要修改
/// 除非一定要在所有的 api 前统一加上特定前缀 /// 除非一定要在所有的 api 前统一加上特定前缀
/// </summary> /// </summary>
public const string Name = ""; public static string Name = "";
} }
} }

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace New_College.Common.Helper
{
/// <summary>
/// 格式化返回的时间格式
/// </summary>
public class DatetimeJsonConverter : JsonConverter<DateTime>
{
private readonly string format;
public DatetimeJsonConverter(string _format)
{
format = _format;
}
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
if (DateTime.TryParse(reader.GetString(), out DateTime date))
return date;
}
return reader.GetDateTime();
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(format));
}
}
}

View File

@ -3,11 +3,19 @@ using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json;
namespace New_College.Common.Helper namespace New_College.Common.Helper
{ {
public class JsonHelper public class JsonHelper
{ {
/// <summary> /// <summary>
/// Json 序列化配置 /// Json 序列化配置
/// </summary> /// </summary>

View File

@ -0,0 +1,177 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace New_College.Common.Helper
{
/// <inheritdoc />
/// <summary>
/// 大数据json序列化重写
/// </summary>
public sealed class NumberConverter : JsonConverter
{
/// <summary>
/// 转换成字符串的类型
/// </summary>
private readonly NumberConverterShip _ship;
/// <summary>
/// 大数据json序列化重写实例化
/// </summary>
public NumberConverter()
{
_ship = (NumberConverterShip)0xFF;
}
/// <summary>
/// 大数据json序列化重写实例化
/// </summary>
/// <param name="ship">转换成字符串的类型</param>
public NumberConverter(NumberConverterShip ship)
{
_ship = ship;
}
/// <inheritdoc />
/// <summary>
/// 确定此实例是否可以转换指定的对象类型。
/// </summary>
/// <param name="objectType">对象的类型。</param>
/// <returns>如果此实例可以转换指定的对象类型,则为:<c>true</c>,否则为:<c>false</c></returns>
public override bool CanConvert(Type objectType)
{
var typecode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
switch (typecode)
{
case TypeCode.Decimal:
return (_ship & NumberConverterShip.Decimal) == NumberConverterShip.Decimal;
case TypeCode.Double:
return (_ship & NumberConverterShip.Double) == NumberConverterShip.Double;
case TypeCode.Int64:
return (_ship & NumberConverterShip.Int64) == NumberConverterShip.Int64;
case TypeCode.UInt64:
return (_ship & NumberConverterShip.UInt64) == NumberConverterShip.UInt64;
case TypeCode.Single:
return (_ship & NumberConverterShip.Single) == NumberConverterShip.Single;
default: return false;
}
}
/// <inheritdoc />
/// <summary>
/// 读取对象的JSON表示。
/// </summary>
/// <param name="reader">从 <see cref="T:Newtonsoft.Json.JsonReader" /> 中读取。</param>
/// <param name="objectType">对象的类型。</param>
/// <param name="existingValue">正在读取的对象的现有值。</param>
/// <param name="serializer">调用的序列化器实例。</param>
/// <returns>对象值。</returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return AsType(reader.Value.ObjToString(), objectType);
}
/// <summary>
/// 字符串格式数据转其他类型数据
/// </summary>
/// <param name="input">输入的字符串</param>
/// <param name="destinationType">目标格式</param>
/// <returns>转换结果</returns>
public static object AsType(string input, Type destinationType)
{
try
{
var converter = TypeDescriptor.GetConverter(destinationType);
if (converter.CanConvertFrom(typeof(string)))
{
return converter.ConvertFrom(null, null, input);
}
converter = TypeDescriptor.GetConverter(typeof(string));
if (converter.CanConvertTo(destinationType))
{
return converter.ConvertTo(null, null, input, destinationType);
}
}
catch
{
return null;
}
return null;
}
/// <inheritdoc />
/// <summary>
/// 写入对象的JSON表示形式。
/// </summary>
/// <param name="writer">要写入的 <see cref="T:Newtonsoft.Json.JsonWriter" /> 。</param>
/// <param name="value">要写入对象值</param>
/// <param name="serializer">调用的序列化器实例。</param>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
}
else
{
var objectType = value.GetType();
var typeCode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
switch (typeCode)
{
case TypeCode.Decimal:
writer.WriteValue(((decimal)value).ToString("f6"));
break;
case TypeCode.Double:
writer.WriteValue(((double)value).ToString("f4"));
break;
case TypeCode.Single:
writer.WriteValue(((float)value).ToString("f2"));
break;
default:
writer.WriteValue(value.ToString());
break;
}
}
}
}
/// <summary>
/// 转换成字符串的类型
/// </summary>
[Flags]
public enum NumberConverterShip
{
/// <summary>
/// 长整数
/// </summary>
Int64 = 1,
/// <summary>
/// 无符号长整数
/// </summary>
UInt64 = 2,
/// <summary>
/// 浮点数
/// </summary>
Single = 4,
/// <summary>
/// 双精度浮点数
/// </summary>
Double = 8,
/// <summary>
/// 大数字
/// </summary>
Decimal =16
}
}

View File

@ -0,0 +1,19 @@
using System;
using Microsoft.AspNetCore.Http;
namespace New_College.Extensions;
public static class HttpContextExtension
{
public static ISession GetSession(this HttpContext context)
{
try
{
return context.Session;
}
catch (Exception)
{
return default;
}
}
}

View File

@ -0,0 +1,45 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace New_College;
/// <summary>
/// 内部只用于初始化使用
/// </summary>
public static class InternalApp
{
internal static IServiceCollection InternalServices;
/// <summary>根服务</summary>
internal static IServiceProvider RootServices;
/// <summary>获取Web主机环境</summary>
internal static IWebHostEnvironment WebHostEnvironment;
/// <summary>获取泛型主机环境</summary>
internal static IHostEnvironment HostEnvironment;
/// <summary>配置对象</summary>
internal static IConfiguration Configuration;
public static void ConfigureApplication(this WebApplicationBuilder wab)
{
HostEnvironment = wab.Environment;
WebHostEnvironment = wab.Environment;
InternalServices = wab.Services;
}
public static void ConfigureApplication(this IConfiguration configuration)
{
Configuration = configuration;
}
public static void ConfigureApplication(this IHost app)
{
RootServices = app.Services;
}
}

View File

@ -0,0 +1,86 @@
using Microsoft.Extensions.DependencyModel;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
namespace New_College;
public static class RuntimeExtension
{
/// <summary>
/// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
/// </summary>
/// <returns></returns>
public static IList<Assembly> GetAllAssemblies()
{
var list = new List<Assembly>();
var deps = DependencyContext.Default;
//只加载项目中的程序集
var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type == "project"); //排除所有的系统程序集、Nuget下载包
foreach (var lib in libs)
{
try
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
list.Add(assembly);
}
catch (Exception e)
{
Log.Debug(e, "GetAllAssemblies Exception:{ex}", e.Message);
}
}
return list;
}
public static Assembly GetAssembly(string assemblyName)
{
return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
}
public static IList<Type> GetAllTypes()
{
var list = new List<Type>();
foreach (var assembly in GetAllAssemblies())
{
var typeInfos = assembly.DefinedTypes;
foreach (var typeInfo in typeInfos)
{
list.Add(typeInfo.AsType());
}
}
return list;
}
public static IList<Type> GetTypesByAssembly(string assemblyName)
{
var list = new List<Type>();
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
var typeInfos = assembly.DefinedTypes;
foreach (var typeInfo in typeInfos)
{
list.Add(typeInfo.AsType());
}
return list;
}
public static Type GetImplementType(string typeName, Type baseInterfaceType)
{
return GetAllTypes().FirstOrDefault(t =>
{
if (t.Name == typeName &&
t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
{
var typeInfo = t.GetTypeInfo();
return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
}
return false;
});
}
}

View File

@ -0,0 +1,76 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace New_College.Common
{
public class SwaggerAuthMiddleware
{
private readonly RequestDelegate next;
public SwaggerAuthMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// 也可以根据是否是本地做判断 IsLocalRequest
if (context.Request.Path.Value.ToLower().Contains("index.html"))
{
// 判断权限是否正确
if (IsAuthorized(context))
{
await next.Invoke(context);
return;
}
// 无权限跳转swagger登录页
// context.RedirectSwaggerLogin();
}
else
{
await next.Invoke(context);
}
}
public bool IsAuthorized(HttpContext context)
{
//使用session模式
//可以使用其他的
return context.IsSuccessSwagger();
}
/// <summary>
/// 判断是不是本地访问
/// 本地不用swagger拦截
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public bool IsLocalRequest(HttpContext context)
{
if (context.Connection.RemoteIpAddress == null && context.Connection.LocalIpAddress == null)
{
return true;
}
if (context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
{
return true;
}
if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress))
{
return true;
}
return false;
}
}
public static class SwaggerAuthorizeExtensions
{
public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SwaggerAuthMiddleware>();
}
}
}

View File

@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using New_College.Extensions;
namespace New_College.Common;
public static class SwaggerContextExtension
{
public const string SwaggerCodeKey = "swagger-code";
public const string SwaggerJwt = "swagger-jwt";
public static bool IsSuccessSwagger()
{
return App.HttpContext?.GetSession()?.GetString(SwaggerCodeKey) == "success";
}
public static bool IsSuccessSwagger(this HttpContext context)
{
return context.GetSession()?.GetString(SwaggerCodeKey) == "success";
}
public static void SuccessSwagger()
{
App.HttpContext?.GetSession()?.SetString(SwaggerCodeKey, "success");
}
public static void SuccessSwagger(this HttpContext context)
{
context.GetSession()?.SetString(SwaggerCodeKey, "success");
}
public static void SuccessSwaggerJwt(this HttpContext context, string token)
{
context.GetSession()?.SetString(SwaggerJwt, token);
}
public static string GetSuccessSwaggerJwt(this HttpContext context)
{
return context.GetSession()?.GetString(SwaggerJwt);
}
public static void RedirectSwaggerLogin(this HttpContext context)
{
var returnUrl = context.Request.GetDisplayUrl(); //获取当前url地址
context.Response.Redirect("/swg-login.html?returnUrl=" + returnUrl);
}
}

View File

@ -15,8 +15,9 @@
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.1.0" /> <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.3.3" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="5.1.1" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,20 @@
using Microsoft.Extensions.DependencyInjection;
using New_College.Common;
using System;
using System.Linq;
namespace New_College.ServiceExtensions;
public static class AllOptionRegister
{
public static void AddAllOptionRegister(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
foreach (var optionType in App.EffectiveTypes.Where(s =>
!s.IsInterface && typeof(IConfigurableOptions).IsAssignableFrom(s)))
{
services.AddConfigurableOptions(optionType);
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using Microsoft.AspNetCore.Http;
namespace New_College.Extensions;
public static class HttpContextExtension
{
public static ISession GetSession(this HttpContext context)
{
try
{
return context.Session;
}
catch (Exception)
{
return default;
}
}
}

View File

@ -106,6 +106,7 @@ namespace New_College.Extensions
}); });
// services.AddSwaggerGenNewtonsoftSupport();
} }
} }

View File

@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.IO.Compression;
namespace New_College.Extensions
{
/// <summary>
/// 将前端UI压缩文件进行解压
/// </summary>
public static class UiFilesZipSetup
{
public static void AddUiFilesZipSetup(this IServiceCollection services, IWebHostEnvironment _env)
{
if (services == null) throw new ArgumentNullException(nameof(services));
string wwwrootFolderPath = Path.Combine(_env.ContentRootPath, "wwwroot");
string zipUiItemFiles = Path.Combine(wwwrootFolderPath, "ui.zip");
if (!File.Exists(Path.Combine(wwwrootFolderPath, "ui", "index.html")))
{
ZipFile.ExtractToDirectory(zipUiItemFiles, wwwrootFolderPath);
}
}
}
}

View File

@ -10,6 +10,7 @@ namespace New_College.Model.ViewModels
{ {
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Code { get; set; }
} }
public class uniMajorClassSelect public class uniMajorClassSelect
@ -17,6 +18,8 @@ namespace New_College.Model.ViewModels
public int TradeId { get; set; } public int TradeId { get; set; }
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Code { get; set; }
} }
/// <summary> /// <summary>

View File

@ -26,7 +26,7 @@ namespace New_College.Repository
var response = await this.Db.Queryable<D_UniversityRank, D_University>((rank, u) => new object[] { JoinType.Left, rank.UniversityName == u.Name }) var response = await this.Db.Queryable<D_UniversityRank, D_University>((rank, u) => new object[] { JoinType.Left, rank.UniversityName == u.Name })
.Where((rank, u) => rank.UniversityType == query.Type) .Where((rank, u) => rank.UniversityType == query.Type)
.WhereIF(!string.IsNullOrWhiteSpace(query.Name), (rank, u) => SqlFunc.Contains(rank.UniversityName, query.Name)) .WhereIF(!string.IsNullOrWhiteSpace(query.Name), (rank, u) => SqlFunc.Contains(rank.UniversityName, query.Name))
.WhereIF(query.SubjectType.HasValue, (rank, u) => u.Subject_Level == query.SubjectType) .WhereIF(query.SubjectType.HasValue, (rank, u) => u.Type == query.SubjectType)
.OrderBy((rank, u) => rank.Rank, OrderByType.Asc) .OrderBy((rank, u) => rank.Rank, OrderByType.Asc)
.Select((rank, u) => new UniversityPcRankList .Select((rank, u) => new UniversityPcRankList
{ {

View File

@ -220,7 +220,7 @@ namespace New_College.Services
{ {
var result = new List<TreeMajorInfoResult>(); var result = new List<TreeMajorInfoResult>();
var classmajors = (await d_MajorClassRepository.Query(x => x.IsDelete == false && x.TradeId == tradeId)).Select(x => new uniMajorClassSelect() { Id = x.Id, Name = x.Name, TradeId = x.TradeId }).ToList(); var classmajors = (await d_MajorClassRepository.Query(x => x.IsDelete == false && x.TradeId == tradeId)).Select(x => new uniMajorClassSelect() { Id = x.Id, Name = x.Name, TradeId = x.TradeId }).ToList();
var majorinfo = (await d_MajorRepository.Query(x => x.IsDelete == false)).Select(s => new uniMajorClassSelect() { Id = s.Id, TradeId = s.CategoryClass_Id, Name = s.Name }).ToList(); var majorinfo = (await d_MajorRepository.Query(x => x.IsDelete == false)).Select(s => new uniMajorClassSelect() { Id = s.Id, TradeId = s.CategoryClass_Id, Name = s.Name,Code=s.MajorCode }).ToList();
classmajors.ForEach(a => classmajors.ForEach(a =>
{ {
var models = new TreeMajorInfoResult(); var models = new TreeMajorInfoResult();
@ -229,7 +229,8 @@ namespace New_College.Services
models.MajorsInfo = majorinfo.Where(e => e.TradeId == a.Id).Select(s => new uniMajorSelect() models.MajorsInfo = majorinfo.Where(e => e.TradeId == a.Id).Select(s => new uniMajorSelect()
{ {
Id = s.Id, Id = s.Id,
Name = s.Name Name = s.Name,
Code=s.Code
}).ToList(); }).ToList();
result.Add(models); result.Add(models);
}); });