#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 для этого.