Skip to content

Commit df68822

Browse files
committed
Content-Type为null时无条件成功匹配
1 parent 66ede4a commit df68822

File tree

12 files changed

+164
-85
lines changed

12 files changed

+164
-85
lines changed

WebApiClientCore.Extensions.OAuths/TokenProviders/OAuth2TokenClient.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ public OAuth2TokenClient(IHttpClientFactory httpClientFactory, IOptionsMonitor<H
8383

8484
var response = await this.httpClientFactory.CreateClient().PostAsync(endpoint, formContent);
8585
var utf8Json = await response.Content.ReadAsUtf8ByteArrayAsync();
86+
if (utf8Json.Length == 0)
87+
{
88+
return default;
89+
}
8690
return JsonSerializer.Deserialize<TokenResult>(utf8Json, this.httpApiOptions.JsonDeserializeOptions);
8791
}
8892
}

WebApiClientCore/ApiResponseContextExtensions.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ public static class ApiResponseContextExtensions
2020
/// <returns></returns>
2121
public static async Task<object?> JsonDeserializeAsync(this ApiResponseContext context, Type objType)
2222
{
23-
if (context.HttpContext.ResponseMessage == null)
24-
{
25-
return objType.DefaultValue();
26-
}
27-
28-
var content = context.HttpContext.ResponseMessage.Content;
29-
if (content == null)
23+
var response = context.HttpContext.ResponseMessage;
24+
if (response == null)
3025
{
3126
return objType.DefaultValue();
3227
}
3328

29+
var content = response.Content;
3430
var encoding = content.GetEncoding();
3531
var options = context.HttpContext.HttpApiOptions.JsonDeserializeOptions;
3632

3733
if (Encoding.UTF8.Equals(encoding) == false)
3834
{
3935
var byteArray = await content.ReadAsByteArrayAsync().ConfigureAwait(false);
36+
if (byteArray.Length == 0)
37+
{
38+
return objType.DefaultValue();
39+
}
4040
var utf8Json = Encoding.Convert(encoding, Encoding.UTF8, byteArray);
4141
return JsonSerializer.Deserialize(utf8Json, objType, options);
4242
}
@@ -49,7 +49,9 @@ public static class ApiResponseContextExtensions
4949
else
5050
{
5151
var utf8Json = await content.ReadAsByteArrayAsync().ConfigureAwait(false);
52-
return JsonSerializer.Deserialize(utf8Json, objType, options);
52+
return utf8Json.Length == 0
53+
? objType.DefaultValue()
54+
: JsonSerializer.Deserialize(utf8Json, objType, options);
5355
}
5456
}
5557

@@ -61,13 +63,15 @@ public static class ApiResponseContextExtensions
6163
/// <returns></returns>
6264
public static async Task<object?> XmlDeserializeAsync(this ApiResponseContext context, Type objType)
6365
{
64-
if (context.HttpContext.ResponseMessage == null)
66+
var response = context.HttpContext.ResponseMessage;
67+
if (response == null)
6568
{
6669
return objType.DefaultValue();
6770
}
6871

72+
var content = response.Content;
6973
var options = context.HttpContext.HttpApiOptions.XmlDeserializeOptions;
70-
var xml = await context.HttpContext.ResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
74+
var xml = await content.ReadAsStringAsync().ConfigureAwait(false);
7175
return XmlSerializer.Deserialize(xml, objType, options);
7276
}
7377
}

WebApiClientCore/Attributes/ReturnAttributes/ApiReturnAttribute.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,22 @@ public Task OnRequestAsync(ApiRequestContext context)
8686
/// <returns></returns>
8787
public async Task OnResponseAsync(ApiResponseContext context)
8888
{
89-
if (context.ActionDescriptor.Return.DataType.IsRawType == true)
89+
var dataType = context.ActionDescriptor.Return.DataType;
90+
if (dataType.IsRawType == true)
9091
{
9192
return;
9293
}
9394

94-
var contenType = context.HttpContext.ResponseMessage?.Content.Headers.ContentType;
95-
if (this.EnsureMatchAcceptContentType && this.IsMatchAcceptContentType(contenType) == false)
95+
var response = context.HttpContext.ResponseMessage;
96+
if (response == null)
97+
{
98+
return;
99+
}
100+
101+
var contenType = response.Content.Headers.ContentType;
102+
if (contenType != null
103+
&& this.EnsureMatchAcceptContentType
104+
&& this.IsMatchAcceptContentType(contenType) == false)
96105
{
97106
return;
98107
}
@@ -101,15 +110,16 @@ public async Task OnResponseAsync(ApiResponseContext context)
101110
await this.SetResultAsync(context).ConfigureAwait(false);
102111
}
103112

113+
104114
/// <summary>
105115
/// 指示响应的ContentType与AcceptContentType是否匹配
106116
/// 返回false则调用下一个ApiReturnAttribute来处理响应结果
107117
/// </summary>
108118
/// <param name="responseContentType">响应的ContentType</param>
109119
/// <returns></returns>
110-
protected virtual bool IsMatchAcceptContentType(MediaTypeHeaderValue? responseContentType)
120+
protected virtual bool IsMatchAcceptContentType(MediaTypeHeaderValue responseContentType)
111121
{
112-
return MediaTypeUtil.IsMatch(this.AcceptContentType.MediaType, responseContentType?.MediaType);
122+
return MediaTypeUtil.IsMatch(this.AcceptContentType.MediaType, responseContentType.MediaType);
113123
}
114124

115125
/// <summary>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace WebApiClientCore.Attributes
2+
{
3+
/// <summary>
4+
/// 表示将结果设置为返回类型的自定义值抽象特性
5+
/// </summary>
6+
public abstract class CustomValueReturnAttribute : SpecialReturnAttribute
7+
{
8+
/// <summary>
9+
/// 将结果设置为返回类型的自定义值抽象特性
10+
/// </summary>
11+
public CustomValueReturnAttribute()
12+
: base()
13+
{
14+
}
15+
16+
/// <summary>
17+
/// 将结果设置为返回类型的自定义值抽象特性
18+
/// </summary>
19+
/// <param name="acceptQuality">accept的质比</param>
20+
public CustomValueReturnAttribute(double acceptQuality)
21+
: base(acceptQuality)
22+
{
23+
}
24+
25+
/// <summary>
26+
/// 指示是否可以设置结果
27+
/// </summary>
28+
/// <param name="context">上下文</param>
29+
/// <returns></returns>
30+
protected sealed override bool CanSetResult(ApiResponseContext context)
31+
{
32+
return context.ActionDescriptor.Return.DataType.IsRawType == false;
33+
}
34+
}
35+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Net.Http;
2+
using System.Threading.Tasks;
3+
4+
namespace WebApiClientCore.Attributes
5+
{
6+
/// <summary>
7+
/// 表示将结果设置为返回类型的默认值抽象特性
8+
/// </summary>
9+
public abstract class DefaultValueReturnAttribute : CustomValueReturnAttribute
10+
{
11+
/// <summary>
12+
/// 将结果设置为返回类型的默认值抽象特性
13+
/// </summary>
14+
public DefaultValueReturnAttribute()
15+
: base()
16+
{
17+
}
18+
19+
/// <summary>
20+
/// 将结果设置为返回类型的默认值抽象特性
21+
/// </summary>
22+
/// <param name="acceptQuality">accept的质比</param>
23+
public DefaultValueReturnAttribute(double acceptQuality)
24+
: base(acceptQuality)
25+
{
26+
}
27+
28+
/// <summary>
29+
/// 如果有结果值,则设置结果值到上下文的Result属性
30+
/// </summary>
31+
/// <param name="context">上下文</param>
32+
/// <returns></returns>
33+
public sealed override Task SetResultAsync(ApiResponseContext context)
34+
{
35+
var response = context.HttpContext.ResponseMessage;
36+
if (response != null && this.CanUseDefaultValue(response))
37+
{
38+
context.Result = context.ActionDescriptor.Return.DataType.Type.DefaultValue();
39+
}
40+
41+
return Task.CompletedTask;
42+
}
43+
44+
/// <summary>
45+
/// 指示是否将结果设置为返回类型的默认值
46+
/// </summary>
47+
/// <param name="responseMessage">响应消息</param>
48+
/// <returns></returns>
49+
protected abstract bool CanUseDefaultValue(HttpResponseMessage responseMessage);
50+
}
51+
}

WebApiClientCore/Attributes/ReturnAttributes/JsonReturnAttribute.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ public JsonReturnAttribute(double acceptQuality)
4343
/// </summary>
4444
/// <param name="responseContentType">响应的ContentType</param>
4545
/// <returns></returns>
46-
protected override bool IsMatchAcceptContentType(MediaTypeHeaderValue? responseContentType)
46+
protected override bool IsMatchAcceptContentType(MediaTypeHeaderValue responseContentType)
4747
{
4848
return base.IsMatchAcceptContentType(responseContentType)
49-
|| MediaTypeUtil.IsMatch(textJson, responseContentType?.MediaType)
50-
|| MediaTypeUtil.IsMatch(problemJson, responseContentType?.MediaType);
49+
|| MediaTypeUtil.IsMatch(textJson, responseContentType.MediaType)
50+
|| MediaTypeUtil.IsMatch(problemJson, responseContentType.MediaType);
5151
}
5252

5353
/// <summary>
Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
using System.Net;
22
using System.Net.Http;
3-
using System.Threading.Tasks;
43

54
namespace WebApiClientCore.Attributes
65
{
76
/// <summary>
8-
/// 表示无内容的结果特性
9-
/// 将结果设置为类型的默认值
7+
/// 表示响应状态为204时将结果设置为返回类型的默认值特性
108
/// </summary>
11-
public sealed class NoneReturnAttribute : SpecialReturnAttribute
9+
public sealed class NoneReturnAttribute : DefaultValueReturnAttribute
1210
{
1311
/// <summary>
14-
/// 无内容的结果特性
12+
/// 响应状态为204时将结果设置为返回类型的默认值特性
1513
/// </summary>
1614
public NoneReturnAttribute()
1715
: base()
1816
{
1917
}
2018

2119
/// <summary>
22-
/// 无内容的结果特性
20+
/// 响应状态为204时将结果设置为返回类型的默认值特性
2321
/// </summary>
2422
/// <param name="acceptQuality">accept的质比</param>
2523
public NoneReturnAttribute(double acceptQuality)
@@ -28,40 +26,19 @@ public NoneReturnAttribute(double acceptQuality)
2826
}
2927

3028
/// <summary>
31-
/// 设置结果值
29+
/// 指示是否将结果设置为返回类型的默认值
3230
/// </summary>
33-
/// <param name="context">上下文</param>
31+
/// <param name="responseMessage">响应消息</param>
3432
/// <returns></returns>
35-
public override Task SetResultAsync(ApiResponseContext context)
33+
protected override bool CanUseDefaultValue(HttpResponseMessage responseMessage)
3634
{
37-
if (context.ActionDescriptor.Return.DataType.IsRawType == true)
38-
{
39-
return Task.CompletedTask;
40-
}
41-
42-
var response = context.HttpContext.ResponseMessage;
43-
if (response != null && IsNoContent(response))
44-
{
45-
context.Result = context.ActionDescriptor.Return.DataType.Type.DefaultValue();
46-
}
47-
48-
return Task.CompletedTask;
49-
}
50-
51-
/// <summary>
52-
/// 指示是否为无内容
53-
/// </summary>
54-
/// <param name="response"></param>
55-
/// <returns></returns>
56-
private static bool IsNoContent(HttpResponseMessage response)
57-
{
58-
if (response.StatusCode == HttpStatusCode.NoContent)
35+
if (responseMessage.StatusCode == HttpStatusCode.NoContent)
5936
{
6037
return true;
6138
}
6239

63-
var status = (int)response.StatusCode;
64-
return status >= 200 && status <= 299 && response.Content.Headers.ContentLength == 0;
40+
return responseMessage.IsSuccessStatusCode
41+
&& responseMessage.Content.Headers.ContentLength == 0;
6542
}
6643
}
6744
}

WebApiClientCore/Attributes/ReturnAttributes/RawReturnAttribute.cs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.Net;
2-
using System.Threading.Tasks;
1+
using System.Threading.Tasks;
32
using WebApiClientCore.Exceptions;
43

54
namespace WebApiClientCore.Attributes
@@ -34,26 +33,35 @@ public RawReturnAttribute(double acceptQuality)
3433
{
3534
}
3635

36+
/// <summary>
37+
/// 指示是否可以设置结果
38+
/// </summary>
39+
/// <param name="context">上下文</param>
40+
/// <returns></returns>
41+
protected override bool CanSetResult(ApiResponseContext context)
42+
{
43+
return context.ActionDescriptor.Return.DataType.IsRawType;
44+
}
45+
3746
/// <summary>
3847
/// 设置结果值
3948
/// </summary>
4049
/// <param name="context">上下文</param>
4150
/// <returns></returns>
4251
public async override Task SetResultAsync(ApiResponseContext context)
4352
{
44-
var dataType = context.ActionDescriptor.Return.DataType;
4553
var response = context.HttpContext.ResponseMessage;
46-
47-
if (dataType.IsRawType == false || response == null)
54+
if (response == null)
4855
{
4956
return;
5057
}
5158

52-
if (this.EnsureSuccessStatusCode && IsSuccessStatusCode(response.StatusCode) == false)
59+
if (this.EnsureSuccessStatusCode && response.IsSuccessStatusCode == false)
5360
{
5461
throw new ApiResponseStatusException(response);
5562
}
5663

64+
var dataType = context.ActionDescriptor.Return.DataType;
5765
if (dataType.IsRawHttpResponseMessage == true)
5866
{
5967
context.Result = response;
@@ -71,16 +79,5 @@ public async override Task SetResultAsync(ApiResponseContext context)
7179
context.Result = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
7280
}
7381
}
74-
75-
/// <summary>
76-
/// 指示http状态码是否为成功的状态码
77-
/// </summary>
78-
/// <param name="statusCode">http状态码</param>
79-
/// <returns></returns>
80-
private static bool IsSuccessStatusCode(HttpStatusCode statusCode)
81-
{
82-
var status = (int)statusCode;
83-
return status >= 200 && status <= 299;
84-
}
8582
}
8683
}

WebApiClientCore/Attributes/ReturnAttributes/SpecialReturnAttribute.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,23 @@ public Task OnRequestAsync(ApiRequestContext context)
6464
/// <returns></returns>
6565
public Task OnResponseAsync(ApiResponseContext context)
6666
{
67-
return this.SetResultAsync(context);
67+
return this.CanSetResult(context)
68+
? this.SetResultAsync(context)
69+
: Task.CompletedTask;
6870
}
6971

7072
/// <summary>
71-
/// 设置结果值
73+
/// 指示是否可以设置结果
74+
/// </summary>
75+
/// <param name="context">上下文</param>
76+
/// <returns></returns>
77+
protected virtual bool CanSetResult(ApiResponseContext context)
78+
{
79+
return true;
80+
}
81+
82+
/// <summary>
83+
/// 如果有结果值,则设置结果值到上下文的Result属性
7284
/// </summary>
7385
/// <param name="context">上下文</param>
7486
/// <returns></returns>

WebApiClientCore/Attributes/ReturnAttributes/XmlReturnAttribute.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ public XmlReturnAttribute(double acceptQuality)
3838
/// </summary>
3939
/// <param name="responseContentType">响应的ContentType</param>
4040
/// <returns></returns>
41-
protected override bool IsMatchAcceptContentType(MediaTypeHeaderValue? responseContentType)
41+
protected override bool IsMatchAcceptContentType(MediaTypeHeaderValue responseContentType)
4242
{
4343
return base.IsMatchAcceptContentType(responseContentType)
44-
|| MediaTypeUtil.IsMatch(textXml, responseContentType?.MediaType);
44+
|| MediaTypeUtil.IsMatch(textXml, responseContentType.MediaType);
4545
}
4646

4747
/// <summary>

0 commit comments

Comments
 (0)