Нужна помощь в преобразовании моего кода RestSharp для использования вместо HttpClient - PullRequest
0 голосов
/ 24 января 2019

В связи с тем, что мне нужно преобразовать эту 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 - это структура, содержащая объявление для строки Token. Я хочу достичь этой же функциональности без использования 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);

}

Мне неясно, как добиться тех же результатов (отправить ключ и пароль API, вернуть токен в виде строки), используя HttpClient, как я делал это раньше с помощью RestSharp. Все, что может направить меня в правильном направлении, очень ценится!

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Я думаю, вы были ужалены этой проблемой .Короче говоря, URI в client.BaseAddress нуждается в косой черте в конце.

Однако я бы не добавил его просто, я бы подумал сделать это немного по-другому.Предположительно, ваш BaseUrl уже имеет косую черту, если вы добавляете "auth/GetToken" к нему.Я бы сделал это следующим образом:

client.BaseAddress = new Uri(BaseUrl);
...
var response = await client.PostAsync("auth/GetToken", content);

Как видите, HttpClient очень точно соответствует тому, как ваш код уже настроен, то есть у вас есть "базовый" адрес с косой чертой иВы хотите добавить к нему конкретный вызов.

Это должно привести вас к этому.Следующее, что вам нужно будет сделать, это десериализовать ответ 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

Последнее замечание: вы сейчас находитесь в асинхронном мире, и это хорошо, но вам нужно знать, как использоватьэто правильно, иначе вы можете получить тупики и другие загадочные ошибки.Короче говоря, не блокирует асинхронный код , вызывая .Result или .Wait() в любом месте стека вызовов.Это самая распространенная ошибка, которую делают люди.Используйте async/await до упора .

0 голосов
/ 24 января 2019

Я думаю, что вам не хватает первого параметра в методе 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;
    }
...