5.5路径片段与查询参数
添加或移除 URL 路径片段。
设置路径片段#
添加或移除 URL 路径片段。
HTTP 声明式请求通过 PathSegmentAttribute 特性来设置或移除路径片段。相应的 HTTP 声明式提取器实现为 PathSegmentDeclarativeExtractor 类型,该类型负责解析 PathSegmentAttribute 特性并构建 HttpRequestBuilder 实例所需的路径片段配置。
1. 添加路径片段
利用 PathSegmentAttribute 特性,可以便捷地在接口、方法或参数上添加路径片段。
// 在接口定义上应用,影响所有方法[PathSegment("segment1")][PathSegment("segment2")]public interface IHttpService : IHttpDeclarative{ // 在方法上应用 [PathSegment("segment3")] [PathSegment("segment4")] [Get("https://furion.net/")] Task<string> GetStringAsync(); // 在参数上应用,支持多重指定 [PathSegment("segment3")] [Get("https://furion.net/")] Task<string> GetStringAsync([PathSegment] string segment3, [QueryParam][QueryParam] int lastSegment); // 在参数上可通过 Segment 属性设定默认值,同样可为 segment 参数设定,例如 string? segment = "default" [Get("https://furion.net/")] Task<string> GetStringAsync([PathSegment(Segment = "default")] string? segment); // 冻结参数类型将被忽略 [Get("https://furion.net/")] Task<string> GetStringAsync([PathSegment] CancellationToken cancellationToken);}若存在重复的路径片段,它们将在后续追加中重复出现(如:/docs/docs/users/docs/)。
2. 移除路径片段
PathSegmentAttribute 特性中,设置 Remove = true,即表示移除该路径片段。在接口、方法或参数上应用有效。
[PathSegment("segment1")] // 添加 segment1 路径片段[PathSegment("segment2", Remove = true)] // 标记 segment2 为待移除public interface IHttpService : IHttpDeclarative{ [PathSegment("segment2")] // 添加 segment2 路径片段 [PathSegment("segment3")] // 添加 segment2 路径片段 [PathSegment("segment3", Remove = true)] // 标记 segment3 为待移除 [Get("https://furion.net/")] Task<string> GetStringAsync([PathSegment(Remove = true)] string seg); // 动态根据 seg 值标记为待移除}在发送 HTTP 请求之前,将移除配置中指定的待移除路径片段集合。也就是说,移除操作会在所有设置操作调用之后执行。
在上述示例中,尽管 GetStringAsync 方法尝试通过 [PathSegment] 特性添加 segment2 和 segment3 路径片段,但由于随后分别有 [PathSegment("segment2", Remove = true)] 和 [PathSegment("segment3", Remove = true)] 特性仅指定了 Remove = true 属性,因此这两个键在最终构建请求 URL 时会被移除。只有 segment1 路径片段会保留在请求 URL 中。
PathSegmentAttribute 包含以下构造函数和属性:
-
构造函数:
new():作用于参数时有效,表示添加路径片段,路径片段为参数值。new(segment):作用于方法或接口时,则表示添加指定路径片段操作;作用于参数且参数值为null时,表示添加路径片段,路径片段为参数segment的值。
-
属性:
Segment:路径片段(string类型),特性作用于参数且参数值为null时,可用作默认值。Remove:是否标记为待删除(bool类型),默认值为false(追加)。
设置查询参数(URL 参数)#
添加、修改或移除 URL 查询参数。
HTTP 声明式请求通过 QueryParamAttribute 特性来设置或移除查询参数。相应的 HTTP 声明式提取器实现为 QueryParamDeclarativeExtractor 类型,该类型负责解析 QueryParamAttribute 特性并构建 HttpRequestBuilder 实例所需的查询参数配置。
1. 添加查询参数
利用 QueryParamAttribute 特性,可以便捷地在接口、方法或参数上添加查询参数。
// 在接口定义上应用,影响所有方法[QueryParam("query1", "value1")][QueryParam("query2", "value2")]public interface IHttpService : IHttpDeclarative{ // 在方法上应用 [QueryParam("query3", "value3")] [QueryParam("query4", "value4")] [Get("https://furion.net/")] Task<string> GetStringAsync(); // 在参数上应用,支持 AliasAs 属性指定别名,且可多重指定 [QueryParam("query3", "value3")] [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam] string query4, [QueryParam][QueryParam(AliasAs = "query5")] int lastQuery); // 在参数上可通过 Value 属性设定默认值,同样可为 age 参数设定,例如 int? age = 30 [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam(Value = 30)] int? age); // 支持将对象作为查询参数,并指定前缀 [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam(Prefix = "user")] object obj); // 支持 [AliasAs] 定义别名 [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam][AliasAs("query5")] int lastQuery); // 支持忽略空值参数,若 str1 值为 null 则忽略 [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam(IgnoreNullValues = true)] string? str1, [QueryParam] string? str2); // 支持 format 格式化 [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam(Format = "yyyyMMdd")] DateTime date); // 冻结参数类型将被忽略 [Get("https://furion.net/")] Task<string> GetStringAsync([QueryParam] CancellationToken cancellationToken);}若存在重复的查询参数键,它们将合并成多个键值对(如 key1=value1&key1=value2)。通过设置 Replace = true 属性,可以覆盖先前的查询参数和原始 URL 地址参数。默认情况下,值为 null 的查询参数会被添加到 URL 中;若需忽略这些参数,可设置 IgnoreNullValues = true。
2. 移除查询参数
QueryParamAttribute 特性中,仅指定查询参数键而不赋值,即表示移除该参数。在接口或方法上应用有效。
[QueryParam("query1", "value1")] // 添加 query1 参数[QueryParam("query2")] // 标记 query2 为待移除public interface IHttpService : IHttpDeclarative{ [QueryParam("query2", "value2")] // 添加 query2 参数 [QueryParam("query3", "value3")] // 添加 query3 参数 [QueryParam("query3")] // 标记 query3 为待移除 [Get("https://furion.net/")] Task<string> GetStringAsync();}在发送 HTTP 请求之前,将移除配置中指定的待移除查询参数集合。也就是说,移除操作会在所有设置操作调用之后执行。
在上述示例中,尽管 GetStringAsync 方法尝试通过 [QueryParam] 特性添加 query2 和 query3 参数,但由于随后分别有 [QueryParam("query2")] 和 [QueryParam("query3")] 特性仅指定了查询参数键而未赋值,因此这两个键在最终构建请求 URL 时会被移除。只有 query1 参数会保留在请求 URL 中。
3. URL 参数格式化程序
在设置 HTTP 请求的查询参数时,框架会将参数键和值传递给 IUrlParameterFormatter 进行格式化。默认实现 UrlParameterFormatter 会为每个值生成一个 key=value 形式的键值对。但某些类型(如 DateTime)可能需要特殊处理,或希望改变整个键值对的输出形态(例如将多个值输出为 key[0]=val1&key[1]=val2 这样的数组格式),此时可以通过自定义格式化程序实现。
以下示例展示如何重写 Format 方法,以便将 DateTime 类型的值格式化为 yyyyMMdd 格式,其余类型使用默认处理:
public class CustomUrlParameterFormatter : UrlParameterFormatter{ /// <inheritdoc /> public override IEnumerable<KeyValuePair<string, string?>>? Format(UrlFormattingContext context, string key, IEnumerable<object?> values) { foreach (var value in values) { if (value is DateTime dateTime) { yield return new(key, dateTime.ToString("yyyyMMdd")); // 格式化 continue; } yield return new(key, FormatValue(context, value)); } }}完成自定义格式化程序后,可以在配置 HttpRemoteOptions 时将其注册为默认的 URL 参数格式化器:
services.AddHttpRemote(builder => {}) .ConfigureOptions(options => { options.UrlParameterFormatter = new CustomUrlParameterFormatter(); });如此一来,在构建 URL 查询参数时,若遇到 DateTime 类型的值,框架将自动将其格式化为 yyyyMMdd 格式的字符串,从而确保输出符合预期。
4. URL 参数排序
尽管对 URL 查询参数排序的需求相对少见,但在一些对安全性要求较高的系统中,往往需要验证参数的顺序。框架为此提供了排序支持,排序对象为最终的键值对集合:
HttpRequestBuilder.Get("https://furion.net/") .WithQueryParameters(new { name = "furion", id = 1}) .SetQueryParametersSorter(pairs => pairs.OrderBy(kv => kv.Key));通过 .SetQueryParametersSorter() 方法配置查询参数排序规则。该方法接收一个 KeyValuePair<string, string?> 序列,返回排序后的新序列。为 null 时不排序(原始添加顺序)。
QueryParamAttribute 包含以下构造函数和属性:
-
构造函数:
new():作用于参数时有效,表示添加查询参数,默认键为参数名。new(name):作用于方法或接口时,则表示移除指定查询参数操作;作用于参数时,表示添加查询参数,键为参数name的值。new(name, value):作用于接口、方法或参数,表示添加查询参数,键为参数name的值,优先级低于AliasAs属性。
-
属性:
Name:查询参数键(string类型),优先级低于AliasAs属性。Value:查询参数的值(object类型),当特性作用于参数时,表示默认值。AliasAs:查询参数键别名(string类型),优先级高于Name属性。Prefix:查询参数前缀(string类型),仅对象参数有效。Replace:是否替换已存在的查询参数(bool类型),默认值为false(追加)。IgnoreNullValues:是否忽略空值(null)的查询参数(bool类型),默认值为false(不忽略)。Format:要使用的格式(string?类型),仅当Value实现IFormattable时有效。