在 ASP.NET Core 3.1 中的 Startup.cs 中注入服务
Inject a service in Startup.cs in ASP.NET Core 3.1
我正在开发 .NET Core 3.1 应用程序。我有一个要求,我必须在 Startup.cs 中注入服务。我的代码是:
Program.cs:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(servicesCollection =>
{
servicesCollection.AddScoped<IUnauthorizedAccessService, UnauthorizedAccessService>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs:
public Startup(IConfiguration configuration, IUnauthorizedAccessService unauthorizedAccessService)
{
Configuration = configuration;
_unauthorizedAccessService = unauthorizedAccessService;
}
public IConfiguration Configuration { get; }
public IUnauthorizedAccessService _unauthorizedAccessService { get; set; }
当我 运行 代码时,我得到以下异常:
Unable to resolve service for type 'Interface.Service.IUnauthorizedAccessService' while attempting to activate 'Website.Startup'.'
如何在 Startup.cs 中注入服务?我什至试过它进入 Configure
方法。但是后来,我在存储库级别得到了异常。代码:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IUnauthorizedAccessService unauthorizedAccessService)
{
_unauthorizedAccessService = unauthorizedAccessService;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Strict,
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=User}/{action=Index}/{id?}");
});
}
我有一个方法 RegisterDatabase
正在从 ConfigureServices
调用。代码:
private void RegisterDatabase(IServiceCollection services)
{
services.AddDbContext<TrainingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
服务代码是:
public class UnauthorizedAccessService : IUnauthorizedAccessService
{
private readonly IEventLogRepository _eventLogRepository;
public UnauthorizedAccessService(IEventLogRepository eventLogRepository)
{
_eventLogRepository = eventLogRepository;
}
public async Task<BaseResponse> LogUnauthorizedAccessInDB(string user, string url, string sessionId)
{
try
{
EventLog eventLog = new EventLog();
eventLog.Httpsession = sessionId;
eventLog.AppUserName = user;
eventLog.EventDateTime = DateTime.Now;
eventLog.MessageLevel = 3;
eventLog.Message = url;
await _eventLogRepository.Add(eventLog);
}
catch(Exception ex)
{
}
return HelperService.Response(null, null);
}
}
添加对象时出现异常
Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'TrainingContext'.
我的所有其他存储库都在工作,但仅在此时出现异常。可能的问题是什么?任何帮助将不胜感激。
基本上,我想要实现的是我想在数据库中记录对我网站的未经授权的访问。代码是:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o =>
{
o.AccessDeniedPath = "/Home/Error";
o.LoginPath = "/Login";
o.SlidingExpiration = false;
o.Events = new CookieAuthenticationEvents
{
//OnRedirectToAccessDenied = new Func<RedirectContext<CookieAuthenticationOptions>, Task>(context =>
OnRedirectToAccessDenied = new Func<RedirectContext<CookieAuthenticationOptions>, Task>(test)
};
});
测试方法是:
private async Task<Task> test (RedirectContext<CookieAuthenticationOptions> context)
{
string user = context.HttpContext.User.Identity.Name;
string url = "/" + context.Request.Host.Value + "/" + context.Request.RouteValues["controller"] + "/" + context.Request.RouteValues["action"];
string sessionId = context.HttpContext.Session.Id;
await _unauthorizedAccessService.LogUnauthorizedAccessInDB(user, url, sessionId);
context.Response.Redirect("/Home/Error");
return context.Response.CompleteAsync();
}
Startup.cs
专为配置自己的服务和管道配置而设计。您不能在构造函数中注入您的自定义服务,因为它们尚未配置。
Docs:
The host provides services that are available to the Startup class
constructor. The app adds additional services via ConfigureServices.
Both the host and app services are available in Configure and
throughout the app.
您需要创建一个实现 CookieAuthenticationEvents
的作用域对象。例如:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Threading.Tasks;
namespace MyApplication.Services
{
public class MyCookieAuthenticationEvents : CookieAuthenticationEvents
{
private readonly IUnauthorizedAccessService _unauthorizedAccessService;
public MyCookieAuthenticationEvents(
IUnauthorizedAccessService unauthorizedAccessService)
{
_unauthorizedAccessService = unauthorizedAccessService;
}
public override Task RedirectToAccessDenied(
RedirectContext<CookieAuthenticationOptions> context)
{
// TODO: you can use _unauthorizedAccessService here
return base.RedirectToAccessDenied(context);
}
}
}
要注入这个,你可以这样做:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.EventsType = typeof(MyCookieAuthenticationEvents);
});
services.AddScoped<MyCookieAuthenticationEvents>();
services.AddScoped<IUnauthorizedAccessService, UnauthorizedAccessService>();
确保从 program.cs
中删除 IUnauthorizedAccessService
。你不在那里注射。您在 Configure
方法中注入。
这就是正确进行依赖注入的方式。您不做已接受的答案正在做的事情。这可能是我很长一段时间以来见过的最非正统的事情之一。
我正在开发 .NET Core 3.1 应用程序。我有一个要求,我必须在 Startup.cs 中注入服务。我的代码是:
Program.cs:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(servicesCollection =>
{
servicesCollection.AddScoped<IUnauthorizedAccessService, UnauthorizedAccessService>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs:
public Startup(IConfiguration configuration, IUnauthorizedAccessService unauthorizedAccessService)
{
Configuration = configuration;
_unauthorizedAccessService = unauthorizedAccessService;
}
public IConfiguration Configuration { get; }
public IUnauthorizedAccessService _unauthorizedAccessService { get; set; }
当我 运行 代码时,我得到以下异常:
Unable to resolve service for type 'Interface.Service.IUnauthorizedAccessService' while attempting to activate 'Website.Startup'.'
如何在 Startup.cs 中注入服务?我什至试过它进入 Configure
方法。但是后来,我在存储库级别得到了异常。代码:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IUnauthorizedAccessService unauthorizedAccessService)
{
_unauthorizedAccessService = unauthorizedAccessService;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Strict,
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=User}/{action=Index}/{id?}");
});
}
我有一个方法 RegisterDatabase
正在从 ConfigureServices
调用。代码:
private void RegisterDatabase(IServiceCollection services)
{
services.AddDbContext<TrainingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
服务代码是:
public class UnauthorizedAccessService : IUnauthorizedAccessService
{
private readonly IEventLogRepository _eventLogRepository;
public UnauthorizedAccessService(IEventLogRepository eventLogRepository)
{
_eventLogRepository = eventLogRepository;
}
public async Task<BaseResponse> LogUnauthorizedAccessInDB(string user, string url, string sessionId)
{
try
{
EventLog eventLog = new EventLog();
eventLog.Httpsession = sessionId;
eventLog.AppUserName = user;
eventLog.EventDateTime = DateTime.Now;
eventLog.MessageLevel = 3;
eventLog.Message = url;
await _eventLogRepository.Add(eventLog);
}
catch(Exception ex)
{
}
return HelperService.Response(null, null);
}
}
添加对象时出现异常
Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'TrainingContext'.
我的所有其他存储库都在工作,但仅在此时出现异常。可能的问题是什么?任何帮助将不胜感激。
基本上,我想要实现的是我想在数据库中记录对我网站的未经授权的访问。代码是:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o =>
{
o.AccessDeniedPath = "/Home/Error";
o.LoginPath = "/Login";
o.SlidingExpiration = false;
o.Events = new CookieAuthenticationEvents
{
//OnRedirectToAccessDenied = new Func<RedirectContext<CookieAuthenticationOptions>, Task>(context =>
OnRedirectToAccessDenied = new Func<RedirectContext<CookieAuthenticationOptions>, Task>(test)
};
});
测试方法是:
private async Task<Task> test (RedirectContext<CookieAuthenticationOptions> context)
{
string user = context.HttpContext.User.Identity.Name;
string url = "/" + context.Request.Host.Value + "/" + context.Request.RouteValues["controller"] + "/" + context.Request.RouteValues["action"];
string sessionId = context.HttpContext.Session.Id;
await _unauthorizedAccessService.LogUnauthorizedAccessInDB(user, url, sessionId);
context.Response.Redirect("/Home/Error");
return context.Response.CompleteAsync();
}
Startup.cs
专为配置自己的服务和管道配置而设计。您不能在构造函数中注入您的自定义服务,因为它们尚未配置。
Docs:
The host provides services that are available to the Startup class constructor. The app adds additional services via ConfigureServices. Both the host and app services are available in Configure and throughout the app.
您需要创建一个实现 CookieAuthenticationEvents
的作用域对象。例如:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Threading.Tasks;
namespace MyApplication.Services
{
public class MyCookieAuthenticationEvents : CookieAuthenticationEvents
{
private readonly IUnauthorizedAccessService _unauthorizedAccessService;
public MyCookieAuthenticationEvents(
IUnauthorizedAccessService unauthorizedAccessService)
{
_unauthorizedAccessService = unauthorizedAccessService;
}
public override Task RedirectToAccessDenied(
RedirectContext<CookieAuthenticationOptions> context)
{
// TODO: you can use _unauthorizedAccessService here
return base.RedirectToAccessDenied(context);
}
}
}
要注入这个,你可以这样做:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.EventsType = typeof(MyCookieAuthenticationEvents);
});
services.AddScoped<MyCookieAuthenticationEvents>();
services.AddScoped<IUnauthorizedAccessService, UnauthorizedAccessService>();
确保从 program.cs
中删除 IUnauthorizedAccessService
。你不在那里注射。您在 Configure
方法中注入。
这就是正确进行依赖注入的方式。您不做已接受的答案正在做的事情。这可能是我很长一段时间以来见过的最非正统的事情之一。