Skip to content

Commit 15ebf05

Browse files
authored
Merge pull request #222 from EzrealJ/master
add docs files
2 parents 78a4470 + 1b2c000 commit 15ebf05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2654
-0
lines changed

docs/Readme.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
home: true
3+
heroImage: /logo.png
4+
heroText: WebApiClient
5+
tagline: 使用C#接口描述你的http接口
6+
actions:
7+
- text: 快速开始 💡
8+
link: /guide/
9+
type: primary
10+
- text: 安装
11+
link: /reference/nuget
12+
type: default
13+
- text: 旧版文档
14+
link: /old/
15+
type: default
16+
features:
17+
- title: AOT/JIT
18+
details: ⛳ 支持编译时,运行时生成代理类,提高运行时性能和兼容性
19+
- title: 多样序列化
20+
details: 🛠 默认System.Text.Json,Newtonsoft.Json,同样也支持XML处理
21+
- title: 语法分析
22+
details: 💡提供接口声明的语法分析与提示,帮助开发者声明接口时避免使用不当的语法。
23+
- title: 功能完备
24+
details: 🌳支持多种拦截器和过滤器、日志、重试、缓存、异常处理功能
25+
- title: 快速接入
26+
details: ✒ 支持OAuth2与token管理扩展包,方便实现身份认证和授权
27+
- title: 自动生成
28+
details: 💻 支持将本地或远程OpenApi文档解析生成WebApiClientCore接口代码的dotnet tool,简化接口声明的工作量
29+
footer: MIT Licensed | Copyright © WebApiClient
30+
---

docs/guide/attribute.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
# 常用内置特性
3+
4+
内置特性指框架内提供的一些特性,拿来即用就能满足一般情况下的各种应用。当然,开发者也可以在实际应用中,编写满足特定场景需求的特性,然后将自定义特性修饰到接口、方法或参数即可。
5+
6+
> 执行前顺序
7+
8+
参数值验证 -> IApiActionAttribute -> IApiParameterAttribute -> IApiReturnAttribute -> IApiFilterAttribute
9+
10+
> 执行后顺序
11+
12+
IApiReturnAttribute -> 返回值验证 -> IApiFilterAttribute
13+
14+
## Return特性
15+
16+
特性名称 | 功能描述 | 备注
17+
---|---|---|
18+
RawReturnAttribute | 处理原始类型返回值 | 缺省也生效
19+
JsonReturnAttribute | 处理Json模型返回值 | 缺省也生效
20+
XmlReturnAttribute | 处理Xml模型返回值 | 缺省也生效
21+
NoneReturnAttribute | 处理空返回值 | 缺省也生效
22+
23+
## 常用Action特性
24+
25+
特性名称 | 功能描述 | 备注
26+
---|---|---|
27+
HttpHostAttribute | 请求服务http绝对完整主机域名| 优先级比Options配置低
28+
HttpGetAttribute | 声明Get请求方法与路径| 支持null、绝对或相对路径
29+
HttpPostAttribute | 声明Post请求方法与路径| 支持null、绝对或相对路径
30+
HttpPutAttribute | 声明Put请求方法与路径| 支持null、绝对或相对路径
31+
HttpDeleteAttribute | 声明Delete请求方法与路径| 支持null、绝对或相对路径
32+
*HeaderAttribute* | 声明请求头 | 常量值
33+
*TimeoutAttribute* | 声明超时时间 | 常量值
34+
*FormFieldAttribute* | 声明Form表单字段与值 | 常量键和值
35+
*FormDataTextAttribute* | 声明FormData表单字段与值 | 常量键和值
36+
37+
## 常用Parameter特性
38+
39+
特性名称 | 功能描述 | 备注
40+
---|---|---|
41+
PathQueryAttribute | 参数值的键值对作为url路径参数或query参数的特性 | 缺省特性的参数默认为该特性
42+
FormContentAttribute | 参数值的键值对作为x-www-form-urlencoded表单 |
43+
FormDataContentAttribute | 参数值的键值对作为multipart/form-data表单 |
44+
JsonContentAttribute | 参数值序列化为请求的json内容 |
45+
XmlContentAttribute | 参数值序列化为请求的xml内容 |
46+
UriAttribute | 参数值作为请求uri | 只能修饰第一个参数
47+
ParameterAttribute | 聚合性的请求参数声明 | 不支持细颗粒配置
48+
*HeaderAttribute* | 参数值作为请求头 |
49+
*TimeoutAttribute* | 参数值作为超时时间 | 值不能大于HttpClient的Timeout属性
50+
*FormFieldAttribute* | 参数值作为Form表单字段与值 | 只支持简单类型参数
51+
*FormDataTextAttribute* | 参数值作为FormData表单字段与值 | 只支持简单类型参数
52+
53+
## Filter特性
54+
55+
特性名称 | 功能描述| 备注
56+
---|---|---|
57+
ApiFilterAttribute | Filter特性抽象类 |
58+
LoggingFilterAttribute | 请求和响应内容的输出为日志的过滤器 |
59+
60+
## 自解释参数类型
61+
62+
类型名称 | 功能描述 | 备注
63+
---|---|---|
64+
FormDataFile | form-data的一个文件项 | 无需特性修饰,等效于FileInfo类型
65+
JsonPatchDocument | 表示将JsonPatch请求文档 | 无需特性修饰

docs/guide/config.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# 配置
2+
3+
## 全局配置
4+
5+
2.0以后的版本,提供services.AddWebApiClient()的全局配置功能,支持提供自定义的IHttpApiActivator<>、IApiActionDescriptorProvider、IApiActionInvokerProvider和IResponseCacheProvider。
6+
7+
## 接口注册与选项
8+
9+
调用`services.AddHttpApi<IUserApi>()`即可完成接口注册,
10+
每个接口的选项对应为`HttpApiOptions`,选项名称通过HttpApi.GetName()方法获取得到。
11+
12+
## 在IHttpClientBuilder配置
13+
14+
```csharp
15+
services
16+
.AddHttpApi<IUserApi>()
17+
.ConfigureHttpApi(Configuration.GetSection(nameof(IUserApi)))
18+
.ConfigureHttpApi(o =>
19+
{
20+
// 符合国情的不标准时间格式,有些接口就是这么要求必须不标准
21+
o.JsonSerializeOptions.Converters.Add(new JsonDateTimeConverter("yyyy-MM-dd HH:mm:ss"));
22+
});
23+
```
24+
25+
配置文件的json
26+
27+
```json
28+
{
29+
"IUserApi": {
30+
"HttpHost": "http://www.webappiclient.com/",
31+
"UseParameterPropertyValidate": false,
32+
"UseReturnValuePropertyValidate": false,
33+
"JsonSerializeOptions": {
34+
"IgnoreNullValues": true,
35+
"WriteIndented": false
36+
}
37+
}
38+
}
39+
```
40+
41+
## 在IServiceCollection配置
42+
43+
```csharp
44+
services
45+
.ConfigureHttpApi<IUserApi>(Configuration.GetSection(nameof(IUserApi)))
46+
.ConfigureHttpApi<IUserApi>(o =>
47+
{
48+
// 符合国情的不标准时间格式,有些接口就是这么要求必须不标准
49+
o.JsonSerializeOptions.Converters.Add(new JsonDateTimeConverter("yyyy-MM-dd HH:mm:ss"));
50+
});
51+
```

docs/guide/core-analyzers.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# 编译时语法分析
2+
3+
WebApiClientCore.Analyzers提供接口声明的语法分析与提示,帮助开发者声明接口时避免使用不当的语法。
4+
5+
* 1.x版本,接口继承IHttpApi才获得语法分析提示
6+
* 2.0以后的版本,不继承IHttpApi也获得语法分析提示

docs/guide/data-validation.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 数据验证
2+
3+
## 参数值验证
4+
5+
对于参数值,支持ValidationAttribute特性修饰来验证值。
6+
7+
```csharp
8+
public interface IUserApi
9+
{
10+
[HttpGet("api/users/{email}")]
11+
Task<User> GetAsync([EmailAddress, Required] string email);
12+
}
13+
```
14+
15+
## 参数或返回模型属性验证
16+
17+
```csharp
18+
public interface IUserApi
19+
{
20+
[HttpPost("api/users")]
21+
Task<User> PostAsync([Required][XmlContent] User user);
22+
}
23+
24+
public class User
25+
{
26+
[Required]
27+
[StringLength(10, MinimumLength = 1)]
28+
public string Account { get; set; }
29+
30+
[Required]
31+
[StringLength(10, MinimumLength = 1)]
32+
public string Password { get; set; }
33+
}
34+
```

docs/guide/deformed-interface.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# 适配畸形接口
2+
3+
在实际应用场景中,常常会遇到一些设计不标准的畸形接口,主要是早期还没有restful概念时期的接口,我们要区分分析这些接口,包装为友好的客户端调用接口。
4+
5+
## 不友好的参数名别名
6+
7+
例如服务器要求一个Query参数的名字为`field-Name`,这个是c#关键字或变量命名不允许的,我们可以使用`[AliasAsAttribute]`来达到这个要求:
8+
9+
```csharp
10+
public interface IDeformedApi
11+
{
12+
[HttpGet("api/users")]
13+
ITask<string> GetAsync([AliasAs("field-Name")] string fieldName);
14+
}
15+
```
16+
17+
然后最终请求uri变为api/users/?field-name=`fileNameValue`
18+
19+
## Form的某个字段为json文本
20+
21+
字段 | 值
22+
---|---
23+
field1 | someValue
24+
field2 | {"name":"sb","age":18}
25+
26+
对应强类型模型是
27+
28+
```csharp
29+
class Field2
30+
{
31+
public string Name {get; set;}
32+
33+
public int Age {get; set;}
34+
}
35+
```
36+
37+
常规下我们得把field2的实例json序列化得到json文本,然后赋值给field2这个string属性,使用[JsonFormField]特性可以轻松帮我们自动完成Field2类型的json序列化并将结果字符串作为表单的一个字段。
38+
39+
```csharp
40+
public interface IDeformedApi
41+
{
42+
Task PostAsync([FormField] string field1, [JsonFormField] Field2 field2)
43+
}
44+
```
45+
46+
## Form提交嵌套的模型
47+
48+
字段 | 值
49+
---|---|
50+
|filed1 |someValue|
51+
|field2.name | sb|
52+
|field2.age | 18|
53+
54+
其对应的json格式为
55+
56+
```json
57+
{
58+
"field1" : "someValue",
59+
"filed2" : {
60+
"name" : "sb",
61+
"age" : 18
62+
}
63+
}
64+
```
65+
66+
合理情况下,对于复杂嵌套结构的数据模型,应当使用applicaiton/json,但接口要求必须使用Form提交,我可以配置KeyValueSerializeOptions来达到这个格式要求:
67+
68+
```csharp
69+
services.AddHttpApi<IDeformedApi>(o =>
70+
{
71+
o.KeyValueSerializeOptions.KeyNamingStyle = KeyNamingStyle.FullName;
72+
});
73+
```
74+
75+
## 响应未指明ContentType
76+
77+
明明响应的内容肉眼看上是json内容,但服务响应头里没有ContentType告诉客户端这内容是json,这好比客户端使用Form或json提交时就不在请求头告诉服务器内容格式是什么,而是让服务器猜测一样的道理。
78+
79+
解决办法是在Interface或Method声明`[JsonReturn]`特性,并设置其EnsureMatchAcceptContentType属性为false,表示ContentType不是期望值匹配也要处理。
80+
81+
```csharp
82+
[JsonReturn(EnsureMatchAcceptContentType = false)]
83+
public interface IDeformedApi
84+
{
85+
}
86+
```
87+
88+
## 类签名参数或apikey参数
89+
90+
例如每个请求的url额外的动态添加一个叫sign的参数,这个sign可能和请求参数值有关联,每次都需要计算。
91+
92+
我们可以自定义ApiFilterAttribute来实现自己的sign功能,然后把自定义Filter声明到Interface或Method即可
93+
94+
```csharp
95+
class SignFilterAttribute : ApiFilterAttribute
96+
{
97+
public override Task OnRequestAsync(ApiRequestContext context)
98+
{
99+
var signService = context.HttpContext.ServiceProvider.GetService<SignService>();
100+
var sign = signService.SignValue(DateTime.Now);
101+
context.HttpContext.RequestMessage.AddUrlQuery("sign", sign);
102+
return Task.CompletedTask;
103+
}
104+
}
105+
106+
[SignFilter]
107+
public interface IDeformedApi
108+
{
109+
...
110+
}
111+
```
112+
113+
## 表单字段排序
114+
115+
不知道是哪门公司起的所谓的“签名算法”,往往要字段排序等。
116+
117+
```csharp
118+
class SortedFormContentAttribute : FormContentAttribute
119+
{
120+
protected override IEnumerable<KeyValue> SerializeToKeyValues(ApiParameterContext context)
121+
{
122+
这里可以排序、加上其它衍生字段等
123+
return base.SerializeToKeyValues(context).OrderBy(item => item.Key);
124+
}
125+
}
126+
127+
public interface IDeformedApi
128+
{
129+
[HttpGet("/path")]
130+
Task<HttpResponseMessage> PostAsync([SortedFormContent] Model model);
131+
}
132+
```

docs/guide/diy-request-response.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
# 自定义请求内容与响应内容解析
3+
4+
除了常见的xml或json响应内容要反序列化为强类型结果模型,你可能会遇到其它的二进制协议响应内容,比如google的ProtoBuf二进制内容。
5+
6+
## 1 编写相关自定义特性
7+
8+
### 自定义请求内容处理特性
9+
10+
```csharp
11+
public class ProtobufContentAttribute : HttpContentAttribute
12+
{
13+
public string ContentType { get; set; } = "application/x-protobuf";
14+
15+
protected override Task SetHttpContentAsync(ApiParameterContext context)
16+
{
17+
var stream = new MemoryStream();
18+
if (context.ParameterValue != null)
19+
{
20+
Serializer.NonGeneric.Serialize(stream, context.ParameterValue);
21+
stream.Position = 0L;
22+
}
23+
24+
var content = new StreamContent(stream);
25+
content.Headers.ContentType = new MediaTypeHeaderValue(this.ContentType);
26+
context.HttpContext.RequestMessage.Content = content;
27+
return Task.CompletedTask;
28+
}
29+
}
30+
```
31+
32+
### 自定义响应内容解析特性
33+
34+
```csharp
35+
public class ProtobufReturnAttribute : ApiReturnAttribute
36+
{
37+
public ProtobufReturnAttribute(string acceptContentType = "application/x-protobuf")
38+
: base(new MediaTypeWithQualityHeaderValue(acceptContentType))
39+
{
40+
}
41+
42+
public override async Task SetResultAsync(ApiResponseContext context)
43+
{
44+
var stream = await context.HttpContext.ResponseMessage.Content.ReadAsStreamAsync();
45+
context.Result = Serializer.NonGeneric.Deserialize(context.ApiAction.Return.DataType.Type, stream);
46+
}
47+
}
48+
```
49+
50+
## 2 应用相关自定义特性
51+
52+
```csharp
53+
[ProtobufReturn]
54+
public interface IProtobufApi
55+
{
56+
[HttpPut("/users/{id}")]
57+
Task<User> UpdateAsync([Required, PathQuery] string id, [ProtobufContent] User user);
58+
}
59+
```

0 commit comments

Comments
 (0)