#c# #asp.net #asp.net-core #asp.net-core-middleware
#c# #asp.net #asp.net-core #asp.net-core-промежуточное программное обеспечение
Вопрос:
Я ищу способ сделать это в каждом методе каждого контроллера, даже для тех, которые не возвращают IActionResult (я буду говорить об этом в будущем):
- Получите User.Claim, чтобы получить информацию о пользователе, зарегистрированную на сайте.
- Проверьте, заблокирован ли пользователь в базе данных (у меня уже работают мои собственные репозитории)
- Перенаправить пользователя на страницу, которая показывает «вы заблокированы», как это делает рабочий процесс исключений.
Соображения и попытки, которые я уже сделал:
- Не могу получить это из заявки, чтобы работать с ViewStart, потому что мне нужно, чтобы блок работал в тот же момент, когда база данных была обновлена. Утверждение должно заставить пользователя выйти и войти в систему.
- Не могу сделать это через контроллер, который возвращает логическое значение с Json на каждой странице, потому что пользователь может остановить перенаправление
- У меня есть несколько методов, которые возвращают partialviews, objects, lists, что угодно, кроме IActionResult. Мне все равно, если это не сработает по двум причинам:
- Это должно быть вызвано основным представлением, которое вызывает их через ajax.
- Пользователь все равно заблокирован, поэтому мне все равно, увидит ли он, что страница сломана.
- Мой рабочий процесс безопасности выглядит следующим образом:
[HttpPost] [Authorize(Policy = "Users")] [Authorize(AuthenticationSchemes = "MyAppScheme")] public IActionResult GetRep() { //Do things }
Прямо сейчас я пытаюсь создать промежуточное программное обеспечение, но я новичок в NET Core на таком глубоком уровне, поэтому не могу скомпилировать ни то, ни другое. Также работает попытка вызвать мой UserRepository из ViewStart
Комментарии:
1. Почему вы не используете промежуточные программы, которые будут работать глобально в вашем приложении. Фильтр действий был бы лучшим выбором Chekc MS Docs
2. @RabbyHasan спасибо! Да, это то, что я пытаюсь, но не знаю, как это сделать правильно
Ответ №1:
Лучший способ — использовать промежуточное программное обеспечение. Вот вам пример:
internal class UserMiddleware
{
private readonly RequestDelegate next;
private readonly IUserRepository userRepository;
public UserMiddleware(RequestDelegate next, IUserRepository userRepository)
{
this.next = next ?? throw new ArgumentNullException(nameof(next));
this.userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
}
public async Task Invoke(HttpContext httpContext)
{
Claim clientId = httpContext.User.FindFirst(ClaimTypes.NameIdentifier);
bool isBlocked = await this.userRepository.CheckUser(clientId);
if (isBlocked)
{
await httpContext.Response.WriteAsync("You are blocked.");
return;
}
await this.next(httpContext);
}
}
Затем в вашем методе запуска вы должны вызвать его перед отображением ваших контроллеров:
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Other stuff...
app.UseMiddleware<UserMiddleware>();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Комментарии:
1. Теперь у меня есть несколько проблем с ‘Вторая операция началась в этом контексте до завершения предыдущей операции. Обычно это вызвано тем, что разные потоки используют один и тот же экземпляр DbContext. Для получения дополнительной информации о том, как избежать проблем с потоками с DbContext, см. go.microsoft.com/fwlink/?linkid=2097913 .’
2. Не знаю почему, потому что я делаю обычное user = await _context . Пользователи. Где(u => u.Guid == guid amp;amp; u.Удалено == 0 amp;amp; u.Заблокировано == 0).FirstAsync();