Cuando intento ejecutar mi aplicación, aparece el error
InvalidOperationException: Cannot resolve 'API.Domain.Data.Repositories.IEmailRepository' from root provider because it requires scoped service 'API.Domain.Data.EmailRouterContext'.
Lo que es extraño es que este EmailRepository y la interfaz están configurados exactamente de la misma manera que todos mis otros repositorios, pero no se arroja ningún error para ellos. El error solo ocurre si trato de usar la aplicación.UseEmailingExceptionHandling (); línea. Aquí hay algunos de mis archivos Startup.cs.
public class Startup
{
public IConfiguration Configuration { get; protected set; }
private APIEnvironment _environment { get; set; }
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
Configuration = configuration;
_environment = APIEnvironment.Development;
if (env.IsProduction()) _environment = APIEnvironment.Production;
if (env.IsStaging()) _environment = APIEnvironment.Staging;
}
public void ConfigureServices(IServiceCollection services)
{
var dataConnect = new DataConnect(_environment);
services.AddDbContext<GeneralInfoContext>(opt => opt.UseSqlServer(dataConnect.GetConnectString(Database.GeneralInfo)));
services.AddDbContext<EmailRouterContext>(opt => opt.UseSqlServer(dataConnect.GetConnectString(Database.EmailRouter)));
services.AddWebEncoders();
services.AddMvc();
services.AddScoped<IGenInfoNoteRepository, GenInfoNoteRepository>();
services.AddScoped<IEventLogRepository, EventLogRepository>();
services.AddScoped<IStateRepository, StateRepository>();
services.AddScoped<IEmailRepository, EmailRepository>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
app.UseAuthentication();
app.UseStatusCodePages();
app.UseEmailingExceptionHandling();
app.UseMvcWithDefaultRoute();
}
}
Aquí está el repositorio de correo electrónico
public interface IEmailRepository
{
void SendEmail(Email email);
}
public class EmailRepository : IEmailRepository, IDisposable
{
private bool disposed;
private readonly EmailRouterContext edc;
public EmailRepository(EmailRouterContext emailRouterContext)
{
edc = emailRouterContext;
}
public void SendEmail(Email email)
{
edc.EmailMessages.Add(new EmailMessages
{
DateAdded = DateTime.Now,
FromAddress = email.FromAddress,
MailFormat = email.Format,
MessageBody = email.Body,
SubjectLine = email.Subject,
ToAddress = email.ToAddress
});
edc.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
edc.Dispose();
disposed = true;
}
}
}
Y finalmente el middleware de manejo de excepciones
public class ExceptionHandlingMiddleware
{
private const string ErrorEmailAddress = "errors@ourdomain.com";
private readonly IEmailRepository _emailRepository;
private readonly RequestDelegate _next;
public ExceptionHandlingMiddleware(RequestDelegate next, IEmailRepository emailRepository)
{
_next = next;
_emailRepository = emailRepository;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex, _emailRepository);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception,
IEmailRepository emailRepository)
{
var code = HttpStatusCode.InternalServerError; // 500 if unexpected
var email = new Email
{
Body = exception.Message,
FromAddress = ErrorEmailAddress,
Subject = "API Error",
ToAddress = ErrorEmailAddress
};
emailRepository.SendEmail(email);
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int) code;
return context.Response.WriteAsync("An error occured.");
}
}
public static class AppErrorHandlingExtensions
{
public static IApplicationBuilder UseEmailingExceptionHandling(this IApplicationBuilder app)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
return app.UseMiddleware<ExceptionHandlingMiddleware>();
}
}
Actualización: encontré este enlace https://github.com/aspnet/DependencyInjection/issues/578 que me llevó a cambiar el método BuildWebHost de mi archivo Program.cs de este
public static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
a esto
public static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseDefaultServiceProvider(options =>
options.ValidateScopes = false)
.Build();
}
No sé qué está pasando exactamente, pero parece funcionar ahora.