Доступ к DbContext в промежуточном ПО в ASP.NET 5
Я написал свое собственное промежуточное программное обеспечение, которое я добавляю в
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//...
app.UseAutologin();
app.UseMvc(routes =>
{
//...
Итак, это последнее промежуточное ПО, прежде чем Mvc вступает в игру.
В моем методе middleware Invoke
я хочу (косвенно) получить доступ к DbContext
.
public async Task Invoke(HttpContext context)
{
if (string.IsNullOrEmpty(context.User.Identity.Name))
{
var applicationContext = _serviceProvider.GetService<ApplicationDbContext>();
var signInManager = _serviceProvider.GetService<SignInManager<ApplicationUser>>();
var result = await signInManager.PasswordSignInAsync(_options.UserName, _options.Password, true, false);
}
await _next(context);
}
Почти каждый раз я получаю следующее исключение:
InvalidOperationException
: Была сделана попытка использовать контекст пока он настроен. Невозможно использовать экземпляр DbContext
внутри OnConfiguring
, поскольку он все еще настроен в этой точке.
Теперь это ясно выражено методом PasswordSignInAsync
. Но как я могу гарантировать, что модель была создана, прежде чем делать такие вещи?
Возможно, я был не совсем ясен: я не хочу использовать DbContext
сам - PasswordSignInAsync
использует его при проверке пользователя и пароля.
Ответы
Ответ 1
Что делать, если вы введете ApplicationDbContext
и SignInManager<ApplicationUser>
с помощью метода Invoke
:
public async Task Invoke(HttpContext context, ApplicationDbContext applicationContext, SignInManager<ApplicationUser> signInManager)
{
if (string.IsNullOrEmpty(context.User.Identity.Name))
{
var result = await signInManager.PasswordSignInAsync(_options.UserName, _options.Password, true, false);
}
await _next(context);
}
Таким образом, службы будут устранены из правильной области. Я заметил, что вы на самом деле не используете ApplicationDbContext
в любом месте, просто SignInManager
. Вам это действительно нужно?
Ответ 2
Эта ошибка, вероятно, происходит потому, что любое промежуточное ПО действует как одноэлементное. Вы должны избегать использования переменных-членов в промежуточном программном обеспечении. Не стесняйтесь вводить в Invoke задачи, но не сохраняйте значение вставки в объект-член.
Смотрите: Сохранение экземпляра HttpContext в промежуточном программном обеспечении, Услуги вызова в промежуточном программном обеспечении
Мне удалось обойти это самостоятельно, создав класс, который я мог бы передать другим методам в моем промежуточном программном обеспечении:
public async Task Invoke(HttpContext context, IMetaService metaService)
{
var middler = new Middler
{
Context = context,
MetaService = metaService
};
DoSomething(middler);
}