I have set a filter to work upon a specific folder and all pages inside it. I need to access database using a claim. The problem is that I cannot seem to register my filter with DI on startup services cause it does not find the database connection
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Administration", "/Account");
options.Conventions.AuthorizeAreaFolder("Production", "/Account");
options.Conventions.AuthorizeAreaFolder("Robotics", "/Account");
options.Conventions.AddAreaFolderApplicationModelConvention("Production", "/FrontEnd",
model => model.Filters.Add(
new LockdownFilter(
new ProducaoRegistoService(new ProductionContext()),
new UrlHelperFactory(),
new HttpContextAccessor())));
})
the filter.
public class LockdownFilter : IAsyncPageFilter
{
private readonly IProducaoRegistoService _producaoRegistoService;
private readonly IUrlHelperFactory _urlHelperFactory;
private readonly IHttpContextAccessor _httpContextAccessor;
public LockdownFilter(IProducaoRegistoService producaoRegistoService, IUrlHelperFactory urlHelperFactory, IHttpContextAccessor httpContextAccessor)
{
_producaoRegistoService = producaoRegistoService;
_urlHelperFactory = urlHelperFactory;
_httpContextAccessor = httpContextAccessor;
}
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
int registoId;
if(!int.TryParse(_httpContextAccessor.HttpContext.User.GetRegistoId(), out registoId))
{
// TODO
}
var registo = _producaoRegistoService.GetById(registoId);
await next.Invoke();
}
public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
await Task.CompletedTask;
}
}
the error is
InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.
here is the whole startup class
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
})
.AddCookie("ProductionUserAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Production/FrontEnd/Login");
options.LogoutPath = new PathString("/Production/FrontEnd/Logout");
options.AccessDeniedPath = new PathString("/Production/FrontEnd/AccessDenied");
options.SlidingExpiration = true;
options.Cookie.Name = "NoPaper.ProductionUser";
options.Cookie.Expiration = TimeSpan.FromDays(1);
})
.AddCookie("ProductionAdminAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Production/BackOffice/Login");
options.LogoutPath = new PathString("/Production/BackOffice/Logout");
options.AccessDeniedPath = new PathString("/Production/BackOffice/AccessDenied");
options.SlidingExpiration = true;
options.Cookie.Name = "NoPaper.ProductionAdmin";
options.Cookie.Expiration = TimeSpan.FromDays(1);
})
.AddCookie("AdministrationAuth", options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.LoginPath = new PathString("/Administration/Index");
options.LogoutPath = new PathString("/Administration/Logout");
options.AccessDeniedPath = new PathString("/Administration/AccessDenied");
options.SlidingExpiration = true;
options.Cookie.Name = "NoPaper.Administration";
options.Cookie.Expiration = TimeSpan.FromDays(1);
});
services.AddAuthorization();
services.AddMemoryCache();
services.AddAutoMapper(typeof(Startup));
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Administration", "/Account");
options.Conventions.AuthorizeAreaFolder("Production", "/Account");
options.Conventions.AddAreaFolderApplicationModelConvention("Production", "/FrontEnd",
model => model.Filters.Add(
new LockdownFilter(
new ProducaoRegistoService(new ProductionContext(new DbContextOptions<ProductionContext>())),
new UrlHelperFactory(),
new HttpContextAccessor())));
})
.AddNToastNotifyToastr(new ToastrOptions()
{
ProgressBar = true,
TimeOut = 3000,
PositionClass = ToastPositions.TopFullWidth,
PreventDuplicates = true,
TapToDismiss = true
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddRouting(options =>
{
options.LowercaseUrls = true;
options.LowercaseQueryStrings = true;
});
services.AddDbContext<DatabaseContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 2,
maxRetryDelay: TimeSpan.FromSeconds(1),
errorNumbersToAdd: null);
sqlOptions.MigrationsHistoryTable("hEFMigrations", "Admin");
});
});
services.AddDbContext<ProductionContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), c => c.MigrationsHistoryTable("hEFMigrations", "Admin")
));
services.AddHttpContextAccessor();
services.AddSingleton<IFileProvider>(new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/files")));
services.AddTransient<IAuthorizationHandler, HasArranqueActivoHandler>();
services.AddTransient<IAuthorizationHandler, HasArranqueInactivoHandler>();
services.AddTransient<IAuthorizationHandler, IsParagemNotOnGoingHandler>();
services.AddTransient<IAuthorizationHandler, IsParagemOnGoingHandler>();
services.AddTransient<Services.Interfaces.IUserService, Services.UserService>();
#region AreaProduction
services.AddTransient<Production.Interfaces.IComponenteService, Production.ComponenteService>();
services.AddTransient<Production.Interfaces.IReferenciaService, Production.ReferenciaService>();
services.AddTransient<Production.Interfaces.IProducaoRegistoService, Production.ProducaoRegistoService>();
services.AddTransient<Production.Interfaces.IParagemService, Production.ParagemService>();
services.AddTransient<Production.Interfaces.ICelulaService, Production.CelulaService>();
services.AddTransient<Production.Interfaces.IUapService, Production.UapService>();
services.AddTransient<Production.Interfaces.ICelulaTipoService, CelulaTipoService>();
services.AddTransient<Production.Interfaces.IMatrizService, MatrizService>();
services.AddTransient<Production.Interfaces.IOperadorService, Production.OperadorService>();
services.AddTransient<Production.Interfaces.IEtiquetaService, Production.EtiquetaService>();
services.AddTransient<Production.Interfaces.IPokayokeService, Production.PokayokeService>();
services.AddTransient<Production.Interfaces.IGeometriaService, Production.GeometriaService>();
services.AddTransient<Production.Interfaces.IEmpregadoService, Production.EmpregadoService>();
services.AddTransient<Production.Interfaces.IPecaService, Production.PecaService>();
services.AddTransient<Production.Interfaces.IDefeitoService, Production.DefeitoService>();
services.AddTransient<Production.Interfaces.ITurnoService, Production.TurnoService>();
#endregion
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
// Use exceptionHandlerPathFeature to process the exception (for example,
// logging), but do NOT expose sensitive error information directly to
// the client.
if (exceptionHandlerPathFeature.Path.Contains("/Administration/") ||
exceptionHandlerPathFeature.Path.Contains("/administration/"))
{
context.Response.Redirect("/Administration/Error");
}
if (exceptionHandlerPathFeature.Path.Contains("/Production/") ||
exceptionHandlerPathFeature.Path.Contains("/production/"))
{
context.Response.Redirect("/Production/Error");
}
});
});
}
app.UseNToastNotify();
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
);
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
my context
public class ProductionContext : DbContext
{
//static LoggerFactory object
public static readonly ILoggerFactory loggerFactory = new LoggerFactory(new[] {
new ConsoleLoggerProvider((_, __) => true, true)
});
public ProductionContext()
{
}
public ProductionContext(DbContextOptions<ProductionContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseLoggerFactory(loggerFactory) //tie-up DbContext with LoggerFactory object
.EnableSensitiveDataLogging();
}
...
}