RESTCLIENT.NET
菜单
中文
↗ GitHub

RESTCLIENT.NET / 从源码到请求

可以运行的代码。

下面的示例使用 RestClient.Net 7.3.1 编译。页面与自动验证共用同一份源码,验证涵盖成功响应、HTTP 错误、连接失败、JSON 请求和取消操作。

从 GET 请求开始

入口方法从 JSONPlaceholder 获取文章,并输出明确的结果。克隆仓库、安装 .NET 9 SDK 后运行:

dotnet run --project Website/examples/Examples.csproj

此命令会向 JSONPlaceholder 发出真实请求。自动验证使用本地消息处理器,不会发出 HTTP 请求。

发送 JSON,保留完整结果

CreatePostAsync 将 JsonContent.Create(request) 作为 requestBody 传入。反序列化委托接收 HttpResponseMessage,因此需要读取 response.Content。成功响应转换为 Post,HTTP 错误保留文本格式的响应内容。

使用现有客户端工厂

GetUsingFactoryAsync 使用名为 posts 的客户端。在应用中通过 services.AddHttpClient("posts") 注册即可。请求使用绝对 URL,已有的处理器、认证和弹性配置仍然适用。

明确处理每一种结果

Result.Match 分别处理成功和失败,随后 HttpError.Match 明确区分 HTTP 响应错误与异常。取消令牌会传递到请求与反序列化操作;取消请求的结果是一个异常错误。

完整源码

中英文页面均展示同一个源码文件。其中的 Main 运行 GET 示例;POST 与客户端工厂方法可直接从应用调用。

using System.Net.Http.Json;
using Outcome;
using RestClient.Net;
using Urls;

namespace WebsiteExamples;

public static class RestClientExamples
{
    // This runnable entry point calls JSONPlaceholder. Tests use a local handler instead.
    public static async Task Main()
    {
        using var client = new HttpClient();
        using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(15));
        var result = await GetPostAsync(client, 1, cancellation.Token);
        Console.WriteLine(Describe(result));
    }

    public static Task<Result<Post, HttpError<string>>> GetPostAsync(
        HttpClient client,
        int id,
        CancellationToken cancellationToken = default
    ) =>
        client.GetAsync(
            url: $"https://jsonplaceholder.typicode.com/posts/{id}".ToAbsoluteUrl(),
            deserializeSuccess: ReadPostAsync,
            deserializeError: ReadErrorAsync,
            headers: new Dictionary<string, string> { ["Accept"] = "application/json" },
            cancellationToken: cancellationToken
        );

    public static Task<Result<Post, HttpError<string>>> CreatePostAsync(
        HttpClient client,
        CreatePost request,
        CancellationToken cancellationToken = default
    ) =>
        client.PostAsync(
            url: "https://jsonplaceholder.typicode.com/posts".ToAbsoluteUrl(),
            requestBody: JsonContent.Create(request),
            deserializeSuccess: ReadPostAsync,
            deserializeError: ReadErrorAsync,
            cancellationToken: cancellationToken
        );

    // Register a named client with services.AddHttpClient("posts") in your application.
    public static Task<Result<Post, HttpError<string>>> GetUsingFactoryAsync(
        IHttpClientFactory factory,
        int id,
        CancellationToken cancellationToken = default
    ) =>
        factory.GetAsync(
            clientName: "posts",
            url: $"https://jsonplaceholder.typicode.com/posts/{id}".ToAbsoluteUrl(),
            deserializeSuccess: ReadPostAsync,
            deserializeError: ReadErrorAsync,
            cancellationToken: cancellationToken
        );

    // Both success and failure are explicit. HTTP failures retain the response body.
    public static string Describe(Result<Post, HttpError<string>> result) =>
        result.Match(
            onSuccess: post => $"Post {post.Id}: {post.Title}",
            onError: error =>
                error.Match(
                    onException: exception => $"Connection failed: {exception.Message}",
                    onErrorResponse: (body, status, headers) => $"HTTP {(int)status}: {body}"
                )
        );

    // Deserialize<T> receives HttpResponseMessage: read its Content property.
    private static async Task<Post> ReadPostAsync(
        HttpResponseMessage response,
        CancellationToken cancellationToken
    ) =>
        await response.Content.ReadFromJsonAsync<Post>(cancellationToken)
        ?? throw new InvalidDataException("The response contained no post.");

    private static Task<string> ReadErrorAsync(
        HttpResponseMessage response,
        CancellationToken cancellationToken
    ) => response.Content.ReadAsStringAsync(cancellationToken);
}

public sealed record Post(int UserId, int Id, string Title, string Body);

public sealed record CreatePost(int UserId, string Title, string Body);

继续探索

HTTP 方法与签名 · 客户端工厂参考 · 错误处理指南 · 从 OpenAPI 生成客户端