Во время Rest запроса появляются символы?

Написал запрос на сайт

public static string UTCtime()
        {
            string url = "http://worldtimeapi.org/api/timezone/Europe/Berlin";
            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            string response ;
            StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
            response = streamReader.ReadToEnd();
            streamReader.Close();
            IRoot myDeserializedClass = JsonConvert.DeserializeObject<IRoot>(response);
            string[] UTC = myDeserializedClass.utc_datetime.Split('.');
            string UTCg = UTC[0].Replace(":","%3A");
            Console.WriteLine(UTCg);
            return UTCg;
        }

Результат этого запроса используется в другом запросе и вот тут начинаются проблемы.Дело в том что вот значение, которое должно отправляться в последующем запросе

2021-09-07T19%3A07%3A10

А вот значение ,которое отправляется по факту

2021-09-07T19%3**25**A07%3**25**A10

В чем проблема не очень понятно. Для большей ясности вот дата которую обрабатываю

2021-09-07T17:29:18

мой код запроса, где используется метод

var request = new RestRequest("/v1/account/accounts");
request.AddQueryParameter("AccessKeyId", apikey);
request.AddQueryParameter("SignatureMethod", "HmacSHA256");
request.AddQueryParameter("SignatureVersion", "2");
request.AddQueryParameter("Timestamp", UTCtime());
request.AddQueryParameter("Signature", CreateSignature(request.Parameters, secret,Method,endpoint,base_uri));
var response = client.Get(request); string Response = response.Content;

Ответы (1 шт):

Автор решения: aepot

Если задача в получении времени из сети именно из этой API, то вы слишком хардкорно подошли к вопросу, все делается намного проще.

Беру строковый ответ API, копирую в буфер обмена Crtl+C.

{
  "abbreviation": "CEST",
  "client_ip": "x.x.x.x",
  "datetime": "2021-09-08T09:03:41.483887+02:00",
  "day_of_week": 3,
  "day_of_year": 251,
  "dst": true,
  "dst_from": "2021-03-28T01:00:00+00:00",
  "dst_offset": 3600,
  "dst_until": "2021-10-31T01:00:00+00:00",
  "raw_offset": 3600,
  "timezone": "Europe/Berlin",
  "unixtime": 1631084621,
  "utc_datetime": "2021-09-08T07:03:41.483887+00:00",
  "utc_offset": "+02:00",
  "week_number": 36
}

Открываю студию, выбираю меню Edit - Paste Special - Paste JSON as classes, получаю класс, переименовываю его, получается код:

public class WorldTimeResponse
{
    public string abbreviation { get; set; }
    public string client_ip { get; set; }
    public DateTime datetime { get; set; }
    public int day_of_week { get; set; }
    public int day_of_year { get; set; }
    public bool dst { get; set; }
    public DateTime dst_from { get; set; }
    public int dst_offset { get; set; }
    public DateTime dst_until { get; set; }
    public int raw_offset { get; set; }
    public string timezone { get; set; }
    public int unixtime { get; set; }
    public DateTime utc_datetime { get; set; }
    public string utc_offset { get; set; }
    public int week_number { get; set; }
}

Лишнее можно конечно выкинуть отсюда.

Далее, вы используете HttpWebRequest, который устарел, когда я еще был маленький и ничего не знал про C#. Закопайте его обратно. Нужно использовать HttpClient.

private static readonly HttpClient client = new HttpClient();

public static async Task<DateTime> UTCtime()
{
    string url = "http://worldtimeapi.org/api/timezone/Europe/Berlin";
    WorldTimeResponse time = await client.GetFromJsonAsync<WorldTimeResponse>(url);
    return time.utc_datetime.ToUniversalTime();
}

И вот вы уже из метода получаете не непонятную строчку, а готовый экземпляр DateTime.

Далее можно с ним делать что угодно, например вот это:

DateTime time = await UTCtime();
Console.WriteLine(time.ToString("s"));
Console.WriteLine(time.ToString("yyyy-MM-ddTHH:mm"));
Console.WriteLine(HttpUtility.UrlEncode(time.ToString("s")).ToUpper());
Console.WriteLine(HttpUtility.UrlEncode(time.ToString("yyyy-MM-ddTHH:mm")).ToUpper());

Вывод в консоль

2021-09-08T07:46:37
2021-09-08T07:46
2021-09-08T07%3A46%3A37
2021-09-08T07%3A46

Кстати, выбранная вами API медленная, экземпляр DateTime можно получить гораздо быстрее. Например с использованием протокола Network Time Protocol (NTP).

public static async Task<DateTime> GetNetworkTimeAsync(string ntpServer, int timeout = 500)
{
    byte[] ntpData = new byte[48];
    ntpData[0] = 0x1B;
    double jitter = 0;
    using (UdpClient client = new UdpClient(ntpServer, 123))
    {
        Task<UdpReceiveResult> receiveTask = client.ReceiveAsync(); // начинаем ждать ответа
        DateTime now = DateTime.Now;
        await client.SendAsync(ntpData, ntpData.Length); // и только потом отправляем запрос
        if (receiveTask == await Task.WhenAny(receiveTask, Task.Delay(timeout)))
            ntpData = receiveTask.Result.Buffer;
        else
            throw new TimeoutException("Timeout occured while waiting for NTP server response");
        jitter = (DateTime.Now - now).TotalMilliseconds / 2; // разброс = пинг / 2, для меня это примерно 25 мс
    }
    byte[] data = ntpData[40..];
    Array.Reverse(data);
    uint fraction = BitConverter.ToUInt32(data);
    uint seconds = BitConverter.ToUInt32(data, 4);
    double milliseconds = (double)seconds * 1000 + (double)fraction * 1000 / 0x100000000L + jitter;
    DateTime networkDateTime = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(milliseconds);
    return networkDateTime;
}

Использовать просто

DateTime time = await GetNetworkTimeAsync("pool.ntp.org");

Результат тот же, но работает почти мгновенно, а не полторы секунды, как API.

Но зачем вообще отправлять запрос за временем в сеть? Ведь можно просто сделать вот так:

DateTime time = DateTime.UtcNow;

По поводу отправляемого запроса, вам не нужно кодировать в Url Encoding, RestClient должен делать это автоматически. Просто вот так:

request.AddQueryParameter("Timestamp", DateTime.UtcNow.ToString("s"));

Кстати, вместо RestClient я бы тоже предложил использовать HttpClient. Примеров его использования в сети очень много.

→ Ссылка