Skip to content

Commit f1c4683

Browse files
committed
feat: allow put command without payload or response
1 parent d4a6fdc commit f1c4683

File tree

3 files changed

+134
-88
lines changed

3 files changed

+134
-88
lines changed

.editorconfig

+8-13
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,6 @@ tab_width = 2
129129
#### C# Coding Conventions ####
130130
[*.cs]
131131

132-
# var preferences
133-
csharp_style_var_elsewhere = false:suggestion
134-
csharp_style_var_for_built_in_types = false:suggestion
135-
csharp_style_var_when_type_is_apparent = false:silent
136-
137132
# Expression-bodied members
138133
csharp_style_expression_bodied_constructors = false:silent
139134
csharp_style_expression_bodied_lambdas = true:suggestion
@@ -272,25 +267,25 @@ dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
272267

273268
# name all constant fields using PascalCase
274269
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
275-
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
276-
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
277-
dotnet_naming_symbols.constant_fields.applicable_kinds = field
270+
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
271+
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
272+
dotnet_naming_symbols.constant_fields.applicable_kinds = field
278273
dotnet_naming_symbols.constant_fields.required_modifiers = const
279274
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
280275

281276
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
282-
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
283-
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
284-
dotnet_naming_symbols.static_fields.applicable_kinds = field
277+
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
278+
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
279+
dotnet_naming_symbols.static_fields.applicable_kinds = field
285280
dotnet_naming_symbols.static_fields.required_modifiers = static
286281
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
287282
dotnet_naming_style.static_prefix_style.required_prefix = s_
288283
dotnet_naming_style.static_prefix_style.capitalization = camel_case
289284

290285
# internal and private fields should be _camelCase
291286
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
292-
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
293-
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
287+
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
288+
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
294289
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
295290
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
296291
dotnet_naming_style.camel_case_underscore_style.required_prefix = _

src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/IApiException.cs

+15-15
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,42 @@
33
namespace Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent;
44

55
/// <summary>
6-
/// API 异常接口
6+
/// Defines exceptions threw when doing an API call.
77
/// </summary>
8-
/// <typeparam name="TException">异常类型。</typeparam>
8+
/// <typeparam name="TException">The type of this API exception.</typeparam>
99
public interface IApiException<out TException>
1010
where TException : Exception, IApiException<TException>
1111
{
1212
/// <summary>
13-
/// HTTP 状态码,不适用则为 -1。
13+
/// The HTTP status code, -1 if not applied.
1414
/// </summary>
1515
int StatusCode { get; }
1616

1717
/// <summary>
18-
/// 错误信息。
18+
/// The raw error message.
1919
/// </summary>
2020
string Message { get; }
2121

2222
/// <summary>
23-
/// 显示给用户的错误信息。
23+
/// The error message to display, can be null if such message is not available.
2424
/// </summary>
2525
string? UserFriendlyMessage { get; }
2626

2727
/// <summary>
28-
/// 抛出异常。
28+
/// Throw a <see cref="TException"/>.
2929
/// </summary>
30-
/// <param name="statusCode">HTTP 状态码,若不适用则为 -1。</param>
31-
/// <param name="message">错误信息。</param>
32-
/// <param name="userFriendlyMessage">给用户显示的错误信息。</param>
30+
/// <param name="statusCode">HTTP status code, -1 if not available.</param>
31+
/// <param name="message">The error message.</param>
32+
/// <param name="userFriendlyMessage">The error message to display, can be null if such message is not available.</param>
3333
[DoesNotReturn]
3434
static abstract void Throw(int statusCode = -1, string message = "", string? userFriendlyMessage = null);
3535

3636
/// <summary>
37-
/// 创建异常。
37+
/// Create(but not throw) a <see cref="TException"/>.
3838
/// </summary>
39-
/// <param name="statusCode">HTTP 状态码,若不适用则为 -1。</param>
40-
/// <param name="message">错误信息。</param>
41-
/// <param name="userFriendlyMessage">给用户显示的错误信息。</param>
42-
/// <returns></returns>
39+
/// <param name="statusCode">HTTP status code, -1 if not available.</param>
40+
/// <param name="message">The error message.</param>
41+
/// <param name="userFriendlyMessage">The error message to display, can be null if such message is not available.</param>
42+
/// <returns>A new instance of <see cref="TException"/>.</returns>
4343
static abstract TException Create(int statusCode = -1, string message = "", string? userFriendlyMessage = null);
44-
}
44+
}

src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/ServiceAgentBase.cs

+111-60
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,37 @@
11
using System.Diagnostics.CodeAnalysis;
22
using System.Net;
33
using System.Net.Http.Json;
4-
54
using Cnblogs.Architecture.Ddd.Infrastructure.Abstractions;
65

76
namespace Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent;
87

98
/// <summary>
10-
/// ServiceAgent 的基础类。
9+
/// Base class for service agent.
1110
/// </summary>
12-
/// <typeparam name="TException">异常类型。</typeparam>
11+
/// <typeparam name="TException">The type of exception that this service agent throws.</typeparam>
1312
public abstract class ServiceAgentBase<TException>
1413
where TException : Exception, IApiException<TException>
1514
{
1615
/// <summary>
17-
/// 构造一个 <see cref="ServiceAgentBase{TException}"/>
16+
/// Create a <see cref="ServiceAgentBase{TException}"/>.
1817
/// </summary>
19-
/// <param name="httpClient">用于访问 API 的 <see cref="HttpClient"/></param>
18+
/// <param name="httpClient">The underlying <see cref="HttpClient"/> used to access the API.</param>
2019
protected ServiceAgentBase(HttpClient httpClient)
2120
{
2221
HttpClient = httpClient;
2322
}
2423

2524
/// <summary>
26-
/// 用于访问 API 的 <see cref="HttpClient"/>
25+
/// The underlying <see cref="HttpClient"/>.
2726
/// </summary>
2827
protected HttpClient HttpClient { get; }
2928

3029
/// <summary>
31-
/// 发送一个 DELETE 请求。
30+
/// Execute a command with DELETE method.
3231
/// </summary>
33-
/// <param name="url">目标 API 路径。</param>
34-
/// <typeparam name="TResponse">返回结果类型。</typeparam>
35-
/// <returns>返回结果。</returns>
32+
/// <param name="url">The url.</param>
33+
/// <typeparam name="TResponse">Response type.</typeparam>
34+
/// <returns>The response.</returns>
3635
public async Task<TResponse?> DeleteCommandAsync<TResponse>(string url)
3736
{
3837
try
@@ -47,9 +46,9 @@ protected ServiceAgentBase(HttpClient httpClient)
4746
}
4847

4948
/// <summary>
50-
/// 发起一个 DELETE 请求。
49+
/// Execute a command with DELETE method.
5150
/// </summary>
52-
/// <param name="url">API 路径。</param>
51+
/// <param name="url">The route of the API.</param>
5352
public async Task DeleteCommandAsync(string url)
5453
{
5554
HttpResponseMessage response;
@@ -71,9 +70,9 @@ public async Task DeleteCommandAsync(string url)
7170
}
7271

7372
/// <summary>
74-
/// 发起一个 POST 请求。
73+
/// Execute a command with POST method.
7574
/// </summary>
76-
/// <param name="url">路径。</param>
75+
/// <param name="url">The route of the API.</param>
7776
public async Task PostCommandAsync(string url)
7877
{
7978
HttpResponseMessage response;
@@ -95,11 +94,11 @@ public async Task PostCommandAsync(string url)
9594
}
9695

9796
/// <summary>
98-
/// 发起一个带 Body 的 POST 请求。
97+
/// Execute a command with POST method and payload.
9998
/// </summary>
100-
/// <param name="url">路径。</param>
101-
/// <param name="payload">请求。</param>
102-
/// <typeparam name="TPayload">请求类型。</typeparam>
99+
/// <param name="url">The route of the API.</param>
100+
/// <param name="payload">The request body.</param>
101+
/// <typeparam name="TPayload">The type of request body.</typeparam>
103102
public async Task PostCommandAsync<TPayload>(string url, TPayload payload)
104103
{
105104
HttpResponseMessage response;
@@ -121,13 +120,13 @@ public async Task PostCommandAsync<TPayload>(string url, TPayload payload)
121120
}
122121

123122
/// <summary>
124-
/// 发起一个带 Body 的 POST 请求。
123+
/// Execute a command with POST method and payload.
125124
/// </summary>
126-
/// <param name="url">路径。</param>
127-
/// <param name="payload">请求。</param>
128-
/// <typeparam name="TResponse">返回类型。</typeparam>
129-
/// <typeparam name="TPayload">请求类型。</typeparam>
130-
/// <returns></returns>
125+
/// <param name="url">The route of the API.</param>
126+
/// <param name="payload">The request body.</param>
127+
/// <typeparam name="TResponse">The type of response body.</typeparam>
128+
/// <typeparam name="TPayload">The type of request body.</typeparam>
129+
/// <returns>The response body.</returns>
131130
public async Task<TResponse> PostCommandAsync<TResponse, TPayload>(string url, TPayload payload)
132131
{
133132
HttpResponseMessage response;
@@ -160,13 +159,63 @@ public async Task<TResponse> PostCommandAsync<TResponse, TPayload>(string url, T
160159
}
161160

162161
/// <summary>
163-
/// 发起一个 PUT 请求。
162+
/// Execute a command with PUT method and payload.
163+
/// </summary>
164+
/// <param name="url">The route of API.</param>
165+
public async Task PutCommandAsync(string url)
166+
{
167+
HttpResponseMessage response;
168+
try
169+
{
170+
response = await HttpClient.PutAsync(url, new StringContent(string.Empty));
171+
}
172+
catch (Exception e)
173+
{
174+
ThrowApiException(HttpMethod.Put, url, e);
175+
return;
176+
}
177+
178+
if (response.IsSuccessStatusCode == false)
179+
{
180+
var content = await response.Content.ReadAsStringAsync();
181+
ThrowApiException(HttpMethod.Put, response.StatusCode, url, content);
182+
}
183+
}
184+
185+
/// <summary>
186+
/// Execute a command with PUT method and payload.
187+
/// </summary>
188+
/// <param name="url">The route of API.</param>
189+
/// <param name="payload">The request body.</param>
190+
/// <typeparam name="TPayload">The type of request body.</typeparam>
191+
public async Task PutCommandAsync<TPayload>(string url, TPayload payload)
192+
{
193+
HttpResponseMessage response;
194+
try
195+
{
196+
response = await HttpClient.PutAsJsonAsync(url, payload);
197+
}
198+
catch (Exception e)
199+
{
200+
ThrowApiException(HttpMethod.Put, url, payload, e);
201+
return;
202+
}
203+
204+
if (response.IsSuccessStatusCode == false)
205+
{
206+
var content = await response.Content.ReadAsStringAsync();
207+
ThrowApiException(HttpMethod.Put, response.StatusCode, url, payload, content);
208+
}
209+
}
210+
211+
/// <summary>
212+
/// Execute a command with PUT method and payload.
164213
/// </summary>
165-
/// <param name="url">路径。</param>
166-
/// <param name="payload">请求内容。</param>
167-
/// <typeparam name="TResponse">返回结果类型。</typeparam>
168-
/// <typeparam name="TPayload">请求类型。</typeparam>
169-
/// <returns></returns>
214+
/// <param name="url">The route of API.</param>
215+
/// <param name="payload">The request body.</param>
216+
/// <typeparam name="TResponse">The type of response body.</typeparam>
217+
/// <typeparam name="TPayload">The type of request body.</typeparam>
218+
/// <returns>The response body.</returns>
170219
public async Task<TResponse> PutCommandAsync<TResponse, TPayload>(string url, TPayload payload)
171220
{
172221
HttpResponseMessage response;
@@ -199,10 +248,11 @@ public async Task<TResponse> PutCommandAsync<TResponse, TPayload>(string url, TP
199248
}
200249

201250
/// <summary>
202-
/// 获取内容。
251+
/// Query item with GET method.
203252
/// </summary>
204-
/// <param name="url">路径。</param>
205-
/// <typeparam name="T">结果类型。</typeparam>
253+
/// <param name="url">The route of the API.</param>
254+
/// <typeparam name="T">The type of item to get.</typeparam>
255+
/// <returns>The query result, can be null if item does not exists or status code is 404.</returns>
206256
public async Task<T?> GetItemAsync<T>(string url)
207257
{
208258
try
@@ -222,14 +272,14 @@ public async Task<TResponse> PutCommandAsync<TResponse, TPayload>(string url, TP
222272
}
223273

224274
/// <summary>
225-
/// 批量获取实体。
275+
/// Batch get items with GET method.
226276
/// </summary>
227-
/// <param name="url">路径。</param>
228-
/// <param name="paramName">参数名称。</param>
229-
/// <param name="ids">主键列表。</param>
230-
/// <typeparam name="TResponse">返回类型。</typeparam>
231-
/// <typeparam name="TId">主键类型。</typeparam>
232-
/// <returns></returns>
277+
/// <param name="url">The route of the API.</param>
278+
/// <param name="paramName">The name of id field.</param>
279+
/// <param name="ids">The id list.</param>
280+
/// <typeparam name="TResponse">The type of the query result item.</typeparam>
281+
/// <typeparam name="TId">The type of the id.</typeparam>
282+
/// <returns>A list of items that contains id that in <paramref name="ids"/>, the order or count of the items are not guaranteed.</returns>
233283
public async Task<List<TResponse>> BatchGetItemsAsync<TResponse, TId>(
234284
string url,
235285
string paramName,
@@ -260,13 +310,13 @@ public async Task<List<TResponse>> BatchGetItemsAsync<TResponse, TId>(
260310
}
261311

262312
/// <summary>
263-
/// 获取分页列表。
313+
/// Get paged list of items based on url.
264314
/// </summary>
265-
/// <param name="url">路径。</param>
266-
/// <param name="pagingParams">页码。</param>
267-
/// <param name="orderByString">分页大小。</param>
268-
/// <typeparam name="TItem">实体类型。</typeparam>
269-
/// <returns></returns>
315+
/// <param name="url">The route of the API.</param>
316+
/// <param name="pagingParams">The paging parameters, including page size and page index.</param>
317+
/// <param name="orderByString">Specifies the order of items to return.</param>
318+
/// <typeparam name="TItem">The type of items to query.</typeparam>
319+
/// <returns>The paged list of items. An empty list is returned when there is no result.</returns>
270320
public async Task<PagedList<TItem>> ListPagedItemsAsync<TItem>(
271321
string url,
272322
PagingParams? pagingParams = null,
@@ -276,13 +326,14 @@ public async Task<PagedList<TItem>> ListPagedItemsAsync<TItem>(
276326
}
277327

278328
/// <summary>
279-
/// 获取分页列表。
329+
/// Get paged list of items based on url.
280330
/// </summary>
281-
/// <param name="url">路径。</param>
282-
/// <param name="pageIndex">页码。</param>
283-
/// <param name="pageSize">分页大小。</param>
284-
/// <param name="orderByString">排序字符串。</param>
285-
/// <typeparam name="TItem">实体类型。</typeparam>
331+
/// <param name="url">The route of the API.</param>
332+
/// <param name="pageIndex">The page index.</param>
333+
/// <param name="pageSize">The page size.</param>
334+
/// <param name="orderByString">Specifies the order of items to return.</param>
335+
/// <typeparam name="TItem">The type of items to query.</typeparam>
336+
/// <returns>The paged list of items. An empty list is returned when there is no result.</returns>
286337
public async Task<PagedList<TItem>> ListPagedItemsAsync<TItem>(
287338
string url,
288339
int? pageIndex,
@@ -315,14 +366,14 @@ public async Task<PagedList<TItem>> ListPagedItemsAsync<TItem>(
315366
}
316367

317368
/// <summary>
318-
/// 处理抛出异常的情况。
369+
/// Throw exceptions.
319370
/// </summary>
320-
/// <param name="method">请求方法。</param>
321-
/// <param name="statusCode">状态码,若不适用则是 -1。</param>
322-
/// <param name="url">请求的 Url</param>
323-
/// <param name="requestBody">请求内容。</param>
324-
/// <param name="response">返回内容。</param>
325-
/// <param name="e">异常。</param>
371+
/// <param name="method">The method for this request.</param>
372+
/// <param name="statusCode">HTTP status code, -1 if not available.</param>
373+
/// <param name="url">The URL to request.</param>
374+
/// <param name="requestBody">The request body.</param>
375+
/// <param name="response">The response body.</param>
376+
/// <param name="e">The exception.</param>
326377
[DoesNotReturn]
327378
protected virtual void ThrowApiException(
328379
HttpMethod method,
@@ -352,4 +403,4 @@ private void ThrowApiException(
352403

353404
private void ThrowApiException(HttpMethod method, string url, object? body, Exception e)
354405
=> ThrowApiException(method, -1, url, body, null, e);
355-
}
406+
}

0 commit comments

Comments
 (0)