【问题标题】:How to Read Parameters sent to an Action Method (WebAPI) within a DelegatingHandler如何在 DelegatingHandler 中读取发送到操作方法 (WebAPI) 的参数
【发布时间】:2019-06-05 08:38:30
【问题描述】:

我正在使用 IHttpClientFactory 使用 Net Core 2.2 从外部 API 发送请求和接收 HTTP 响应。

我已经实现了一个 DelegatingHandler 来“拦截”我的 http 请求并添加授权标头(令牌)。如果令牌无效,它会获取一个新令牌并重试一次。

同样,当我第一次获得新令牌时,我会将令牌缓存在内存中以供进一步参考。为了缓存令牌,我创建了一个需要 accountID 和令牌的字典。

我遇到的问题是在Startup.cs类中注册了DelegatingHandler,但是此时我没有accountID,我在Controller的ActionMethod中获取accountID作为参数。该操作方法是调用 SendAsync 并从 DelegatingHandler 获取令牌等等。

我不知道,在控制器收到请求后,如何将该 accountID 注入 DelegatingHandler。

我正在尝试创建 IClientCredentials 接口和该接口的实现,该接口可以在控制器中实例化并注入 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);

【问题讨论】:

    标签: c# asp.net-core dependency-injection token httpclientfactory


    【解决方案1】:

    您可以使用HttpContext.Items 传递数据。 (未经测试,从手机发送)。 在控制器中:

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

    在你的处理程序中注入IHttpContextAccessor

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

    IHttpContextAccessor 默认情况下未注册,但可以由您正在使用的组件之一注册。如果遇到异常,请在 DI 中显式注册:

    services.AddHttpContextAccessor();
    

    如果缺少 IHttpContextAccessor 类型,请添加 Microsoft.AspNetCore.Http nuget。

    数据将保留在那里,直到请求结束。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      相关资源
      最近更新 更多