c# - 使 Refit 自动在查询字符串中提供参数

标签 c# .net refit

我正在使用 Refit 为 Web 服务生成客户端。

我的 Web API 的所有 URL 都是这样的:

https://service.com/api/v3/datasets ? api_key=XXXXXXX

如您所见,API key 是在查询字符串而不是 header 中指定的。

我希望 Refit 自动提供我的访问 token 作为查询字符串的一部分,而不必在我的服务接口(interface)中指定它。

我查看了文档,但还没有找到方法。

最佳答案

最后,我创建了一个 HttpMessageHandler拦截请求并使用以下代码在查询字符串中注入(inject)“api_key”:

服务创建

service = RestService.For<IMyService>(new HttpClient(new QuerystringInjectingHttpMessageHandler(("api_key", token)))
    {
        BaseAddress = uri,
    });

处理程序
public class QuerystringInjectingHttpMessageHandler : DelegatingHandler
{
    private readonly (string Key, string Value)[] injectedParameters;

    public QuerystringInjectingHttpMessageHandler(params (string key, string value)[] injectedParameters) : this()
    {
        this.injectedParameters = injectedParameters;
    }

    public QuerystringInjectingHttpMessageHandler() : base(new HttpClientHandler())
    {
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var finalUri = InjectIntoQuerystring(request.RequestUri, injectedParameters);

        request.RequestUri = finalUri;

        return base.SendAsync(request, cancellationToken);
    }

    private static Uri InjectIntoQuerystring(Uri uri, IEnumerable<(string Key, string Value)> parameters)
    {
        var uriStr = uri.ToString();

        var queryString = new string(uriStr.SkipWhile(c => c != '?').ToArray());
        var baseUri = uriStr.Substring(0, uriStr.Length - queryString.Length);
        var currentParameters = HttpUtility.ParseQueryString(queryString);

        foreach (var (key, value) in parameters)
        {
            currentParameters[key] = value;
        }

        var tuples = currentParameters.ToTuples();

        var newUri =
            string.Join("&", tuples.Select(tuple =>
            {
                if (tuple.name == null)
                {
                    return tuple.value;
                }

                return tuple.name + "=" + tuple.value;
            }));

        var suffix = newUri == "" ? "" : "?" + newUri;
        var finalUri = new Uri(baseUri + suffix);
        return finalUri;
    }
}

延期
public static class Extensions
{
    public static IEnumerable<(string name, string value)> ToTuples(this NameValueCollection collection)
    {
        if (collection == null)
        {
            throw new ArgumentNullException("collection");
        }

        return
            from key in collection.Cast<string>()
            from value in collection.GetValues(key)
            select (key, value);
    }
}

关于c# - 使 Refit 自动在查询字符串中提供参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60174517/

相关文章:

c# - 如何在控制台应用程序中以编程方式查找所有已安装的 Internet Explorer 加载项

c# - 使用 MVVM Light 消息制作新对话窗口时获取 "Calling thread must be STA"

c# - 在另一个线程上继续执行代码

.net - linq to sql将这个查询翻译成: "select *"?格式是不是效率低下

c# - 测试 Refit 实现的 API 时出现 NullReferenceException

c# - 从 C# 启动远程服务

c# - 为什么 NLog ${aspnet-request-host} 是空的?

c# - 32feet .NET api 拒绝连接 "The requested address is not valid in its context"

c# - 使用动态基地址 retrofit 客户端