feat:增加swagger权限功能
parent
079cb6e313
commit
0210507de1
|
|
@ -58,6 +58,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\New_College.Common\New_College.Common.csproj" />
|
||||
<ProjectReference Include="..\New_College.Extensions\New_College.Extensions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ using Essensoft.AspNetCore.Payment.Alipay;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using IdentityModel;
|
||||
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
|
||||
{
|
||||
|
|
@ -109,6 +113,7 @@ namespace New_College
|
|||
services.Configure<KestrelServerOptions>(x => x.AllowSynchronousIO = true)
|
||||
.Configure<IISServerOptions>(x => x.AllowSynchronousIO = true);
|
||||
|
||||
|
||||
services.AddControllers(o =>
|
||||
{
|
||||
// 全局异常过滤
|
||||
|
|
@ -117,17 +122,40 @@ namespace New_College
|
|||
//o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
|
||||
// 全局路由前缀,统一修改路由
|
||||
o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
|
||||
})
|
||||
//全局配置Json序列化处理
|
||||
.AddNewtonsoftJson(options =>
|
||||
}).AddJsonOptions(
|
||||
options =>
|
||||
{
|
||||
//忽略循环引用
|
||||
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
||||
//不使用驼峰样式的key
|
||||
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
|
||||
//设置时间格式
|
||||
//options.SerializerSettings.DateFormatString = "yyyy-MM-dd";
|
||||
//格式化日期时间格式
|
||||
options.JsonSerializerOptions.Converters.Add(new DatetimeJsonConverter("yyyy-MM-dd HH:mm:ss"));
|
||||
//数据格式首字母小写
|
||||
//options.JsonSerializerOptions.PropertyNamingPolicy =JsonNamingPolicy.CamelCase;
|
||||
//数据格式原样输出
|
||||
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;
|
||||
}
|
||||
|
|
@ -164,7 +192,7 @@ namespace New_College
|
|||
// 强制实施 HTTPS 在 ASP.NET Core,配合 app.UseHttpsRedirection
|
||||
//app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseSwaggerAuthorized();
|
||||
// 封装Swagger展示
|
||||
app.UseSwaggerMildd(() => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("New_College.Api.index.html"));
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
"Name": "New_College"
|
||||
}
|
||||
},
|
||||
"urls": "http://*:8083", // IIS 部署,注释掉
|
||||
"urls": "http://*:8082", // IIS 部署,注释掉
|
||||
"AllowedHosts": "*",
|
||||
"AppSettings": {
|
||||
"RedisCachingAOP": {
|
||||
|
|
|
|||
|
|
@ -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.
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace New_College.Common;
|
||||
|
||||
/// <summary>
|
||||
/// 应用选项依赖接口 <br/>
|
||||
/// 自动注入配置文件 <br/>
|
||||
/// 文件名为Option或Options结尾
|
||||
/// </summary>
|
||||
public interface IConfigurableOptions
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,14 @@
|
|||
/// true:表示启动IDS4
|
||||
/// false:表示使用JWT
|
||||
public static bool IsUseIds4 = false;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 当前项目是否启用Authing权限方案
|
||||
/// true:表示启动
|
||||
/// false:表示使用JWT
|
||||
public static bool IsUseAuthing = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -24,6 +32,6 @@
|
|||
/// 如果不需要,尽量留空,不要修改
|
||||
/// 除非一定要在所有的 api 前统一加上特定前缀
|
||||
/// </summary>
|
||||
public const string Name = "";
|
||||
public static string Name = "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,11 +3,19 @@ using Newtonsoft.Json.Converters;
|
|||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace New_College.Common.Helper
|
||||
{
|
||||
|
||||
|
||||
|
||||
public class JsonHelper
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Json 序列化配置
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,9 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.1.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.3.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="5.1.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -106,6 +106,7 @@ namespace New_College.Extensions
|
|||
|
||||
|
||||
});
|
||||
// services.AddSwaggerGenNewtonsoftSupport();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ namespace New_College.Model.ViewModels
|
|||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Code { get; set; }
|
||||
}
|
||||
|
||||
public class uniMajorClassSelect
|
||||
|
|
@ -17,6 +18,8 @@ namespace New_College.Model.ViewModels
|
|||
public int TradeId { get; set; }
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Code { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
.Where((rank, u) => rank.UniversityType == query.Type)
|
||||
.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)
|
||||
.Select((rank, u) => new UniversityPcRankList
|
||||
{
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ namespace New_College.Services
|
|||
{
|
||||
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 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 =>
|
||||
{
|
||||
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()
|
||||
{
|
||||
Id = s.Id,
|
||||
Name = s.Name
|
||||
Name = s.Name,
|
||||
Code=s.Code
|
||||
}).ToList();
|
||||
result.Add(models);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue