Использование класса DelegatingHandler в классе HttpClient из оконных форм. Внутренний обработчик не установлен.

Во-первых, сообщение об ошибке, которое я получаю, выглядит следующим образом: Внутренний обработчик не установлен

Я пишу специальный обработчик сообщений для обработки тайм-аутов cookie проверки подлинности для моего API. Например, если моя база кода делает вызов API и, в свою очередь, получает 401, то он должен повторить URL-адрес входа, чтобы получить обновленный файл cookie. Я планировал сделать это следующим образом:

public class CkApiMessageHandler : DelegatingHandler
{
    private readonly string _email;
    private readonly string _password;
    private const string _loginPath = "Account/Login";

    public CkApiMessageHandler(string email, string password)
    {
        _email = email;
        _password = password;

        //InnerHandler = new HttpControllerDispatcher(null);
    }

    protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {

        var response = await base.SendAsync(request, cancellationToken);

        if(response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        {
            Logging.Logger.LogInformation("Authentication cookie timed out");
            var baseAddress = request.RequestUri.Host;
            var loginPath = baseAddress + _loginPath;

            var originalRequest = request;

            var loginRequest = new HttpRequestMessage(new HttpMethod("POST"), loginPath);
            var dict = new Dictionary<string, string>();
            dict.Add("Email", _email);
            dict.Add("Password", _password);

            var form = new FormUrlEncodedContent(dict);
            loginRequest.Content = form;
            loginRequest.Headers.Clear();

            foreach(var header in originalRequest.Headers)
            {
                loginRequest.Headers.Add(header.Key, header.Value);
            }

            var loginResponse = await base.SendAsync(loginRequest, cancellationToken);

            if (loginResponse.IsSuccessStatusCode)
            {
                Logging.Logger.LogInformation("Successfully logged back in");
                return await base.SendAsync(originalRequest, cancellationToken);
            }
            else
            {
                Logging.Logger.LogException(new Exception("Failed to log back in"), "Could not log back in");
            }
        }

        return response;
    }


}  

Я преобразовываю старую службу, которая используется для прямого доступа к базе данных, к службе, которая обращается к веб-api, и я пытаюсь это сделать, не меняя ни одного из потребителей этого класса. Следовательно, странный обработчик, Ниже приведен пример метода из класса службы.

 public void UpdateClientInstallDatabaseAndServiceData(string dbAcronym, string clientVersion, string clientEnginePort, Guid installationId, string sqlserver)
    {
        var dict = new Dictionary<string, string>();
        dict.Add("dbAcronym", dbAcronym);
        dict.Add("clientVersion", clientVersion);
        dict.Add("clientEnginePort", clientEnginePort);
        dict.Add("desktopClientId", installationId.ToString());
        dict.Add("sqlServerIp", sqlserver);

        var form = new FormUrlEncodedContent(dict);

        _client.PostAsync(_apiPath + "/UpdateClientInstallDatabaseAndServiceData", form);
    }  

Таким образом, если приведенный выше код завершится с ошибкой 401, служба автоматически выполнит вход в систему и повторит первоначальный код без того, чтобы потребитель службы должен был проверять запросы и переходить обратно. Потребитель не должен знать, что он имеет дело с веб-api.

Моя проблема в том, что мой обработчик сообщения ожидает установки InnerHandler, для которой требуется экземпляр класса HttpConfiguration. Когда я рассмотрю спецификации здесь, это, как представляется, некоторый тип класса, используемый для настройки службы веб-api. Это хорошо, за исключением того, что этот код не выполняется в api.. Он выполняется в приложении Windows Forms. Обработчик делегирования используется в классе HttpClient, таком как...

_client = new HttpClient(new CKEnterprise.Common.CkApiMessageHandler(email, password));  

Итак, мой вопрос: Как я могу заставить этот DelegatingHandler выполнять эту работу за пределами контекста веб-проекта api?

Выполнение обновления. Похоже, что я могу просто использовать класс HttpClientHandler https://blogs.msdn.microsoft.com/henrikn/2012/08/07/httpclient-httpclienthandler-and-webrequesthandler-explained/

Ответ 1

Я должен был это осознать раньше, но имеет смысл установить внутренний обработчик для по умолчанию обработчика HttpClient. Таким образом, внутри вашего дочернего класса DelegatingHandler вы должны установить свой внутренний обработчик в обработчик по умолчанию, используемый HttpClient следующим образом:

    public CkApiMessageHandler(string email, string password, Guid moduleId)
    {
        _email = email;
        _password = password;
        _moduleId = moduleId;
        InnerHandler = new HttpClientHandler();

    }