services net mvc inyeccion injection español dependency dependencias configureservices asp addmvc entity-framework-6 asp.net-web-api2 asp.net-core

entity framework 6 - mvc - Llamando a los métodos de servicio/repositorio en el middleware ASP.Net Core



middleware c# (1)

Nodo de ASP.Net Core aquí ... Estoy usando un proyecto principal de ASP.Net Core WebAPI usando DNX451 con EF 6.

Tengo un requisito para implementar API Key auth en nuestro servicio. Para hacer esto, he creado un middleware que obtiene información de la solicitud y continúa con la autenticación. Se SUPONE ir a la base de datos, obtener la clave para que coincida, y luego regresar y hacer la validación.

Aquí está el middleware implementado para mirar el contexto y obtener la APIKey

AuthenticationHandler

public class AuthorizationHandler { private readonly RequestDelegate _next; private IAuthenticationService _authenticationService; public AuthorizationHandler(RequestDelegate next, IAuthenticationService authService) { _authenticationService = authService; _next = next; } public async Task Invoke(HttpContext context) { try { var apiKey = context.Request.Headers["Key"]; var location = context.Request.Headers["Host"]; var locationKey = _authenticationService.GetApiKey(location); if (apiKey == locationKey) await _next(context); context.Response.StatusCode = 403; context.Response.Headers.Add("WWW-Authenticate", new[] { "Basic" }); } catch (Exception ex) { context.Response.StatusCode = 500; context.Response.Headers.Add("WWW-Authenticate", new[] { "Basic" }); } } }

Aquí está la clase de inicio con registro de contexto y middleware

public class Startup { public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); builder.AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfiguration Configuration { get; set; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddScoped(k => new DbContext(Configuration["Data:Context:ConnectionString"])); // Add framework services. services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseIISPlatformHandler(); app.UseStaticFiles(); app.RegisterAuthorizationHeader(); app.RegisterAuthorization(); app.UseMvc(); } // Entry point for the application. public static void Main(string[] args) => WebApplication.Run<Startup>(args); }

Aquí está el servicio de autenticación

public interface IAuthenticationService { string GetApiKey(string location); } public class AuthenticationService: IAuthenticationService { private IApiKeyRepository _apiKeyRepository; public AuthenticationService(IApiKeyRepository repo) { _apiKeyRepository= repo; } public string GetApiKey(string location) { return _apiKeyRepository.GetApiKeyByLocation(location); } }

El repo

public interface IApiRepository { string GetApiKeyByLocation(string location); } public class ApiRepository: IApiRepository { private DbContext _context; public ApiRepository(DbContext context) { _context = context; } public string GetApiKeyByLocation(string location) { var apiRow = _context.ApiKeyStore.FirstOrDefault(a => a.Location == location); return apiRow == null ? string.Empty : apiRow.APIKey; } }

Al intentar esto me sale el siguiente error:

El contexto no se puede usar mientras se está creando el modelo. Se puede lanzar esta excepción si el contexto se usa dentro del método OnModelCreating o si varios subprocesos acceden simultáneamente a la misma instancia de contexto. Tenga en cuenta que no se garantiza que los miembros de instancia de DbContext y las clases relacionadas sean seguros para la ejecución de subprocesos.

Ahora, cuando depuro esto, cada punto de quiebre es golpeado dos veces. Creo que entiendo POR QUÉ está ocurriendo este problema, pero no tengo idea de cómo solucionarlo.

¿Alguien puede darme una idea, por favor? ¿Alguna mejor solución de ideas?


Para usar dependencias con ámbito en un middleware (que es necesariamente un singleton por definición), el mejor enfoque es hacer que fluya como un parámetro de InvokeAsync lugar de hacerlo fluir a través del constructor:

public async Task Invoke(HttpContext context, IAuthenticationService authenticationService) { try { var apiKey = context.Request.Headers["Key"]; var location = context.Request.Headers["Host"]; var locationKey = authenticationService.GetApiKey(location); if (apiKey == locationKey) await _next(context); context.Response.StatusCode = 403; context.Response.Headers.Add("WWW-Authenticate", new[] { "Basic" }); } catch (Exception ex) { context.Response.StatusCode = 500; context.Response.Headers.Add("WWW-Authenticate", new[] { "Basic" }); } }