Механизм AspNet Mvc для «Сделай что-нибудь для каждого действия» имеет значение Фильтры .
Фильтры могут работать до вызова метода, и они могут, например, установить Http.Context.User
.
Фильтр может быть применен к действию, контроллеру или (путем записи кода в Startup
) глобально.
[SwapUserToAuthorizedDatabaseUser]
public class MyController
{
public IActionResult About() => Ok(User);
}
, который будет вызывать этот фильтр для каждого действия вКонтроллер:
public class SwapUserToAuthorizedDatabaseUserAttribute : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
SiteUser currentUser = new SiteUser(db, User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value);
if (currentUser == null)
{
context.Result= new RedirectToRouteResult("/Identity/Logout");
}
else
{
var claimsIdentity =
new ClaimsIdentity(
new Claim[]
{
new Claim("Id", currentUser.Id),
new Claim("UserName", currentUser.UserName),
new Claim("WhateverElseYourSiteUserHas", currentUser.Something.ToString()),
}
);
context.HttpContext.User = new ClaimsPrincipal(new[]{claimsIdentity});
}
}
public void OnActionExecuted(ActionExecutedContext context){}
}
Если перезапись HttpContext.User
это не то, что вам нужно, тогда гораздо меньше кода для использования HttpContext.Items
:
public class SwapUserToAuthorizedDatabaseUserAttribute : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Items["SiteUser"]= new SiteUser(db, User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value);
}
public void OnActionExecuted(ActionExecutedContext context){}
}
вместо IActionFilter
для выполнения каждого действия вы можете использовать IAuthorizationFilter
, который имеет метод public void OnAuthorization(AuthorizationFilterContext context)
.Это позволило бы избежать повторного вызова базы данных, но означает ли это, что вы должны где-то кэшировать currentUser
, предположительно в Session
.
Проблема в том, как получить доступ к вашей базе данных?Если вы идете по пути добавления Глобального фильтра, добавив его в Startup:
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc(o=>o.Filters.Add(new SwapUserToAuthorizedDatabaseUserAttribute(provide a db instance here)));
}
Тогда вы можете дать свой Filter конструктор и передать в базу данных.Существует также перегрузка для использования системы DependencyInjection.
Если вы не используете метод запуска, вам придется сделать некоторую самостоятельную инъекцию, например, имея статический метод для возврата DbContext
.