Как читать параметры, отправленные в метод действия (WebAPI) в DelegatingHandler - PullRequest
1 голос
/ 05 июня 2019

Я использую IHttpClientFactory для отправки запросов и получения HTTP-ответов от внешних API-интерфейсов с использованием Net Core 2.2.

Я реализовал DelegatingHandler для «перехвата» моего http-запроса и добавления заголовка авторизации (Token).если токен недействителен, он получает новый токен и повторяет попытку еще раз.

Аналогично, когда я впервые получаю новый токен, я кеширую токен в памяти для дальнейших ссылок.Для кеширования токена я создал словарь, который требует accountID и токен.

Проблема, с которой я столкнулся, состоит в том, что DelegatingHandler зарегистрирован в классе Startup.cs, но в тот момент у меня нет accountID, я получаю accountID в качестве параметра в ActionMethod Контроллера.Этот метод действия вызывает метод SendAsync и получает токен от DelegatingHandler и т. Д.

Я не знаю, как я могу внедрить этот accountID в DelegatingHandler после получения запроса в контроллере.

Я пытался создать интерфейс IClientCredentials и реализовать этот интерфейс, который может быть создан в контроллере и внедрен в DelegatingHandler.

Мой код выглядит следующим образом:

DelegatingHandler:

public class AuthenticationDelegatingHandler : DelegatingHandler
{

    private readonly AccessTokenManager _accessTokenManager;
    private readonly IClientCredentials _clientCredentials;

    public AuthenticationDelegatingHandler(IHttpClientFactory httpClientFactory, 
                                           IOptions<AppSettings> appSettings, IClientCredentials clientCredentials)
    {
        _accessTokenManager = new AccessTokenManager(httpClientFactory, appSettings);
        _clientCredentials = clientCredentials;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var clientCredentials = _clientCredentials.GetClientCredentials();

        var accessToken =  _accessTokenManager.GetToken(clientCredentials._accountID);

        if (accessToken == null) {               

             accessToken = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
            _accessTokenManager.AddOrUpdateToken(clientCredentials._accountID, accessToken);
        }

        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.access_token);

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

        if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
        {
            var token = await _accessTokenManager.GetAccessTokenAsync(clientCredentials._accountID);
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.access_token);
            response = await base.SendAsync(request, cancellationToken);
        }

        return response;
    }

}

Startup.cs так:

 services.AddScoped<IClientCredentials>(_ => new 
                    ClientCredentials("au","123"));

services.AddHttpClient("myClient")
              .AddHttpMessageHandler<AuthenticationDelegatingHandler>();

И контроллер:

[HttpPost("{siteName}/{accountID}")]
public async Task<ActionResult<AirRequest>> Post(AirModel model, string 
siteName, string accountID)
    {
      ....
      SetClientCredentials(siteName, accountID);

      var clientJAAPI = 
      _httpClientFactory.CreateClient("myClient");

      var responseclientJAAPI = await 
        clientJAAPI.SendAsync(request);
     .....
    }

  private ClientCredentials SetClientCredentials(string siteName, string 
  accountID) =>
       new ClientCredentials(siteName, accountID);

1 Ответ

0 голосов
/ 05 июня 2019

Вы можете использовать HttpContext.Items для передачи данных. (Не проверено, отправлено с мобильного). В контроллере:

this.HttpContext.Items["accountId"] = accountId;

В ваш обработчик впрыснуть IHttpContextAccessor

var accountId = _httpContextAccessor.HttpContext.Items["accountId"];

IHttpContextAccessor не зарегистрирован по умолчанию, но может быть зарегистрирован одним из компонентов, которые вы используете. Если вы получили исключение, зарегистрируйте его явно в DI:

services.AddHttpContextAccessor();

Если тип IHttpContextAccessor отсутствует, добавьте Microsoft.AspNetCore.Http nuget.

Данные будут храниться до конца запроса.

...