Emi*_*las 2 attributes dependency-injection entity-framework-core asp.net-core
我正在创建 ASP.NET Core 3.1 应用程序,使用 SPA 作为前端。所以我决定创建自定义身份验证和授权。因此,我创建了自定义属性来发出和验证 JWT。
可以说它看起来像这样:
[AttributeUsage(AttributeTargets.Method)]
public class AuthLoginAttribute : Attribute, IAuthorizationFilter
{
public async void OnAuthorization(AuthorizationFilterContext filterContext)
{
//Checking Headers..
using (var EF = new DatabaseContext)
{
user = EF.User.Where(p => (p.Email == username)).FirstOrDefault();
}
filterContext.HttpContext.Response.Headers.Add(
"AccessToken",
AccessToken.CreateAccessToken(user));
}
}
Run Code Online (Sandbox Code Playgroud)
一切都很好,但我的DatabaseContext,看起来像这样:
public class DatabaseContext : DbContext
{
public DbSet<User> User { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL("ConnectionString");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//....
}
}
Run Code Online (Sandbox Code Playgroud)
我想从 Appsettings.json 中获取连接字符串,并可能使用依赖注入。我将 Startup.cs 更改为如下所示:
//...
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<DatabaseContext>(
options => options.UseMySQL(Configuration["ConnectionStrings:ConnectionString"]));
services.Add(new ServiceDescriptor(
typeof(HMACSHA256_Algo), new HMACSHA256_Algo(Configuration)));
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
//...
Run Code Online (Sandbox Code Playgroud)
将数据库上下文类更改为:
public class DatabaseContext : DbContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
public DbSet<User> User { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
///..
}
}
Run Code Online (Sandbox Code Playgroud)
在控制器中,我注入了数据库上下文,一切正常。它看起来像这样:
[ApiController]
[Route("API")]
public class APIController : ControllerBase
{
private DatabaseContext EF;
public WeatherForecastController(DatabaseContext ef)
{
EF = ef;
}
[HttpGet]
[Route("/API/GetSomething")]
public async Task<IEnumerable<Something>> GetSomething()
{
using(EF){
//.. this works
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我的自定义属性不再起作用。我无法声明新的数据库上下文,因为它需要DatabaseContextOptions<DatabaseContext>对象来声明,那么如何像对控制器那样将 DBContext 注入到属性中?
这不起作用:
public class AuthLoginAttribute : Attribute, IAuthorizationFilter
{
private DatabaseContext EF;
public AuthLoginAttribute(DatabaseContext ef)
{
EF = ef;
}
public async void OnAuthorization(AuthorizationFilterContext filterContext)
{
using(EF){
}
}
}
Run Code Online (Sandbox Code Playgroud)
这适用于控制器,但使用属性会抱怨没有带有 0 个参数的构造函数。
您可以做的是利用 RequestServices:
[AttributeUsage(AttributeTargets.Method)]
public class AuthLoginAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var dbContext = context.HttpContext
.RequestServices
.GetService(typeof(DatabaseContext)) as DatabaseContext;
// your code
}
}
Run Code Online (Sandbox Code Playgroud)
如果您允许我在您的代码中添加两条注释:
async void因为一旦发生异常你会很困惑到底发生了什么。using(EF) { .. }。您将尽早处理它,这将导致稍后的请求中出现错误。DI 容器正在为您管理生命周期,相信它。| 归档时间: |
|
| 查看次数: |
4241 次 |
| 最近记录: |