需要帮助将我的 RestSharp 代码转换为使用 HttpClient
Need help converting my RestSharp code to use HttpClient instead
由于我需要将这个 C# dll 转换成一个 tlp 文件以便从 Visual Basic 6 调用,我需要避免使用外部依赖项。我已经使用 RestSharp 通过执行以下操作(有效)来使用 WebAPI:
using RestSharp;
using Newtonsoft.Json;
..
public string GetToken (string Key, string Password) {
var client = new RestClient (BaseUrl + "auth/GetToken");
var request = new RestRequest (Method.POST);
request.AddHeader ("cache-control", "no-cache");
request.AddHeader ("Content-Type", "application/json");
Dictionary<string, string> data = new Dictionary<string, string> {
{ "APIKey", Key },
{ "APIPassword", Password }
};
var dataJSON = JsonConvert.SerializeObject (data);
request.AddParameter ("undefined", dataJSON, ParameterType.RequestBody);
IRestResponse response = client.Execute (request);
GetTokenResults g = JsonConvert.DeserializeObject<GetTokenResults> (response.Content);
return g.Token;
}
其中 GetTokenResults 是一个包含字符串令牌声明的结构。我想在不使用 RestSharp 的情况下实现同样的功能。这是我不成功的尝试:
using System.Net.Http;
using System.Net.Http.Headers;
..
public async void GetToken (string Key, string Password) {
var client = new HttpClient ( );
client.DefaultRequestHeaders.Accept.Clear ( );
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue ("application/json"));
client.BaseAddress = new Uri (BaseUrl + "auth/GetToken");
Dictionary<string, string> data = new Dictionary<string, string> {
{ "APIKey", Key },
{ "APIPassword", Password }
};
var dataJSON = JsonConvert.SerializeObject (data);
var content = new StringContent (dataJSON, Encoding.UTF8, "application/json");
var response = await client.PostAsync ("", content);
}
我不清楚如何使用 HttpClient 获得与我之前使用 RestSharp 时相同的结果(发送 API 密钥和密码,return 令牌作为字符串)。任何能为我指明正确方向的东西都将不胜感激!
我认为您在 PostAsync 方法中缺少第一个参数,即 requestUri=Client.BaseAddress(请参阅下面的实现)。
先试试这个,如果不行,请阅读下文。我有一些不同的实现,我将 client.BaseAddress
作为第一个参数传递,并将我的内容作为 ByteArrayContent 传递。在我的例子中,我必须将我的内容作为我的代码的 "application/x-www-form-urlencoded" 摘录来传递:
var buffer = Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
//as I can't send JSON, probably, you can skip as it's already JSON
byteContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
//requestUri=client.BaseAddress
await client.PostAsync(requestUri, byteContent).ConfigureAwait(false);
我们的需求有些不同,但我认为您的需求非常接近。如果没有帮助,请写信给我,我将分享我的代码。阅读评论后,我想分享一下我是如何制作 HttpClient 的。代码原样:
using (var client = CreateMailClientForPOST($"{BaseUrl}/"))
{
//removed code, you can call above code as method like
var response= await client.DoThingAsAsync($"{client.BaseAddress}, content").ConfigureAwait(false);
}
protected HttpClient CreateMailClientForPOST(string resource)
{
var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate;
}
var client = new HttpClient(handler)
{
BaseAddress = new Uri($"https://api.address.com/rest/{resource}")
};
return client;
}
我想你被 this issue 蜇了。简而言之,client.BaseAddress
中的 URI 需要在其末尾添加一个斜杠。
但是,我不会简单地添加它,我会考虑做一些不同的事情。假设您要向其附加 "auth/GetToken"
,那么您的 BaseUrl
可能已经有一个尾部斜线。我会这样做:
client.BaseAddress = new Uri(BaseUrl);
...
var response = await client.PostAsync("auth/GetToken", content);
如您所见,HttpClient
非常适合您的代码已经设置的方式,即您有一个带有尾部斜线的 "base" 地址,并且您想要附加到它具体调用。
这应该会让你摆脱这一点。您需要处理的下一件事是反序列化 JSON 响应,以便您可以从中获取令牌。它与您在 RestSharp 中的做法类似,除了 response.Content
不是 HttpClient
世界中的字符串,因此您需要多一步才能获得:
var json = await response.Content.ReadAsStringAsync();
GetTokenResults g = JsonConvert.DeserializeObject<GetTokenResults>(json);
return g.Token;
要编译它,您需要做的最后一件事是将方法签名更改为:
public async Task<string> GetTokenAsync
最后一点:您现在处于异步世界中,这是一件好事,但您需要知道如何正确使用它,否则您可能会遇到死锁和其他神秘错误。简而言之,don't block on async code 通过在调用堆栈的任何位置调用 .Result
或 .Wait()
。这是迄今为止人们最常犯的错误。使用async/await
一路向下.
由于我需要将这个 C# dll 转换成一个 tlp 文件以便从 Visual Basic 6 调用,我需要避免使用外部依赖项。我已经使用 RestSharp 通过执行以下操作(有效)来使用 WebAPI:
using RestSharp;
using Newtonsoft.Json;
..
public string GetToken (string Key, string Password) {
var client = new RestClient (BaseUrl + "auth/GetToken");
var request = new RestRequest (Method.POST);
request.AddHeader ("cache-control", "no-cache");
request.AddHeader ("Content-Type", "application/json");
Dictionary<string, string> data = new Dictionary<string, string> {
{ "APIKey", Key },
{ "APIPassword", Password }
};
var dataJSON = JsonConvert.SerializeObject (data);
request.AddParameter ("undefined", dataJSON, ParameterType.RequestBody);
IRestResponse response = client.Execute (request);
GetTokenResults g = JsonConvert.DeserializeObject<GetTokenResults> (response.Content);
return g.Token;
}
其中 GetTokenResults 是一个包含字符串令牌声明的结构。我想在不使用 RestSharp 的情况下实现同样的功能。这是我不成功的尝试:
using System.Net.Http;
using System.Net.Http.Headers;
..
public async void GetToken (string Key, string Password) {
var client = new HttpClient ( );
client.DefaultRequestHeaders.Accept.Clear ( );
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue ("application/json"));
client.BaseAddress = new Uri (BaseUrl + "auth/GetToken");
Dictionary<string, string> data = new Dictionary<string, string> {
{ "APIKey", Key },
{ "APIPassword", Password }
};
var dataJSON = JsonConvert.SerializeObject (data);
var content = new StringContent (dataJSON, Encoding.UTF8, "application/json");
var response = await client.PostAsync ("", content);
}
我不清楚如何使用 HttpClient 获得与我之前使用 RestSharp 时相同的结果(发送 API 密钥和密码,return 令牌作为字符串)。任何能为我指明正确方向的东西都将不胜感激!
我认为您在 PostAsync 方法中缺少第一个参数,即 requestUri=Client.BaseAddress(请参阅下面的实现)。
先试试这个,如果不行,请阅读下文。我有一些不同的实现,我将 client.BaseAddress
作为第一个参数传递,并将我的内容作为 ByteArrayContent 传递。在我的例子中,我必须将我的内容作为我的代码的 "application/x-www-form-urlencoded" 摘录来传递:
var buffer = Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
//as I can't send JSON, probably, you can skip as it's already JSON
byteContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
//requestUri=client.BaseAddress
await client.PostAsync(requestUri, byteContent).ConfigureAwait(false);
我们的需求有些不同,但我认为您的需求非常接近。如果没有帮助,请写信给我,我将分享我的代码。阅读评论后,我想分享一下我是如何制作 HttpClient 的。代码原样:
using (var client = CreateMailClientForPOST($"{BaseUrl}/"))
{
//removed code, you can call above code as method like
var response= await client.DoThingAsAsync($"{client.BaseAddress}, content").ConfigureAwait(false);
}
protected HttpClient CreateMailClientForPOST(string resource)
{
var handler = new HttpClientHandler();
if (handler.SupportsAutomaticDecompression)
{
handler.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate;
}
var client = new HttpClient(handler)
{
BaseAddress = new Uri($"https://api.address.com/rest/{resource}")
};
return client;
}
我想你被 this issue 蜇了。简而言之,client.BaseAddress
中的 URI 需要在其末尾添加一个斜杠。
但是,我不会简单地添加它,我会考虑做一些不同的事情。假设您要向其附加 "auth/GetToken"
,那么您的 BaseUrl
可能已经有一个尾部斜线。我会这样做:
client.BaseAddress = new Uri(BaseUrl);
...
var response = await client.PostAsync("auth/GetToken", content);
如您所见,HttpClient
非常适合您的代码已经设置的方式,即您有一个带有尾部斜线的 "base" 地址,并且您想要附加到它具体调用。
这应该会让你摆脱这一点。您需要处理的下一件事是反序列化 JSON 响应,以便您可以从中获取令牌。它与您在 RestSharp 中的做法类似,除了 response.Content
不是 HttpClient
世界中的字符串,因此您需要多一步才能获得:
var json = await response.Content.ReadAsStringAsync();
GetTokenResults g = JsonConvert.DeserializeObject<GetTokenResults>(json);
return g.Token;
要编译它,您需要做的最后一件事是将方法签名更改为:
public async Task<string> GetTokenAsync
最后一点:您现在处于异步世界中,这是一件好事,但您需要知道如何正确使用它,否则您可能会遇到死锁和其他神秘错误。简而言之,don't block on async code 通过在调用堆栈的任何位置调用 .Result
或 .Wait()
。这是迄今为止人们最常犯的错误。使用async/await
一路向下.