SIDA.Core 2.0.4

dotnet add package SIDA.Core --version 2.0.4
NuGet\Install-Package SIDA.Core -Version 2.0.4
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SIDA.Core" Version="2.0.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SIDA.Core --version 2.0.4
#r "nuget: SIDA.Core, 2.0.4"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install SIDA.Core as a Cake Addin
#addin nuget:?package=SIDA.Core&version=2.0.4

// Install SIDA.Core as a Cake Tool
#tool nuget:?package=SIDA.Core&version=2.0.4

Webapi核心库

概述

SIDA.Core 可理解为二次封装微软 net webapi 项目模版,目的是为了让研发业务应用更能聚焦到业务层面。

快速开始

  1. 新建WebApi类型项目,添加包SIDA.Core引用
  2. 打开Program.cs删除所有内容,编写如下代码。
using SIDA.Core.Startup;
// 实例AppHost类执行Startup方法即可按默认配置启动。
var appHost = new AppHost().Startup(args);
  1. 新建TestService.cs服务接口类。
[DynamicWebApi]
public class TestService : IDynamicWebApi
{
    public async Task<int> GetTestIdAsync()
    {
	    return 1;
    }
}
  1. 启动项目,即可看到TestId接口。

配置说明

AppHostOptions

在实例化AppHost 时,可传入 AppHostOptions 按自定义配置参数执行

var appHost = new AppHost(new AppHostOptions{
// AppHostOptions 配置
}).Startup(args); 

AppHostOptions 解释

// 配置 WebApplicationBuilder
ConfigureWebApplicationBuilder 
// 配置拦截器
ConfigureInterceptor 
// 配置 Autofac
ConfigureAutofacContainer
// 注入前置服务
ConfigurePreServices 
// 注入后置服务
ConfigurePostServices
// 配置鉴权认证
ConfigureAuthentication
// 配置JwtBearer 
ConfigureJwtBearer 
// 配置Swagger
ConfigureSwaggerGen 
// 配置MvcBuilder
ConfigureMvcBuilder 
// 配置响应参数
ConfigureResponseOptions
// 配置动态API
ConfigureDynamicWebApi 
// 前置中间件
ConfigurePreMiddleware
// 后置中间件
ConfigurePostMiddleware 

配置文件

添加包SIDA.Core引用后,第一次启动项目 SIDA.Core将在目录Settings中检测是否存在core.settings.json配置文件,如不存在将自动生成。

{
  //Api地址 可为空
  "urls": [ "http://*:9001" ],
  //跨域地址
  "corUrls": [],
  //最大请求大小 默认 104857600 = 100MB 
  "maxRequestBodySize": 104857600,
  //程序集名称
  "assemblyNames": [ "SIDA.SystemMgt" ],
  //MiniProfiler性能分析器
  "miniProfiler": false,
  //默认密码
  "defaultPassword": "111111",
  //是否启用 动态API 响应 格式化
  "responseFormat": true,
  //设置枚举请求和返回使用字符串而非数字
  "enableJsonStringEnumConverter": true,
  //Swagger文档
  "swagger": {
    //启用
    "enable": true,
    //文档描述
    "description":"SIDA.Core API",
    //启用Redoc
    "enableRedoc": true,
    //Redoc路径
    "redocPath": "/redoc"
  },
  
  //统一认证授权服务器 - identityServer
  "identityServer": {
    //启用
    "enable": false,
    //认证地址
    "url": "https://localhost:5000",
    //启用Https
    "requireHttpsMetadata": true,
    //受众
    "audience": "sida.server.api"
  },
  //统一认证授权服务器 - JWT
  "jwt": {
    //启用
    "enable": false,
    //发行者
    "issuer": "test",
    //订阅者
    "audience": "test",
    //密钥
    "securityKey": "12345678123456781234567812345678",
    //有效期(分钟) 120 = 2小时
    "expires": 120,
    //刷新有效期(分钟) 1440 = 1天
    "refreshExpires": 1440,
    //编码
    "EncodingType": "ASCII"
  },

  "healthCheck": {
    //启用
    "enable": true,
    //访问路径
    "path": "/admin/health"
  },

  "cache": {
    //缓存类型 Memory = 0,Redis = 1
    "type": "Memory",
    //限流缓存类型 Memory = 0,Redis = 1
    "typeRateLimit": "Memory",
    //Redis配置
    "redis": {
      //连接字符串
      "connectionString": "127.0.0.1:6379,password=,defaultDatabase=0",
      //限流连接字符串
      "connectionStringRateLimit": "127.0.0.1:6379,password=,defaultDatabase=0"
    }
  }
}

响应格式

SIDA.Core 提供了一套标准的响应格式,如果你想自定义,可通过继承 IResponseFormat接口实现自己的响应格式。

自定义响应格式

OutputFormat.cs 实现接口 IResponseFormat

public class OutputFormat : IResponseFormat
{
	public JsonResult Result<T>(bool isSuccess, string code = "", string msg = null, T data = default)
	{
		var res = new OutputEntity<T>
		{
			IsSuccess = isSuccess,
			Code = code,
			Message = msg,
			Data = data
		};
		return new JsonResult(res);
	}
}

public class OutputEntity<T>
{
	public bool IsSuccess { get; set; }
	public string Code { get; set; }
	public string Message { get; set; }
	public T Data { get; set; }
}

配置 AppHostOptions 启动参数

ConfigureResponseOptions = (options, appHostServicesContext) =>
{
	// 配置响应实体类型,用于Swagger UI 展示
	options.ResponseType = typeof(OutputEntity<>);
	// 响应格式化类库,需实现接口 IResponseFormat
	options.ResponseFormat = new OutputFormat();
}

响应成功示例

系统将自动按既定格式输出

public virtual async Task<string> PostTestAsync(){
	// 你的逻辑
	return "123"
}
// 前端得到 {IsSuccess:true,code:"200",Message:"",data:"123"}

响应失败示例

如果需要抛出失败,直接抛出 AppException

// 无code 默认为0
throw new AppException("用户名或密码错误");
// 前端响应得到 {IsSuccess:false,code:"0",Message:"用户名或密码错误"}

// 带code
throw new AppException("您无权操作","401");
// 前端响应得到 {IsSuccess:false,code:"401",Message:"您无权操作"}

// 带code 带data
throw new AppException("错误消息", "0", new { id = 1, title = "alonso" });
// 前端响应得到 {IsSuccess:false,code:"401",Message:"错误消息",Data:{id:1,titile:"alonso"}}

不按既定规则响应

如果某一个特殊接口不想以既定响应格式输出,可通过 特性 NonFormatResult 对方法进行标记。

[NonFormatResult]
public virtual async Task<string> PostTestAsync(){
	// 你的逻辑
	return "123"
}
// 前端得到 "123"

[NonFormatResult]
public virtual async Task<List<string>> PostTestAsync(){
	// 你的逻辑
	return new List<string> {"a","b"};
}
// 前端得到 ["a", "b"]

自定义动态API

ConfigureDynamicWebApi = (options, appHostServicesContext) => {
	//自定义动态API选择器 详细见 自定义`SelectController`
	options.SelectController = new ServiceLocalSelectController();
	//自定义动态API路由构造器 详细见 自定义`ActionRouteFactory`
	options.ActionRouteFactory = new ServiceActionRouteFactory();
	// 其他配置 见 DynamicWebApiOptions 配置
}

自定义动态API选择器

实现 ISelectController 接口

// 选择器 ServiceLocalSelectController 实现 ISelectController
internal class ServiceLocalSelectController : ISelectController
{
    public bool IsController(Type type)
    {
	    // 通过查找类是否有ServiceAttribute特性为注册WebApi条件
        return type.IsPublic && type.GetCustomAttribute<ServiceAttribute>() != null;
    }
}

// ServiceAttribute.cs
[AttributeUsage(AttributeTargets.Class)]
public class ServiceAttribute : Attribute
{
    public ServiceAttribute()
    {
        ServiceName = string.Empty;
    }
    public ServiceAttribute(string serviceName)
    {
        ServiceName = serviceName;
    }
    public string ServiceName { get; }
}

自定义动态API路由构造器

实现 IActionRouteFactory 接口,生成路由规则 /api/ServiceName/Method

internal class ServiceActionRouteFactory : IActionRouteFactory
{
    public string CreateActionRouteModel(string areaName, string controllerName, ActionModel action)
    {
        var controllerType = action.ActionMethod.DeclaringType;
        var serviceAttribute = controllerType.GetCustomAttribute<ServiceAttribute>();
        // `ServiceAttribute.ServiceName`为空时,`controllerName` 替换 `Service` 字符串为空,反之则将`ServiceAttribute.ServiceName` 替换为空.
        var _controllerName = serviceAttribute.ServiceName == string.Empty ? controllerName.Replace("Service", "") : serviceAttribute.ServiceName.Replace("Service", "");
        // ActionName 含有 "Async" 字符串替换为空。
        return $"api/{_controllerName}/{action.ActionName.Replace("Async", "")}";
    }
}

DynamicWebApiOptions 配置

所有的配置均在对象 DynamicWebApiOptions 中,说明如下:

属性名 是否必须 说明
DefaultHttpVerb 默认值:POST。默认HTTP动词
DefaultAreaName 默认值:空。Area 路由名称
DefaultApiPrefix 默认值:api。API路由前缀
RemoveControllerPostfixes 默认值:AppService/ApplicationService。类名需要移除的后缀
RemoveActionPostfixes 默认值:Async。方法名需要移除的后缀
FormBodyBindingIgnoredTypes 默认值:IFormFile。不通过MVC绑定到参数列表的类型。

HttpMethod 配置

默认的HTTP动词为POST,可以理解为API的 Http Method,但可以通过 HttpGet/HttpPost/HttpDelete 等等ASP.NET Core 内置特性来覆盖 如果不使用 HttpGet/HttpPost/HttpDelete 等等ASP.NET Core 内置特性,SIDA.Core.DynamicWebApi将以默认规约方式进行定义 HttpMethod HttpMethod 规约如下: 根据方法名字来设置HTTP动词,如 CreateApple 或者 Create 生成的API动词为 POST,对照表如下,若命中(忽略大小写)对照表那么该API的名称中的这部分将会被省略,如 CreateApple 将会变成 Apple,如未在以下对照表中,将会使用默认动词 POST

方法名开头 动词
create POST
add POST
post POST
get GET
find GET
fetch GET
query GET
update PUT
put PUT
delete DELETE
remove DELETE

强烈建议方法名称使用帕斯卡命名(PascalCase)规范,且使用以上对照表的动词。如: 添加 → Add/AddApple/Create/CreateApple 更新 → Update/UpdateApple

动态API其他说明

  • 要让类生成动态API需要满足两个条件,一个是该类直接间接实现 IDynamicWebApi,同时该类本身或者父抽象类或者实现的接口具有特性 DynamicWebApi
  • 添加特性 [NonDynamicWebApi] 可使一个类不生成API,[NonDynamicWebApi] 具有最高的优先级。[DynamicWebApi] 特性因为可被继承,所以为了父类被误识别,禁止放在除抽象类、接口以外的父类上。
  • 添加特性 [NonDynamicMethod] 可使一个方法不生成API,[NonDynamicMethod] 具有最高的优先级。
  • 会对符合规则的动态API类名进行后缀的删除,对于标记为  [NonDynamicWebApi] 的类,后缀为 Service 的将替换为空,其中方法为Async的后缀也将替换为空。
  • 会自动添加API路由前缀,默认会为所有API添加 api前缀

依赖注入

自动注入

在配置文件中配置了程序集,在配置程序集中以 Service、Repository 结尾的类库将自动注入

//程序集名称 配置的程序集将自动按既定条件注入(Service、Repository结尾的类库将自动注入)
"assemblyNames": [ "SD.Tenant.Services.System", "SD.Tenant.Services.Business", "SD.Tenant.Infrastructure" ],

标记特性注入

通过对类库标记特性 SingleInstance 实现自动注入(单例注入,Scope暂未提供,可自行实现)

// 带接口的
[SingleInstance]
public class UploadTool : IUploadTool
{}

// 不带接口的
[SingleInstance]
public class UploadTool
{}

手工注入

通过对类库标记特性 SingleInstance 实现自动注入(单例注入,Scope暂未提供,可自行实现)

// 注入前置服务 ConfigurePreServices 或 注入后置服务 ConfigurePostServices
// 进行如下手动配置
services.AddSingleton<IUploadTool, UploadTool>();

注入对象获取

通过构造函数注入获取对象、属性注入获取对象、利用 CoreContext 直接获取

// 利用 `CoreContext` 直接获取
CoreContext.ServiceProvider.GetRequiredService<IUploadTool>();

工具

JwtToken 生成

命名空间 : SIDA.Core.JwtToken

已将 IToken 注入到容器中 可直接使用

var claims = new List<Claim>()
{
	new Claim("你的ClaimKey", user.Id.ToString(), ClaimValueTypes.Integer64)
	// 其他Claim信息
};
var token = ServiceProvider.GetService<IToken>().Create(claims);

帮助类库

SIDA.Core.Common.Helpers;

AssemblyHelper
ClassHelper
ConfigHelper
FileHelper
JsonHelper
MD5Helper
//里面的方法使用自行查看

扩展类库

String 字符串扩展

SIDA.Core.Common.Extensions;

    // 判断字符串是否为Null、空白
    public static bool IsNull(this string s)
    // 判断字符串是否为Null、空
    public static bool IsNullOrEmpty(this string str)
    // 判断字符串是否不为Null、空白
    public static bool NotNull(this string s)
    // 与字符串进行比较,忽略大小写
    public static bool EqualsIgnoreCase(this string s, string value)
    // 首字母转小写
    public static string FirstCharToLower(this string s)
    // 首字母转大写
    public static string FirstCharToUpper(this string s)
    // 转为Base64,UTF-8格式
    public static string ToBase64(this string s)
    // 转为Base64
    public static string ToBase64(this string s, Encoding encoding)
    // 转为 路径格式
    // eg: 
    // Path.Combine(Directory.GetCurrentDirectory(), path).ToPath();
    // !File.Exists(filePath)
    public static string ToPath(this string s)
	// 更加object key 替换字符串中为格式为"{key}"的值
    public static string Format(this string str, object obj)
    // 判断是否在数组中
    public static bool IsIn(this string str, params string[] data)
    // 字符左截取
    public static string Left(this string str, int len)
    // 字符右截取
    public static string Right(this string str, int len)
    // 去除后缀 
    public static string RemovePostFix(this string str, params string[] postFixes)
    // 去除后缀
    public static string RemovePostFix(this string str, string postFixe) 
    // 去除前缀
    public static string RemovePreFix(this string str, params string[] preFixes)
    // 去除前缀
    public static string RemovePreFix(this string str, string preFixe)
	// 得到CamelCase驼峰第一个字母构成的字符串
    public static string GetCamelCaseFirstWord(this string str)
	// 得到PascalCase驼峰第一个字母构成的字符串
    public static string GetPascalCaseFirstWord(this string str)
	// 得到CamelCase 或 PascalCase驼峰第一个字母构成的字符串
    public static string GetPascalOrCamelCaseFirstWord(this string str)

DateTime 日期扩展

SIDA.Core.Common.Extensions;

// 转换为时间戳
public static long ToTimestamp(this DateTime dateTime, bool milliseconds = false)
// 获取周几
public static string GetWeekName(this DateTime datetime)

IDictionary 扩展

SIDA.Core.Common.Extensions;

// 取得 Dictionary 中的值,如果没有则添加
public static TValue GetOrAdd<TKey, TValue>(
   this IDictionary<TKey, TValue> dictionary,
   TKey key,
   Func<TKey, TValue> factory)

// 取得 Dictionary 中的值,如果没有则添加
public static TValue GetOrAdd<TKey, TValue>(
   this IDictionary<TKey, TValue> dictionary,
   TKey key,
   Func<TValue> factory)
// 向 Dictionary 中添加或更新,
public static TValue AddOrUpdate<TKey, TValue>(
   this IDictionary<TKey, TValue> dictionary,
   TKey key,
   Func<TKey, TValue> addFactory,
   Func<TKey, TValue, TValue> updateFactory)
   
// 向 Dictionary 中添加或更新,
public static TValue AddOrUpdate<TKey, TValue>(
   this IDictionary<TKey, TValue> dictionary,
   TKey key,
   Func<TValue> addFactory,
   Func<TValue, TValue> updateFactory)

Enum 枚举扩展

SIDA.Core.Common.Extensions;

// 得到枚举描述
public static string ToDescription(this Enum item)
// 得到枚举名称+描述
public static string ToNameWithDescription(this Enum item)
// 得到枚举值
public static long ToInt64(this Enum item)
// 枚举转List:  ["Label"] = x.ToDescription(), ["Value"] = x
public static List<Dictionary<string, object>> ToList(this Enum value, bool ignoreNull = false)

Exception 异常扩展

SIDA.Core.Common.Extensions;

// 得到异常消息,异常内容错误将全部取出
public static string GetaAllMessages(this Exception exp)

Object 对象扩展

SIDA.Core.Common.Extensions;

// 转整型
public static int ToInt(this object s, bool round = false)
//  转 long
public static long ToLong(this object s)
//  转 ToMoney  转换失败 返回0
public static double ToMoney(this object thisValue)
//  转 ToMoney  转换失败 返回空errorValue
public static double ToMoney(this object thisValue, double errorValue)
//  转 Float  转换失败 返回空
public static string ToString(this object thisValue)
//  转 Float  转换失败 返回errorValue
public static string ToString(this object thisValue, string errorValue)
//  转 Float 
public static float ToFloat(this object s, int? digits = null)
//  转 double 
public static double ToDouble(this object s, int? digits = null)
//  转 decimal 
public static decimal ToDecimal(this object thisValue)
//  转 decimal 转换失败 返回errorValue
public static decimal ToDecimal(this object thisValue, decimal errorValue)
//  转 DateTime
public static DateTime ToDateTime(this object thisValue)
//  转 DateTime 转换失败 返回errorValue
public static DateTime ToDateTime(this object thisValue, DateTime errorValue)
//  转 bool
public static bool ToBool(this object thisValue)
//  转换byte
public static byte ToByte(this object s)
// 转换为16进制
public static string ToHex(this byte[] bytes, bool lowerCase = true)
//  转换为16进制转字节数组
public static byte[] HexToBytes(this string s)
// 转换为Base64
public static string ToBase64(this byte[] bytes)

上下文 CoreContext

提供了经常使用到变量

public static IServiceCollection Services;

public static IServiceProvider ServiceProvider;

public static IWebHostEnvironment WebHostEnvironment;

public static IHostEnvironment HostEnvironment;

public static IConfiguration Configuration;

强烈建议在你自己的应用中建立属于你自己的Context静态类库加入诸如鉴权用户、日志处理、缓存等对象,以方便开发人员使用更全面的对象。

可借鉴如下例子:


public static class SystemContext
{
    /// <summary>
    /// 服务提供程序
    /// </summary>
    public static IServiceProvider ServiceProvider => CoreContext.ServiceProvider;
    
    /// <summary>
    /// Web主机环境
    /// </summary>
    public static IWebHostEnvironment WebHostEnvironment => CoreContext.WebHostEnvironment;

    /// <summary>
    /// 泛型主机环境
    /// </summary>
    public static IHostEnvironment HostEnvironment => CoreContext.HostEnvironment;

    /// <summary>
    /// 配置
    /// </summary>
    public static IConfiguration Configuration => CoreContext.Configuration;

    /// <summary>
    /// 请求上下文
    /// </summary>
    public static HttpContext HttpContext => ServiceProvider?.GetService<IHttpContextAccessor>()?.HttpContext;


    /// <summary>
    /// 登录用户
    /// </summary>
    public static IUser User => HttpContext == null ? null : ServiceProvider?.GetService<IUser>();

    /// <summary>
    /// 日志
    /// </summary>
    public static ILogHelper LogHelper => CoreContext.ServiceProvider.GetRequiredService<ILogHelper>();

    /// <summary>
    /// 缓存
    /// </summary>
    public static ICache Cache => ServiceProvider?.GetService<ICache>();

    /// <summary>
    /// 系统配置参数
    /// </summary>
    public static CoreSettings CoreSettings => ServiceProvider?.GetService<CoreSettings>();

    /// <summary>
    /// 上传配置参数
    /// </summary>
    public static UploadSettings UploadSettings => ServiceProvider?.GetService<UploadSettings>();

    /// <summary>
    /// 应用配置参数
    /// </summary>
    public static AppSettings AppSettings => CoreContext.ServiceProvider.GetRequiredService<AppSettings>();
}
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.4 0 5/16/2024
2.0.3 0 5/16/2024
2.0.2 94 4/27/2024
2.0.1 90 4/24/2024
2.0.0 83 4/24/2024
1.1.5 132 12/15/2023
1.1.4 146 9/14/2023
1.1.3 129 9/12/2023
1.1.2 128 9/10/2023
1.1.1 109 9/10/2023
1.1.0 114 9/10/2023
1.0.9 121 9/9/2023
1.0.8 116 9/1/2023
1.0.7 123 8/25/2023
1.0.6 152 8/14/2023
1.0.5 138 8/14/2023
1.0.4 128 7/31/2023
1.0.3 149 7/16/2023
1.0.2 139 7/12/2023
1.0.1 137 7/6/2023
1.0.0 134 7/5/2023