diff --git a/.editorconfig b/.editorconfig index 64b759b..671120f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -129,11 +129,6 @@ tab_width = 2 #### C# Coding Conventions #### [*.cs] -# var preferences -csharp_style_var_elsewhere = false:suggestion -csharp_style_var_for_built_in_types = false:suggestion -csharp_style_var_when_type_is_apparent = false:silent - # Expression-bodied members csharp_style_expression_bodied_constructors = false:silent csharp_style_expression_bodied_lambdas = true:suggestion @@ -272,16 +267,16 @@ dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase # name all constant fields using PascalCase dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_style.pascal_case_style.capitalization = pascal_case dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion -dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields -dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style -dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_symbols.static_fields.applicable_kinds = field dotnet_naming_symbols.static_fields.required_modifiers = static dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected dotnet_naming_style.static_prefix_style.required_prefix = s_ @@ -289,8 +284,8 @@ dotnet_naming_style.static_prefix_style.capitalization = camel_case # internal and private fields should be _camelCase dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion -dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields -dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style dotnet_naming_symbols.private_internal_fields.applicable_kinds = field dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal dotnet_naming_style.camel_case_underscore_style.required_prefix = _ diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/IApiException.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/IApiException.cs index 77aa007..ce4db8f 100644 --- a/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/IApiException.cs +++ b/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/IApiException.cs @@ -3,42 +3,42 @@ namespace Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent; /// -/// API 异常接口 +/// Defines exceptions threw when doing an API call. /// -/// 异常类型。 +/// The type of this API exception. public interface IApiException where TException : Exception, IApiException { /// - /// HTTP 状态码,不适用则为 -1。 + /// The HTTP status code, -1 if not applied. /// int StatusCode { get; } /// - /// 错误信息。 + /// The raw error message. /// string Message { get; } /// - /// 显示给用户的错误信息。 + /// The error message to display, can be null if such message is not available. /// string? UserFriendlyMessage { get; } /// - /// 抛出异常。 + /// Throw a . /// - /// HTTP 状态码,若不适用则为 -1。 - /// 错误信息。 - /// 给用户显示的错误信息。 + /// HTTP status code, -1 if not available. + /// The error message. + /// The error message to display, can be null if such message is not available. [DoesNotReturn] static abstract void Throw(int statusCode = -1, string message = "", string? userFriendlyMessage = null); /// - /// 创建异常。 + /// Create(but not throw) a . /// - /// HTTP 状态码,若不适用则为 -1。 - /// 错误信息。 - /// 给用户显示的错误信息。 - /// + /// HTTP status code, -1 if not available. + /// The error message. + /// The error message to display, can be null if such message is not available. + /// A new instance of . static abstract TException Create(int statusCode = -1, string message = "", string? userFriendlyMessage = null); -} \ No newline at end of file +} diff --git a/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/ServiceAgentBase.cs b/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/ServiceAgentBase.cs index a99e0d1..a304488 100644 --- a/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/ServiceAgentBase.cs +++ b/src/Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent/ServiceAgentBase.cs @@ -1,38 +1,37 @@ using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.Http.Json; - using Cnblogs.Architecture.Ddd.Infrastructure.Abstractions; namespace Cnblogs.Architecture.Ddd.Cqrs.ServiceAgent; /// -/// ServiceAgent 的基础类。 +/// Base class for service agent. /// -/// 异常类型。 +/// The type of exception that this service agent throws. public abstract class ServiceAgentBase where TException : Exception, IApiException { /// - /// 构造一个 + /// Create a . /// - /// 用于访问 API 的 。 + /// The underlying used to access the API. protected ServiceAgentBase(HttpClient httpClient) { HttpClient = httpClient; } /// - /// 用于访问 API 的 。 + /// The underlying . /// protected HttpClient HttpClient { get; } /// - /// 发送一个 DELETE 请求。 + /// Execute a command with DELETE method. /// - /// 目标 API 路径。 - /// 返回结果类型。 - /// 返回结果。 + /// The url. + /// Response type. + /// The response. public async Task DeleteCommandAsync(string url) { try @@ -47,9 +46,9 @@ protected ServiceAgentBase(HttpClient httpClient) } /// - /// 发起一个 DELETE 请求。 + /// Execute a command with DELETE method. /// - /// API 路径。 + /// The route of the API. public async Task DeleteCommandAsync(string url) { HttpResponseMessage response; @@ -71,9 +70,9 @@ public async Task DeleteCommandAsync(string url) } /// - /// 发起一个 POST 请求。 + /// Execute a command with POST method. /// - /// 路径。 + /// The route of the API. public async Task PostCommandAsync(string url) { HttpResponseMessage response; @@ -95,11 +94,11 @@ public async Task PostCommandAsync(string url) } /// - /// 发起一个带 Body 的 POST 请求。 + /// Execute a command with POST method and payload. /// - /// 路径。 - /// 请求。 - /// 请求类型。 + /// The route of the API. + /// The request body. + /// The type of request body. public async Task PostCommandAsync(string url, TPayload payload) { HttpResponseMessage response; @@ -121,13 +120,13 @@ public async Task PostCommandAsync(string url, TPayload payload) } /// - /// 发起一个带 Body 的 POST 请求。 + /// Execute a command with POST method and payload. /// - /// 路径。 - /// 请求。 - /// 返回类型。 - /// 请求类型。 - /// + /// The route of the API. + /// The request body. + /// The type of response body. + /// The type of request body. + /// The response body. public async Task PostCommandAsync(string url, TPayload payload) { HttpResponseMessage response; @@ -160,13 +159,63 @@ public async Task PostCommandAsync(string url, T } /// - /// 发起一个 PUT 请求。 + /// Execute a command with PUT method and payload. + /// + /// The route of API. + public async Task PutCommandAsync(string url) + { + HttpResponseMessage response; + try + { + response = await HttpClient.PutAsync(url, new StringContent(string.Empty)); + } + catch (Exception e) + { + ThrowApiException(HttpMethod.Put, url, e); + return; + } + + if (response.IsSuccessStatusCode == false) + { + var content = await response.Content.ReadAsStringAsync(); + ThrowApiException(HttpMethod.Put, response.StatusCode, url, content); + } + } + + /// + /// Execute a command with PUT method and payload. + /// + /// The route of API. + /// The request body. + /// The type of request body. + public async Task PutCommandAsync(string url, TPayload payload) + { + HttpResponseMessage response; + try + { + response = await HttpClient.PutAsJsonAsync(url, payload); + } + catch (Exception e) + { + ThrowApiException(HttpMethod.Put, url, payload, e); + return; + } + + if (response.IsSuccessStatusCode == false) + { + var content = await response.Content.ReadAsStringAsync(); + ThrowApiException(HttpMethod.Put, response.StatusCode, url, payload, content); + } + } + + /// + /// Execute a command with PUT method and payload. /// - /// 路径。 - /// 请求内容。 - /// 返回结果类型。 - /// 请求类型。 - /// + /// The route of API. + /// The request body. + /// The type of response body. + /// The type of request body. + /// The response body. public async Task PutCommandAsync(string url, TPayload payload) { HttpResponseMessage response; @@ -199,10 +248,11 @@ public async Task PutCommandAsync(string url, TP } /// - /// 获取内容。 + /// Query item with GET method. /// - /// 路径。 - /// 结果类型。 + /// The route of the API. + /// The type of item to get. + /// The query result, can be null if item does not exists or status code is 404. public async Task GetItemAsync(string url) { try @@ -222,14 +272,14 @@ public async Task PutCommandAsync(string url, TP } /// - /// 批量获取实体。 + /// Batch get items with GET method. /// - /// 路径。 - /// 参数名称。 - /// 主键列表。 - /// 返回类型。 - /// 主键类型。 - /// + /// The route of the API. + /// The name of id field. + /// The id list. + /// The type of the query result item. + /// The type of the id. + /// A list of items that contains id that in , the order or count of the items are not guaranteed. public async Task> BatchGetItemsAsync( string url, string paramName, @@ -260,13 +310,13 @@ public async Task> BatchGetItemsAsync( } /// - /// 获取分页列表。 + /// Get paged list of items based on url. /// - /// 路径。 - /// 页码。 - /// 分页大小。 - /// 实体类型。 - /// + /// The route of the API. + /// The paging parameters, including page size and page index. + /// Specifies the order of items to return. + /// The type of items to query. + /// The paged list of items. An empty list is returned when there is no result. public async Task> ListPagedItemsAsync( string url, PagingParams? pagingParams = null, @@ -276,13 +326,14 @@ public async Task> ListPagedItemsAsync( } /// - /// 获取分页列表。 + /// Get paged list of items based on url. /// - /// 路径。 - /// 页码。 - /// 分页大小。 - /// 排序字符串。 - /// 实体类型。 + /// The route of the API. + /// The page index. + /// The page size. + /// Specifies the order of items to return. + /// The type of items to query. + /// The paged list of items. An empty list is returned when there is no result. public async Task> ListPagedItemsAsync( string url, int? pageIndex, @@ -315,14 +366,14 @@ public async Task> ListPagedItemsAsync( } /// - /// 处理抛出异常的情况。 + /// Throw exceptions. /// - /// 请求方法。 - /// 状态码,若不适用则是 -1。 - /// 请求的 Url - /// 请求内容。 - /// 返回内容。 - /// 异常。 + /// The method for this request. + /// HTTP status code, -1 if not available. + /// The URL to request. + /// The request body. + /// The response body. + /// The exception. [DoesNotReturn] protected virtual void ThrowApiException( HttpMethod method, @@ -352,4 +403,4 @@ private void ThrowApiException( private void ThrowApiException(HttpMethod method, string url, object? body, Exception e) => ThrowApiException(method, -1, url, body, null, e); -} \ No newline at end of file +}