12:43 PM
6 hours later…
6:48 PM
public class Query : IRequest<int?> { public Query(int id) { this.Id = id; } public int Id { get; } } public class Handler : BaseHandler, IRequestHandler<Query, int?> { public Task<int?> Handle(Query request, CancellationToken cancellationToken) { return this.Call<int?>(Url, request, cancellationToken); } private const string Url = "/api/SomeEntity/SomeMethod/"; }
И вся логика по обработке запроса была вынесена в большой класс (который скрывает детали реализации -- что используется HttpClient, что запросы отправляются в json и расшифровываются обратно, что используется JWT токен для авторизации):
public class BaseHandler { protected BaseHandler() { this.Client = new HttpClient(); } private HttpClient Client { get; } private const string BaseUrl = "https://server.tld"; private const string ServiceAccountUserName = "user"; private const string ServiceAccountUserPassword = "password"; protected async Task<T> Call<T>(string uri, object request, CancellationToken cancellationToken) { var jsonString = JsonConvert.SerializeObject(request);
В принципе, меня до какого-то момента всё устраивало: весь код тихо складирован в одном месте, всё под рукой... Однако захотелось мне сделать запрос токена не на каждый запрос, а на некоторое время -- понял, что класс распухнет и решил немного предварительно порефакторить.
Методы PostWithToken и PostWithoutToken отправились в класс WebTransport, поскольку они практически одинаковые то они стали одним-единственным методом Call:
public class WebTransport { public WebTransport(HttpClient client) { this.Client = client; } private HttpClient Client { get; } public async Task<string> Call(string uri, string data) { var content = new StringContent(data, Encoding.UTF8, "application/json"); var response = await this.Client.PostAsync(uri, content); return await response.Content.ReadAsStringAsync(); } }
Соответственно, нам нужно два вида клиентов (для запроса с токеном и без токена), поэтому появилась небольшая фабрика:
public static class HttpClientFactory { public static HttpClient Get(string token) { var client = new HttpClient(); if (token != null) client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); return client; } }
Процесс обработки запроса стал унифицированным, что его стало возможным вынести в отдельный менеджер, который занимается только этим:
public static class WebProcessor { public static async Task<T> Call<T>(string url, object request, string token) { var jsonString = JsonConvert.SerializeObject(request); var client = new WebTransport(HttpClientFactory.Get(token)); var result = await client.Call($"{BaseUrl}{url}", jsonString); var deserialized = JsonConvert.DeserializeObject<T>(result); return deserialized; } private const string BaseUrl = "https://server.tld";
public static class TokenObtainer { public static async Task<string> GetToken(string userName, string password) { var request = new TokenRequest { UserName = userName, Password = password, }; var result = await WebProcessor.Call<TokenAnwer>("/api/token", request, null); return result.Token; } private class TokenRequest { public string UserName { get; set; }
public class BaseHandler { protected BaseHandler() { Token = null; } private static string Token { get; set; } protected async Task<T> Call<T>(string url, object request) { await this.AssertToken(); return await WebProcessor.Call<T>(url, request, Token); } private async Task AssertToken() { // TODO: Check expired if (Token != null) return;
2 hours later…
9:59 PM
10:43 PM
« first day (1579 days earlier) ← previous day next day → last day (1452 days later) »
Transcript for
Dec10
Dec '1911
Dec12
Дискуссии о C#/.NET на русском
Эта комната посвящена обсуждению C#: всё, что не подходит в фо...