Параметры регистрации службы

#c# #asp.net-core #dependency-injection

#c# #asp.net-core #внедрение зависимостей

Вопрос:

У меня есть этот класс, который получает значение заголовка авторизации из заголовка и сохраняет его в переменной следующим образом:

 public class AuthenticationHeader
{
   private static  IHttpContextAccessor _httpContextAccessor;
   public AuthenticationHeader(IHttpContextAccessor httpContextAccessor)
   {
      _httpContextAccessor = httpContextAccessor;
   }
   public string AuthHeader => _httpContextAccessor.HttpContext?.Request.Headers["Authorization"]
}
  

И я зарегистрировал этот класс для DI вот так в моем Startup.cs

 services.AddScoped<AuthenticationHeader>();
  

И затем этот класс используется в моем NetworkClient с использованием внедрения конструктора.

 public ClubMatasClient(HttpClient client, ILogger<ClubMatasClient> logger, AuthenticationHeader authHeader)
{
   _client = client;
   client.BaseAddress = new Uri("url");
   client.DefaultRequestHeaders.Add("Accept", "application/json");
   _logger = logger;
   AuthToken = authHeader.AuthHeader;
}
  

Я прочитал жизненный цикл Scoped и Transient в здешних документах, и я в замешательстве, какой из них мне следует использовать. Я не хочу смешивать заголовки аутентификации, которые поступают в заголовки моего запроса.

Ответ №1:

Область действия определяется для каждого http-запроса, переходный — для каждого типа.

Поскольку ваш заголовок авторизации соответствует запросу, вы можете зарегистрировать AuthenticationHeader класс как ограниченный, что означает, что все типы, созданные для обслуживания вашего запроса, получат один и тот же экземпляр.

Но вы также можете зарегистрировать его как временный, тогда все типы, созданные для обслуживания вашего запроса, получат новый экземпляр AuthenticationHeader , который внутренне использует IHttpContextAccessor, который предоставит вам тот же HttpContext для вашего http-запроса.

Таким образом, вы можете использовать оба варианта, единственное соображение — это потребление памяти. Область действия будет использовать меньше памяти.

Редактировать: На самом деле вы также можете использовать Singleton, потому что IHttpContextAccessor зарегистрирован как Singleton и внутренне использует AsyncLocal для хранения текущего контекста. Но я бы не рекомендовал это, потому что в будущем AuthenticationHeader может быть расширен с некоторой дополнительной логикой, которая нарушит поведение.

Комментарии:

1. @Arthur на самом деле я пытался использовать Singleton , но он сохранял authToken, и если бы я добавил заголовок авторизации со значением в нем, он работал бы нормально (запрос выполнен успешно), но он работал нормально, даже если я отправил пустой заголовок авторизации, который был неправильным, потому что из-за регистрации как Singleton он сохранял последнее значение заголовка.

2. @Shabirjan, это странно. Я попытаюсь проверить это, чтобы выяснить, почему. Из-за AsyncLocal все должно работать нормально.

3. @Shabirjan Я только что проверил это, и все работает так, как ожидалось. Возможно, у вас проблема в другом месте.

4. Нет, когда я зарегистрировал свой AuthorizationHeader как одноэлементный, первый запрос, содержащий заголовок авторизации, работал нормально. Когда я попробовал второй запрос одновременно. Я добавил пустой заголовок авторизации, по логике он не должен работать, но при отладке в AuthHeader было старое значение. Таким образом, запрос с пустым заголовком Auth также успешно выполнен.

5. ок, проблема найдена. теперь он отлично работает и в Singleton. Но все же я считаю, что мне не следует использовать singleton для этого.