### Complete .csproj File Example for AOT Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html A comprehensive example of a .csproj file configured for AOT publishing, including necessary package references and build properties. ```xml Exe net8.0 enable true true true ``` -------------------------------- ### New: Full Interface Example Source: https://webapiclient.github.io/guide/advanced/migration-guide.html The equivalent full interface example using WebApiClientCore, showcasing updated attributes, parameter types, and return types. ```csharp using WebApiClientCore; using System.Text.Json.Serialization; [LoggingFilter] [HttpHost("https://petstore.swagger.io/v2/")] public interface IPetApi { [HttpPost("pet")] Task AddPetAsync([JsonContent] Pet body, CancellationToken token = default); [HttpGet("pet/findByStatus")] Task> FindPetsByStatusAsync(IEnumerable status, CancellationToken token = default); [HttpGet("pet/{petId}")] Task GetPetByIdAsync(long petId, CancellationToken token = default); [HttpPost("pet/{petId}/uploadImage")] Task UploadFileAsync(long petId, [FormDataText] string additionalMetadata, FormDataFile file, CancellationToken token = default); } ``` -------------------------------- ### Basic JsonRpc Call Example Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html A complete example demonstrating how to define a user API interface with JsonRpc methods and make calls to add, get, and list users. ```csharp // 定义用户模型 public class User { public string Name { get; set; } public int Age { get; set; } } // 定义 RPC 接口 [HttpHost("http://localhost:5000/jsonrpc")] public interface IUserApi { [JsonRpcMethod("user.add")] ITask> AddUserAsync([JsonRpcParam] string name, [JsonRpcParam] int age); [JsonRpcMethod("user.get")] ITask> GetUserAsync([JsonRpcParam] int id); [JsonRpcMethod("user.list")] ITask>> ListUsersAsync(); } // 调用示例 var api = HttpApi.Create(); // 添加用户 var addResult = await api.AddUserAsync("张三", 25); if (addResult.Error == null) { Console.WriteLine($"用户ID: {addResult.Result}"); } // 获取用户 var getResult = await api.GetUserAsync(1); if (getResult.Error == null) { Console.WriteLine($"用户名: {getResult.Result.Name}"); } ``` -------------------------------- ### Complete WebApiClientCore Configuration Example Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html A full example demonstrating how to configure WebApiClientCore, including registering the JSON source generator context and HTTP API interfaces, within a .NET generic host application. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; class Program { static void Main(string[] args) { Host.CreateDefaultBuilder(args) .ConfigureServices(services => { // 配置 WebApiClientCore services .AddWebApiClient() .ConfigureHttpApi(options => { options.PrependJsonSerializerContext(AppJsonSerializerContext.Default); }); // 注册 HTTP API 接口 services.AddHttpApi(); // 注册后台服务 services.AddHostedService(); }) .Build() .Run(); } } ``` -------------------------------- ### Old: Full Interface Example Source: https://webapiclient.github.io/guide/advanced/migration-guide.html A comprehensive example of an interface declaration using the old WebApiClient, demonstrating various attributes and types. ```csharp using WebApiClient; using WebApiClient.Attributes; using WebApiClient.Parameterables; [TraceFilter] [HttpHost("https://petstore.swagger.io/v2/")] public interface IPetApi : IHttpApi { [HttpPost("pet")] ITask AddPetAsync([Required] [JsonContent] Pet body); [HttpGet("pet/findByStatus")] ITask> FindPetsByStatusAsync([Required] IEnumerable status); [HttpGet("pet/{petId}")] ITask GetPetByIdAsync([Required] long petId); [HttpPost("pet/{petId}/uploadImage")] ITask UploadFileAsync([Required] long petId, [MulitpartContent] string additionalMetadata, MulitpartFile file); } ``` -------------------------------- ### Complete AOT Publish Command Example Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html A comprehensive example of the 'dotnet publish' command, including common AOT-specific options like trimming, globalization invariant mode, symbol stripping, and optimization preferences. ```bash # 完整发布命令示例 dotnet publish -c Release -r linux-x64 \ -p:PublishAot=true \ -p:PublishTrimmed=true \ -p:InvariantGlobalization=true \ -p:StripSymbols=true \ -p:OptimizationPreference=Speed ``` -------------------------------- ### Main Program Entry Point Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html The main program entry point sets up the .NET generic host, configures services including WebApiClientCore and HTTP API interfaces, and starts the application. ```csharp // Program.cs using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; class Program { static void Main(string[] args) { Host.CreateDefaultBuilder(args) .ConfigureServices(services => { services .AddWebApiClient() .ConfigureHttpApi(options => { options.PrependJsonSerializerContext(AppJsonSerializerContext.Default); }); services.AddHttpApi(); services.AddHostedService(); }) .Build() .Run(); } } ``` -------------------------------- ### Full Example: Basic Call Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Demonstrates how to define and use a JSON-RPC client interface with WebApiClientCore, including making calls and handling responses. ```APIDOC ## 完整示例 ### 示例 1:基础调用 ```csharp // 定义用户模型 public class User { public string Name { get; set; } public int Age { get; set; } } // 定义 RPC 接口 [HttpHost("http://localhost:5000/jsonrpc")] public interface IUserApi { [JsonRpcMethod("user.add")] ITask> AddUserAsync([JsonRpcParam] string name, [JsonRpcParam] int age); [JsonRpcMethod("user.get")] ITask> GetUserAsync([JsonRpcParam] int id); [JsonRpcMethod("user.list")] ITask>> ListUsersAsync(); } // 调用示例 var api = HttpApi.Create(); // 添加用户 var addResult = await api.AddUserAsync("张三", 25); if (addResult.Error == null) { Console.WriteLine($"用户ID: {addResult.Result}"); } // 获取用户 var getResult = await api.GetUserAsync(1); if (getResult.Error == null) { Console.WriteLine($"用户名: {getResult.Result.Name}"); } ``` ``` -------------------------------- ### Install JsonRpc Extension Package Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Add the JsonRpc extension package to your project using the .NET CLI. ```bash dotnet add package WebApiClientCore.Extensions.JsonRpc ``` -------------------------------- ### Generated Proxy Class Example Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html This code shows an example of a proxy class generated by the WebApiClientCore Source Generator for an IHttpApi interface. It demonstrates how the interface methods are implemented to use an interceptor. ```csharp // HttpApiProxyClass.IUserApi.g.cs namespace WebApiClientCore { partial class HttpApiProxyClass { [HttpApiProxyClass(typeof(IUserApi))] sealed partial class IUserApi : IUserApi { private readonly IHttpApiInterceptor _apiInterceptor; private readonly ApiActionInvoker[] _actionInvokers; public IUserApi(IHttpApiInterceptor apiInterceptor, ApiActionInvoker[] actionInvokers) { _apiInterceptor = apiInterceptor; _actionInvokers = actionInvokers; } [HttpApiProxyMethod(0, "GetAsync", typeof(IUserApi))] Task IUserApi.GetAsync(string p0) { return (Task)_apiInterceptor.Intercept(_actionInvokers[0], new object[] { p0 }); } } } } ``` -------------------------------- ### Retry Delay Strategies Source: https://webapiclient.github.io/guide/configuration/retry-policy.html Examples demonstrating different delay strategies for retries, including fixed delay, exponential backoff, linear increment, and custom logic based on the day of the week. ```csharp // 固定延时:每次重试前等待 1 秒 await userApi.GetByIdAsync("id001") .Retry(3, TimeSpan.FromSeconds(1)); // 指数退避:1s, 2s, 4s... await userApi.GetByIdAsync("id001") .Retry(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))); // 线性递增:1s, 2s, 3s... await userApi.GetByIdAsync("id001") .Retry(3, i => TimeSpan.FromSeconds(i + 1)); // 自定义策略:基于工作日/周末不同延时 await userApi.GetByIdAsync("id001") .Retry(3, i => { var now = DateTime.Now; return now.DayOfWeek == DayOfWeek.Saturday || now.DayOfWeek == DayOfWeek.Sunday ? TimeSpan.FromSeconds(5) : TimeSpan.FromSeconds(1); }); ``` -------------------------------- ### Old: Basic Interface Declaration Source: https://webapiclient.github.io/guide/advanced/migration-guide.html Example of a basic interface declaration using the old WebApiClient. ```csharp using WebApiClient; using WebApiClient.Attributes; public interface IUserApi : IHttpApi { [HttpGet("api/user")] ITask GetAsync(string account); [HttpPost("api/user")] ITask AddAsync([FormContent] UserInfo user); } ``` -------------------------------- ### New: Basic Interface Declaration Source: https://webapiclient.github.io/guide/advanced/migration-guide.html Example of a basic interface declaration using the new WebApiClientCore, including attributes and default cancellation token. ```csharp using WebApiClientCore; [LoggingFilter] [HttpHost("http://localhost:5000/")] public interface IUserApi { [HttpGet("api/user")] Task GetAsync(string account, CancellationToken token = default); [HttpPost("api/user")] Task AddAsync([FormContent] UserInfo user, CancellationToken token = default); } ``` -------------------------------- ### JsonRpcParamsStyle.Object Example Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Illustrates the Object parameter serialization style for JSON-RPC calls, where parameters are sent as a named object. ```csharp [JsonRpcMethod("getUser", ParamsStyle = JsonRpcParamsStyle.Object)] ITask> GetUserAsync([JsonRpcParam] string name, [JsonRpcParam] int age); ``` ```json {"jsonrpc":"2.0","method":"getUser","params":{"name":"张三","age":18},"id":2} ``` -------------------------------- ### WhenCatch Usage Examples Source: https://webapiclient.github.io/guide/configuration/retry-policy.html Demonstrates various scenarios for using WhenCatch, including catching specific exceptions like HttpRequestException, logging exceptions, retrying based on inner exceptions, handling multiple exception types, and asynchronous exception handling. ```csharp // 场景1:捕获 HttpRequestException 并重试 var result = await userApi.GetByIdAsync("id001") .Retry(3) .WhenCatch(); // 场景2:捕获异常后记录日志 var result = await userApi.GetByIdAsync("id001") .Retry(3) .WhenCatch(ex => { logger.LogWarning(ex, "请求失败,准备重试"); }); // 场景3:仅当特定条件满足时才重试 var result = await userApi.GetByIdAsync("id001") .Retry(3) .WhenCatch(ex => { // 仅网络相关异常重试 return ex.InnerException is SocketException; }); // 场景4:捕获多种异常类型 var result = await userApi.GetByIdAsync("id001") .Retry(3) .WhenCatch() .WhenCatch() .WhenCatch(); // 场景5:异步异常处理 var result = await userApi.GetByIdAsync("id001") .Retry(3) .WhenCatchAsync(async ex => { await auditService.LogRetryAttemptAsync(ex); }); ``` -------------------------------- ### JsonRpcParamsStyle.Array Example Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Demonstrates the Array parameter serialization style for JSON-RPC calls, where parameters are sent as a positional array. ```csharp [JsonRpcMethod("add", ParamsStyle = JsonRpcParamsStyle.Array)] ITask> AddAsync([JsonRpcParam] int a, [JsonRpcParam] int b); ``` ```json {"jsonrpc":"2.0","method":"add","params":[1,2],"id":1} ``` -------------------------------- ### Project Structure for AOT Application Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html An example project structure for an AOT-compiled application using WebApiClientCore. This includes the main project file, program entry point, JSON serializer context, API interface, data models, and service implementations. ```plaintext AppAot/ ├── AppAot.csproj ├── Program.cs ├── AppJsonSerializerContext.cs ├── IUserApi.cs ├── User.cs └── AppService.cs ``` -------------------------------- ### HTTP API Interface Definition Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Defines the IUserApi interface for interacting with a user API. It includes attributes for logging, setting the base host, and defining HTTP methods (GET, POST) with associated routes and content types. ```csharp // IUserApi.cs using WebApiClientCore.Attributes; [LoggingFilter] [HttpHost("https://api.example.com")] public interface IUserApi { [HttpGet("api/users/{id}")] Task GetUserAsync(string id); [HttpPost("api/users")] Task CreateUserAsync([JsonContent] User user); [HttpGet("api/users")] Task ListUsersAsync(); } ``` -------------------------------- ### Old: Static Configuration Registration Source: https://webapiclient.github.io/guide/advanced/migration-guide.html Demonstrates the old way of registering and configuring WebApiClient using static methods. ```csharp using WebApiClient; // Old: Register and configure using static methods HttpApi.Register().ConfigureHttpApiConfig(c => { c.HttpHost = new Uri("http://www.webapiclient.com/"); c.FormatOptions.DateTimeFormat = DateTimeFormats.ISO8601_WithMillisecond; }); // Old: Get instance using static methods var api = HttpApi.Resolve(); ``` -------------------------------- ### Module Initializer Registration for Proxy Classes Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html This generated code snippet demonstrates the use of `[ModuleInitializer]` and `[DynamicDependency]` attributes to ensure that the generated proxy classes are registered and available at runtime, preventing them from being trimmed. ```csharp // HttpApiProxyClass.g.cs static partial class HttpApiProxyClass { [ModuleInitializer] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(HttpApiProxyClass))] public static void Initialize() { } } ``` -------------------------------- ### New: Dependency Injection Configuration Source: https://webapiclient.github.io/guide/advanced/migration-guide.html Shows the new method for configuring WebApiClientCore using dependency injection in Startup or ServiceCollection. ```csharp using WebApiClientCore; using Microsoft.Extensions.DependencyInjection; // New: Configure in Startup or ServiceCollection public void ConfigureServices(IServiceCollection services) { services.AddHttpApi().ConfigureHttpApi(o => { o.HttpHost = new Uri("http://www.webapiclient.com/"); o.UseLogging = Environment.IsDevelopment(); // json serialization options o.JsonSerializeOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; o.JsonDeserializeOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; }); } // New: Inject via constructor public class YourService { private readonly IUserApi userApi; public YourService(IUserApi userApi) { this.userApi = userApi; } } ``` -------------------------------- ### Basic AOT Publish Command Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Use the 'dotnet publish' command with the Release configuration to publish your application as a self-contained AOT application for the current platform. ```bash # 发布为当前平台的 AOT 应用 dotnet publish -c Release ``` -------------------------------- ### Configure AOT Publishing Properties in .csproj Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Set these properties in your .csproj file to configure your project for AOT publishing. This includes enabling AOT compilation, trimming, and optionally using invariant globalization for reduced size. ```xml Exe net8.0 true true true ``` -------------------------------- ### Import JsonRpc Namespaces Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Include these namespaces when using the JsonRpc extension for attributes and result types. ```csharp using WebApiClientCore.Attributes; // JsonRpcMethodAttribute, JsonRpcParamAttribute, JsonRpcParamsStyle using WebApiClientCore.Extensions.JsonRpc; // JsonRpcResult, JsonRpcError ``` -------------------------------- ### Publish Output Directory Structure Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html The output of the 'dotnet publish' command for AOT applications is located in the 'bin/Release/net8.0//publish/' directory. Key files include the executable and PDB symbols (if not stripped). ```bash # 发布输出位于 bin/Release/net8.0//publish/ # 主要文件 # - <应用名> (可执行文件) # - <应用名>.pdb (调试符号,如果未剥离) ``` -------------------------------- ### JsonRpcMethodAttribute Constructors Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Use these constructors to define JSON-RPC methods, optionally specifying the RPC method name and request path. ```csharp [JsonRpcMethod("methodName")] ``` ```csharp [JsonRpcMethod("methodName", "/rpc/path")] ``` -------------------------------- ### Await ITask Directly Source: https://webapiclient.github.io/guide/configuration/retry-policy.html ITask is awaitable and fully compatible with Task. It can be directly awaited or used with ConfigureAwait for controlling synchronization context. ```csharp // ITask 可以直接 await ITask task = userApi.GetByIdAsync("id001"); User user = await task; // 支持 ConfigureAwait User user = await userApi.GetByIdAsync("id001").ConfigureAwait(false); ``` -------------------------------- ### WebApiClientCore NuGet Package References Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Add these NuGet packages to your project to enable WebApiClientCore and its Source Generator for AOT compatibility. The analyzer package must be referenced with OutputItemType='Analyzer' and ReferenceOutputAssembly='false'. ```xml ``` -------------------------------- ### Handling ApiInvalidConfigException Source: https://webapiclient.github.io/guide/configuration/exception-handling.html Handle configuration errors by catching HttpRequestException and checking for ApiInvalidConfigException. Configuration errors should typically be fixed during development. ```csharp try { var user = await api.GetUserAsync(); } catch (HttpRequestException ex) when (ex.InnerException is ApiInvalidConfigException configEx) { Console.WriteLine($"Configuration error: {configEx.Message}"); // Configuration errors should be fixed during development, not ignored at runtime throw; } ``` -------------------------------- ### ITask vs Task Return Types Source: https://webapiclient.github.io/guide/configuration/retry-policy.html Choose ITask for scenarios requiring conditional retries, default value handling on exceptions, or fluent API chaining. Use Task for simple requests without retry needs. ```csharp public interface IUserApi { // 返回 Task - 标准异步模式 [HttpGet("api/users/{id}")] Task GetAsync(string id); // 返回 ITask - 支持链式调用 [HttpGet("api/users/{id}")] ITask GetByIdAsync(string id); } ``` -------------------------------- ### Register JSON Source Generator Context Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Register the JsonSerializerContext in your dependency injection configuration. Use PrependJsonSerializerContext to add your custom context before the default ones. ```csharp using Microsoft.Extensions.DependencyInjection; services .AddWebApiClient() .ConfigureHttpApi(options => { // 注册 JSON 源生成上下文 options.PrependJsonSerializerContext(AppJsonSerializerContext.Default); }); ``` -------------------------------- ### WhenCatch Method Signatures Source: https://webapiclient.github.io/guide/configuration/retry-policy.html WhenCatch allows specifying exception types to trigger retries. It supports direct retries, handling exceptions before retrying, or using a predicate to conditionally retry. ```csharp // 捕获指定类型异常,直接重试 IRetryTask WhenCatch() where TException : Exception // 捕获异常后执行处理逻辑,然后重试 IRetryTask WhenCatch(Action handler) where TException : Exception // 捕获异常后判断是否需要重试 IRetryTask WhenCatch(Func predicate) where TException : Exception // 异步版本:捕获异常后执行异步处理 IRetryTask WhenCatchAsync(Func handler) where TException : Exception // 异步版本:捕获异常后异步判断是否需要重试 IRetryTask WhenCatchAsync(Func> predicate) where TException : Exception ``` -------------------------------- ### User Data Model Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Defines the User data model with properties for Id, Name, and Email. It uses JsonPropertyName attributes to map C# properties to JSON field names. ```csharp // User.cs using System.Text.Json.Serialization; public class User { [JsonPropertyName("id")] public string Id { get; set; } = string.Empty; [JsonPropertyName("name")] public string Name { get; set; } = string.Empty; [JsonPropertyName("email")] public string? Email { get; set; } } ``` -------------------------------- ### JsonRpcResult Structure Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Defines the structure for handling JSON-RPC responses, including success results and errors. ```csharp public class JsonRpcResult { /// /// 请求 id /// public int? Id { get; set; } /// /// json rpc 版本号 /// public string JsonRpc { get; set; } /// /// 结果值(成功时) /// public TResult Result { get; set; } /// /// 错误内容(失败时) /// public JsonRpcError? Error { get; set; } } ``` -------------------------------- ### JsonRpcResult Response Handling Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Represents a JSON-RPC 2.0 response, containing either a result or an error. ```APIDOC ## 响应处理:JsonRpcResult JSON-RPC 响应通过 `JsonRpcResult` 泛型类接收: ```csharp public class JsonRpcResult { /// /// 请求 id /// public int? Id { get; set; } /// /// json rpc 版本号 /// public string JsonRpc { get; set; } /// /// 结果值(成功时) /// public TResult Result { get; set; } /// /// 错误内容(失败时) /// public JsonRpcError? Error { get; set; } } ``` ``` -------------------------------- ### Specify Target Platform for AOT Publish Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Specify the target runtime identifier (RID) when publishing your AOT application to ensure compatibility with the desired operating system and architecture. ```bash # 指定目标平台 dotnet publish -c Release -r win-x64 dotnet publish -c Release -r linux-x64 dotnet publish -c Release -r osx-x64 dotnet publish -c Release -r osx-arm64 ``` -------------------------------- ### Retry Method Overloads Source: https://webapiclient.github.io/guide/configuration/retry-policy.html The Retry extension method on ITask returns IRetryTask and allows configuring retry conditions. Overloads support specifying maximum retry count, fixed delay, or a dynamic delay function. ```csharp // 最大重试次数 IRetryTask Retry(this ITask task, int maxCount) // 最大重试次数 + 固定延时 IRetryTask Retry(this ITask task, int maxCount, TimeSpan delay) // 最大重试次数 + 动态延时 IRetryTask Retry(this ITask task, int maxCount, Func? delay) ``` -------------------------------- ### JSON Source Generator Context Definition Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Defines the AppJsonSerializerContext for JSON source generation, specifying the User type and User array as serializable types. This is a partial class that will be implemented by the source generator. ```csharp // AppJsonSerializerContext.cs using System.Text.Json.Serialization; [JsonSerializable(typeof(User))] [JsonSerializable(typeof(User[]))] public partial class AppJsonSerializerContext : JsonSerializerContext { } ``` -------------------------------- ### Define JsonSerializerContext for AOT Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Create a partial class that derives from `JsonSerializerContext` and uses the `[JsonSerializable]` attribute to specify the types that will be serialized or deserialized. This is crucial for AOT compatibility with `System.Text.Json`. ```csharp using System.Text.Json.Serialization; [JsonSerializable(typeof(User))] [JsonSerializable(typeof(User[]))] [JsonSerializable(typeof(Order))] [JsonSerializable(typeof(Order[]))] // 添加所有接口中使用的 JSON 模型类型 public partial class AppJsonSerializerContext : JsonSerializerContext { } ``` -------------------------------- ### JsonRpcParamsStyle Parameter Styles Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Defines the serialization style for parameters in JSON-RPC requests: Array (positional) and Object (named). ```APIDOC ## JsonRpcParamsStyle 参数风格 `JsonRpcParamsStyle` 枚举定义了参数序列化的三种模式: ### Array 模式(默认) 参数按位置序列化为数组: ```csharp [JsonRpcMethod("add", ParamsStyle = JsonRpcParamsStyle.Array)] ITask> AddAsync([JsonRpcParam] int a, [JsonRpcParam] int b); ``` 生成的请求: ```json {"jsonrpc":"2.0","method":"add","params":[1,2],"id":1} ``` ### Object 模式 参数按名称序列化为对象: ```csharp [JsonRpcMethod("getUser", ParamsStyle = JsonRpcParamsStyle.Object)] ITask> GetUserAsync([JsonRpcParam] string name, [JsonRpcParam] int age); ``` 生成的请求: ```json {"jsonrpc":"2.0","method":"getUser","params":{"name":"张三","age":18},"id":2} ``` ### 选择建议 模式| 适用场景 ---|--- Array| 服务端按位置解析参数,参数数量固定 Object| 服务端按名称解析参数,参数可选或顺序不固定 ``` -------------------------------- ### Handling ApiResponseStatusException Source: https://webapiclient.github.io/guide/configuration/exception-handling.html Handle HTTP errors by catching HttpRequestException and checking for ApiResponseStatusException. This allows inspection of the status code and response message for detailed error handling. ```csharp try { var user = await api.GetUserAsync(1); } catch (HttpRequestException ex) when (ex.InnerException is ApiResponseStatusException statusEx) { var statusCode = (int)statusEx.StatusCode; var reasonPhrase = statusEx.ResponseMessage.ReasonPhrase; Console.WriteLine($"HTTP Error: {statusCode} {reasonPhrase}"); // Can read response content for detailed error information var errorContent = await statusEx.ResponseMessage.Content.ReadAsStringAsync(); Console.WriteLine($"Error details: {errorContent}"); // Classify and handle based on status code switch (statusCode) { case 401: // Unauthorized, may require re-authentication break; case 403: // Forbidden break; case 404: // Resource not found break; case >= 500: // Server error break; } } ``` -------------------------------- ### Declare JSON Source Generator Context Source: https://webapiclient.github.io/guide/advanced/aot-publishing.html Declare all JSON data types used in interfaces, including element and collection types for collections, and specific generic parameters for generic types. This is required for the JSON source generator. ```csharp // 示例:完整的 JSON 类型声明 [JsonSerializable(typeof(User))] [JsonSerializable(typeof(User[]))] [JsonSerializable(typeof(List))] [JsonSerializable(typeof(ApiResponse))] [JsonSerializable(typeof(ApiResponse>))] public partial class AppJsonSerializerContext : JsonSerializerContext { } ``` -------------------------------- ### Catching Specific ApiException Types Source: https://webapiclient.github.io/guide/configuration/exception-handling.html Catch HttpRequestException and use a 'when' clause to specifically handle ApiException subclasses like ApiInvalidConfigException. ```csharp catch (HttpRequestException ex) when (ex.InnerException is ApiException apiException) { // Catch all WebApiClientCore internal exceptions logger.LogError(apiException, "API call failed"); } ``` -------------------------------- ### JsonRpcError Structure Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Represents a JSON-RPC error response, containing code, message, and optional data. ```csharp public class JsonRpcError { /// /// 错误码 /// public int Code { get; set; } /// /// 提示消息 /// public string? Message { get; set; } /// /// 错误详情 /// public object? Data { get; set; } } ``` -------------------------------- ### Standard JSON-RPC Error Codes Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html A list of standard error codes defined by the JSON-RPC 2.0 specification. ```APIDOC ### 标准 JSON-RPC 错误码 错误码| 含义 ---|--- -32700| 解析错误(Parse error) -32600| 无效请求(Invalid Request) -32601| 方法不存在(Method not found) -32602| 无效参数(Invalid params) -32603| 内部错误(Internal error) -32000 ~ -32099| 服务端自定义错误 ``` -------------------------------- ### WhenResult Method Signatures Source: https://webapiclient.github.io/guide/configuration/retry-policy.html WhenResult allows retrying based on the response result. It provides synchronous and asynchronous predicate functions to evaluate the result and determine if a retry is needed. ```csharp // 同步判断 IRetryTask WhenResult(Func predicate) // 异步判断 IRetryTask WhenResultAsync(Func> predicate) ``` -------------------------------- ### JsonRpcMethodAttribute Usage Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html The JsonRpcMethodAttribute marks an interface method for JSON-RPC invocation. It can be used with or without specifying the RPC method name and path. ```APIDOC ## JsonRpcMethodAttribute `JsonRpcMethodAttribute` 用于标记接口方法为 JSON-RPC 调用,它继承自 `HttpPostAttribute` 并实现了 `IApiFilterAttribute`。 ### 构造函数 构造函数| 说明 ---|--- `JsonRpcMethodAttribute()`| 使用方法名作为 RPC 方法名 `JsonRpcMethodAttribute(string method)`| 指定 RPC 方法名 `JsonRpcMethodAttribute(string method, string path)`| 指定 RPC 方法名和请求路径 ### 属性 属性| 类型| 默认值| 说明 ---|---|---|--- `ContentType`| string| `application/json-rpc`| 请求的 Content-Type `ParamsStyle`| JsonRpcParamsStyle| `Array`| 参数序列化风格 ### 工作原理 1. **OnRequestAsync** :初始化 `JsonRpcParameters` 容器 2. **IApiFilter.OnRequestAsync** :收集参数后构建 JSON-RPC 请求体 3. 方法名默认使用接口方法名,可通过构造函数指定 ``` -------------------------------- ### Catching HttpRequestException with Inner ApiException Source: https://webapiclient.github.io/guide/configuration/exception-handling.html Catch HttpRequestException and check if the InnerException is an ApiException for unified handling of WebApiClientCore internal errors. ```csharp try { var data = await api.GetAsync(); } catch (HttpRequestException ex) { // ex.InnerException is the actual exception Console.WriteLine($"Actual exception type: {ex.InnerException?.GetType().Name}"); } ``` -------------------------------- ### JsonRpcParamAttribute Usage Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html The JsonRpcParamAttribute marks method parameters to be included in the JSON-RPC 'params' field. It must be used in conjunction with JsonRpcMethodAttribute. ```APIDOC ## JsonRpcParamAttribute `JsonRpcParamAttribute` 用于标记方法参数为 JSON-RPC 参数。被标记的参数会被收集到参数列表中,最终序列化为 `params` 字段。 ### 使用规则 * 必须与 `JsonRpcMethodAttribute` 配合使用 * 参数按声明顺序收集 * 未标记的参数(如 `CancellationToken`)不会参与 RPC 调用 ``` -------------------------------- ### JsonRpcError Structure Source: https://webapiclient.github.io/guide/extensions/jsonrpc-extension.html Represents a JSON-RPC error object, including code, message, and optional data. ```APIDOC ### 错误处理:JsonRpcError ```csharp public class JsonRpcError { /// /// 错误码 /// public int Code { get; set; } /// /// 提示消息 /// public string? Message { get; set; } /// /// 错误详情 /// public object? Data { get; set; } } ``` ``` -------------------------------- ### Handling ApiResultNotMatchException Source: https://webapiclient.github.io/guide/configuration/exception-handling.html Handle cases where retry conditions based on results fail after exhausting retries. This exception contains the last result that failed the condition. ```csharp try { var result = await api.GetDataAsync() .Retry(3) .WhenResult(r => r.Success == false); } catch (HttpRequestException ex) when (ex.InnerException is ApiResultNotMatchException resultEx) { Console.WriteLine($"Result validation failed, retries exhausted"); Console.WriteLine($"Last result: {resultEx.Result}"); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.