Skip to content

Mud.HttpUtils.Attributes

概述

Mud.HttpUtils.Attributes 是 Mud.HttpUtils 的特性定义层,提供 HTTP API 声明式编程所需的全部特性标注。

仅依赖 Mud.HttpUtils.Abstractions,自身无其他外部依赖。

目标框架

  • netstandard2.0

包含内容

核心特性

特性用途目标关键属性
HttpClientApiAttribute标注 HTTP API 接口InterfaceBaseAddress, ContentType, Timeout, TokenManage, HttpClient, RegistryGroupName, IsAbstract, InheritedFrom
BasePathAttribute标注接口基础路径前缀InterfacePath

HTTP 方法特性

特性用途目标
GetAttributeGET 请求Method
PostAttributePOST 请求Method
PutAttributePUT 请求Method
DeleteAttributeDELETE 请求(支持带请求体)Method
PatchAttributePATCH 请求Method
HeadAttributeHEAD 请求Method
OptionsAttributeOPTIONS 请求Method

所有 HTTP 方法特性继承自 HttpMethodAttribute,支持以下公共属性:

属性类型说明
Routestring请求路径模板
ContentTypestring?请求内容类型
ResponseContentTypestring?响应内容类型
ResponseEnableDecryptbool响应是否启用解密

参数特性

特性用途目标关键属性
PathAttribute路径参数Parameter / PropertyName, Format, UrlEncode
QueryAttribute查询参数Parameter / PropertyName, Encode, Format
QueryMapAttribute查询参数映射(对象/字典展开)Parameter / PropertyPropertySeparator, SerializationMethod, UrlEncode, IncludeNullValues
RawQueryStringAttribute原始查询字符串ParameterPrependQuestionMark
ArrayQueryAttribute数组查询参数ParameterSeparator
HeaderAttribute请求头参数Parameter / Method / InterfaceName, Value, AliasAs, Replace
BodyAttribute请求体参数ParameterContentType, EnableEncrypt, EncryptSerializeType, EncryptPropertyName, RawString, UseStringContent
TokenAttribute令牌参数Parameter / Interface / MethodTokenType, InjectionMode, Name, Scopes, Replace, TokenManagerKey, RequiresUserId
FilePathAttribute文件路径参数ParameterBufferSize
FormContentAttribute表单内容参数Parameter / Class
FormAttribute表单字段(URL 编码)ParameterFieldName
MultipartFormAttribute多部分表单字段Parameter
UploadAttribute文件上传参数ParameterFieldName, FileName, ContentType

缓存特性

特性用途目标关键属性
CacheAttribute响应缓存标注MethodDurationSeconds, CacheKeyTemplate, VaryByUser, UseSlidingExpiration, Priority

安全与脱敏特性

特性用途目标关键属性
SensitiveDataAttribute标记敏感数据属性Property / ParameterMaskMode, PrefixLength, SuffixLength

控制特性

特性用途目标
IgnoreGeneratorAttribute忽略代码生成Interface / Method / Property / Field
AllowAnyStatusCodeAttribute允许任意 HTTP 状态码Method

事件处理特性

特性用途目标
GenerateEventHandlerAttribute生成事件处理器Class

安装

xml
<PackageReference Include="Mud.HttpUtils.Attributes" Version="x.x.x" />

使用场景

配合源代码生成器使用(推荐)

当你需要声明式定义 HTTP API 接口,配合 Mud.HttpUtils.Generator 源代码生成器自动生成实现代码时:

csharp
using Mud.HttpUtils.Attributes;

[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
public interface IUserApi
{
    [Get("/users/{id}")]
    Task<UserInfo> GetUserAsync([Path] int id);

    [Post("/users")]
    Task<UserInfo> CreateUserAsync([Body] CreateUserRequest request);

    [Delete("/users/{id}")]
    Task<bool> DeleteUserAsync([Path] int id, [Body] DeleteReason reason);

    [Get("/users")]
    Task<List<UserInfo>> SearchUsersAsync([Query] string keyword);
}

仅需特性定义

当你需要在共享类库中定义 API 接口合同,而不需要引入客户端实现或生成器时:

xml
<!-- 共享类库项目只引用 Attributes -->
<PackageReference Include="Mud.HttpUtils.Attributes" Version="x.x.x" />

HttpClientApiAttribute 详解

三种运行模式

csharp
// 模式一:默认模式(构造函数依赖 IMudAppContext)
[HttpClientApi]
public interface IDefaultApi { }

// 模式二:TokenManager 模式(构造函数依赖指定的 Token 管理器)
[HttpClientApi(TokenManage = "IFeishuAppManager")]
public interface ITokenApi { }

// 模式三:HttpClient 模式(构造函数依赖指定的 HttpClient 接口,推荐)
[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
public interface IHttpClientApi { }

注意HttpClientTokenManage 互斥,同时定义时 HttpClient 优先。 BaseAddress 构造函数和属性已废弃,请通过 AddMudHttpClient(clientName, baseAddress) 配置基地址。

全部属性

属性类型默认值说明
ContentTypestring"application/json"默认请求内容类型
Timeoutint50超时时间(秒),生成器会在注册代码中生成 client.Timeout 设置
TokenManagestring?nullToken 管理器接口类型全名
HttpClientstring?nullHttpClient 接口类型全名
RegistryGroupNamestring?null注册组名称,影响生成的注册方法名
IsAbstractboolfalse是否生成抽象类
InheritedFromstring?null继承的基类名称

BodyAttribute 详解

属性类型默认值说明
ContentTypestring?null请求体内容类型(优先级最高)
EnableEncryptboolfalse是否启用加密
EncryptSerializeTypeSerializeTypeJson加密序列化类型
EncryptPropertyNamestring"data"加密后的属性名
RawStringboolfalse是否作为原始字符串发送(不进行 JSON 序列化,也不调用 ToString())
UseStringContentboolfalse是否将参数作为字符串内容发送(调用 ToString())

RawString 用法

当需要直接发送纯文本或预格式化字符串时,使用 RawString = true

csharp
[Post("/api/content")]
Task PostContentAsync([Body(RawString = true)] string content);

UseStringContent 用法

当需要将对象调用 ToString() 后作为字符串内容发送时:

csharp
[Post("/api/text")]
Task SendTextAsync([Body(UseStringContent = true)] object message);

TokenAttribute 详解

属性类型默认值说明
TokenTypestring"TenantAccessToken"Token 类型标识符(建议使用 TokenTypes 常量类)
InjectionModeTokenInjectionModeHeaderToken 注入模式
Namestring?null自定义 Header/Query 名称
Scopesstring?null令牌作用域,多个作用域用逗号分隔
Replacebooltrue是否替换已有 Header
TokenManagerKeystring?null令牌管理器查找键,用于解耦业务概念(TokenType)和技术查找键
RequiresUserIdboolfalse是否需要用户 ID,为 true 时通过 ICurrentUserContext 获取

TokenManagerKey:当指定此值时,代码生成器将使用此键而非 TokenTypeIMudAppContext 中查找令牌管理器。此属性用于解耦业务概念和技术查找键,例如多个不同的 TokenType 可以映射到同一个 TokenManager。如果未指定,则使用 TokenType 作为查找键。

RequiresUserId:当设置为 true 时,生成的代码将通过 ICurrentUserContext 获取当前用户 ID,并将其传递给 ITokenProvider 以获取用户级令牌。如果未显式指定,则根据 TokenType 自动推断:TokenType"UserAccessToken" 时默认为 true,否则默认为 false

使用 TokenTypes 常量

csharp
using Mud.HttpUtils;

[Token(TokenTypes.TenantAccessToken)]
public interface IFeishuApi { }

[Get("/users/{id}")]
Task<User> GetUserAsync(
    [Path] int id,
    [Token(TokenTypes.UserAccessToken)] string? token = null
);

Token 注入模式

模式说明
Header0注入到 HTTP Header(默认)
Query1注入到 URL Query 参数
Path2注入到 URL Path
ApiKey3API Key 认证,通过 IApiKeyProvider 获取密钥注入到请求头
HmacSignature4HMAC 签名认证,通过 IHmacSignatureProvider 计算签名注入到请求头
csharp
// API Key 认证模式
[Token("ApiKey", InjectionMode = TokenInjectionMode.ApiKey, Name = "X-API-Key")]
public interface IApiKeyApi { }

// HMAC 签名认证模式
[Token("Hmac", InjectionMode = TokenInjectionMode.HmacSignature)]
public interface IHmacApi { }

Token Scopes

csharp
// 指定令牌作用域
[Token(TokenTypes.UserAccessToken, Scopes = "user:read,user:write")]
public interface IScopedApi { }

// 方法级别令牌
[Get("/api/user/profile")]
[Token("UserAccessToken", Scopes = "user:read")]
Task<Profile> GetProfileAsync();

TokenManagerKey 使用

csharp
// 使用 TokenManagerKey 解耦业务概念和技术查找键
[Token(TokenType = "UserAccessToken", TokenManagerKey = "FeishuUser")]
public interface IFeishuUserApi { }

// 多个不同的 TokenType 映射到同一个 TokenManager
[Token(TokenType = "UserAccessToken", TokenManagerKey = "FeishuUser")]
public interface IFeishuContactApi { }

RequiresUserId 使用

csharp
// 显式指定需要用户 ID
[Token(TokenType = "CustomToken", RequiresUserId = true)]
public interface ICustomUserApi { }

// 方法级别覆盖接口的 RequiresUserId
[Get("/api/public-data")]
[Token(RequiresUserId = false)]
Task<PublicData> GetPublicDataAsync();

CacheAttribute 详解

属性类型默认值说明
DurationSecondsint300缓存持续时间(秒)
CacheKeyTemplatestring?null缓存键模板
VaryByUserboolfalse是否按用户区分缓存
UseSlidingExpirationboolfalse是否使用滑动过期
PriorityCachePriorityNormal缓存优先级(Low / Normal / High / NeverRemove
csharp
[Get("/users/{id}")]
[Cache(60, VaryByUser = true)]
Task<User> GetUserAsync([Path] int id);

[Get("/config")]
[Cache(300, CacheKeyTemplate = "config:{0}", UseSlidingExpiration = true, Priority = CachePriority.High)]
Task<Config> GetConfigAsync();

HeaderAttribute 详解

HeaderAttribute 支持应用到参数、方法或接口级别:

属性类型默认值说明
Namestring?null请求头名称
Valueobject?null请求头值(方法/接口级别使用)
AliasAsstring?null别名,用于映射到不同的请求头名称
Replaceboolfalse是否替换已有的同名请求头
csharp
// 参数级别
[Get("/api/users")]
Task<List<User>> GetUsersAsync([Header("X-API-Key")] string apiKey);

// 方法级别(添加固定请求头)
[Get("/api/users")]
[Header("Accept", "application/json")]
[Header("X-Request-Source", "Web")]
Task<List<User>> GetUsersAsync();

// 接口级别(所有方法自动携带)
[HttpClientApi]
[Header("X-API-Version", "v2")]
public interface IUserApi { }

FormAttribute 详解

用于 application/x-www-form-urlencoded 请求,标记参数作为表单字段:

属性类型默认值说明
FieldNamestring?null表单字段名称,未设置时使用参数名
csharp
[Post("/api/login")]
Task<LoginResult> LoginAsync(
    [Form("username")] string user,
    [Form("password")] string pass);

MultipartFormAttribute 详解

用于 multipart/form-data 请求,标记参数作为多部分表单字段:

csharp
[Post("/api/upload")]
Task<UploadResult> UploadFileAsync(
    [MultipartForm] IFormFile file,
    [MultipartForm] string description);

UploadAttribute 详解

专用于文件上传场景,支持自定义字段名、文件名和内容类型:

属性类型默认值说明
FieldNamestring?null表单字段名称,未设置时使用参数名
FileNamestring?null上传的文件名,未设置时使用原始文件名
ContentTypestring?null文件内容类型(MIME),未设置时自动检测
csharp
// 基本文件上传
[Post("/api/upload")]
Task<UploadResult> UploadAsync([Upload] IFormFile file);

// 自定义字段名和文件名
[Post("/api/upload")]
Task<UploadResult> UploadDocumentAsync(
    [Upload(FieldName = "document", FileName = "report.pdf")] IFormFile file);

// 指定内容类型
[Post("/api/upload")]
Task<UploadResult> UploadImageAsync(
    [Upload(ContentType = "image/png")] IFormFile image);

SensitiveDataAttribute 详解

属性类型默认值说明
MaskModeSensitiveDataMaskModeMask脱敏模式
PrefixLengthint2前缀保留长度(Mask 模式)
SuffixLengthint2后缀保留长度(Mask 模式)

脱敏模式说明:

模式说明示例
Hide完全隐藏"***"
Mask部分遮盖"张***01"
TypeOnly仅显示类型"[String]"
csharp
public class UserRequest
{
    public string Name { get; set; }

    [SensitiveData(MaskMode = SensitiveDataMaskMode.Mask, PrefixLength = 3, SuffixLength = 4)]
    public string IdCard { get; set; }

    [SensitiveData(MaskMode = SensitiveDataMaskMode.Hide)]
    public string Password { get; set; }
}

BasePathAttribute 详解

支持在接口级别定义统一的路径前缀,避免每个方法重复书写相同的路径段:

属性类型说明
Pathstring基础路径前缀,可包含占位符(如 {tenantId}

URL 构建规则:

情况实际路径
正常[Base Address] + [Base Path] + [Method Path]
Method Path 以 / 开头[Base Address] + [Method Path](忽略 Base Path)
Method Path 是绝对 URL[Method Path](忽略 Base Address 和 Base Path)
csharp
[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
[BasePath("api/v1")]
public interface IUserApi
{
    [Get("users/{id}")]       // 实际路径: /api/v1/users/{id}
    Task<User> GetUserAsync([Path] int id);

    [Get("/admin/users")]     // 以 / 开头,忽略 BasePath,实际路径: /admin/users
    Task<List<User>> GetAllUsersAsync();
}

// 带占位符的 Base Path
[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
[BasePath("{tenantId}/api/v1")]
public interface ITenantApi
{
    [Path("tenantId")]
    string TenantId { get; set; }

    [Get("users")]
    Task<List<User>> GetUsersAsync();
}

QueryMapAttribute 详解

将对象属性或字典键值对展开为 URL 查询参数,适用于动态查询条件场景:

属性类型默认值说明
PropertySeparatorstring"_"嵌套属性名称分隔符
SerializationMethodQuerySerializationMethodToString序列化方法(ToString / Json
UrlEncodebooltrue是否对查询参数值进行 URL 编码
IncludeNullValuesboolfalse是否包含值为 null 的属性
csharp
// POCO 对象展开
public class SearchCriteria
{
    public string? Keyword { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

[Get("/api/search")]
Task<SearchResult> SearchAsync([QueryMap] SearchCriteria criteria);

// 调用: api.SearchAsync(new SearchCriteria { Keyword = "test", Page = 1, PageSize = 10 });
// 生成: /api/search?Keyword=test&Page=1&PageSize=10

// 字典类型
[Get("/api/search")]
Task<SearchResult> SearchAsync([QueryMap] IDictionary<string, object> filters);

// 自定义序列化
[Get("/api/search")]
Task<SearchResult> SearchAsync(
    [QueryMap(PropertySeparator = ".", SerializationMethod = QuerySerializationMethod.Json)]
    SearchCriteria criteria);

QuerySerializationMethod 枚举

说明
ToString调用 ToString() 方法转换为字符串(默认)
Json使用 JSON 序列化器序列化为 JSON 字符串

RawQueryStringAttribute 详解

直接传递原始查询字符串,不做任何编码或处理:

属性类型默认值说明
PrependQuestionMarkbooltrue是否在字符串前添加 ? 前缀
csharp
[Get("/api/search")]
Task<SearchResult> SearchAsync([RawQueryString] string queryString);

// 调用: api.SearchAsync("keyword=test&page=1");
// 生成: /api/search?keyword=test&page=1

接口级动态属性

PathAttributeQueryAttribute 现在支持应用到接口属性(AttributeTargets.Property),用于定义全局参数:

csharp
[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
[BasePath("{tenantId}/api/v1")]
public interface ITenantApi
{
    [Path("tenantId")]
    string TenantId { get; set; }

    [Query("apiKey")]
    string ApiKey { get; set; }

    [Query("locale")]
    string? Locale { get; set; }

    [Get("users")]
    Task<List<User>> GetUsersAsync();

    [Get("users/{id}")]
    Task<User> GetUserAsync([Path] int id);
}

// 使用
var api = serviceProvider.GetRequiredService<ITenantApi>();
api.TenantId = "tenant-123";
api.ApiKey = "my-api-key";
api.Locale = "zh-CN";

await api.GetUsersAsync();
// 实际请求: /tenant-123/api/v1/users?apiKey=my-api-key&locale=zh-CN

优先级:方法参数优先级高于接口属性。如果方法参数与接口属性同名,方法参数值会覆盖接口属性值。

设计原则

  • 轻量级:仅依赖 Abstractions,无其他传递依赖
  • netstandard2.0 兼容性:确保在尽可能多的项目中可用
  • 特性属性类型均为基础类型stringintboolenum,无复杂依赖
  • 与生成器解耦:特性可在不引用生成器的项目中使用,便于接口定义共享
  • 安全优先:内置 SensitiveDataAttribute 支持敏感数据脱敏,CacheAttribute 支持缓存控制