C# 如何在控制器中访问IApplicationBuilder?
只是想知道,是否可以在startup.cs之外访问IApplicationBuilder属性?比如控制器 我知道它只用于定义应用程序管道,那么解决方案是什么?比如注册一个打包实例的服务,然后注入服务而不是IApplicationBuilder 我正试图从Autofac取回我的DbConext。代码如下: 在C# 如何在控制器中访问IApplicationBuilder?,c#,asp.net-core,dependency-injection,autofac,C#,Asp.net Core,Dependency Injection,Autofac,只是想知道,是否可以在startup.cs之外访问IApplicationBuilder属性?比如控制器 我知道它只用于定义应用程序管道,那么解决方案是什么?比如注册一个打包实例的服务,然后注入服务而不是IApplicationBuilder 我正试图从Autofac取回我的DbConext。代码如下: 在业务项目中: public class AutofacBusinessModule : Autofac.Module { protected override voi
业务
项目中:
public class AutofacBusinessModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacDataModule());
}
}
public class AutofacDataModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AppDbContext>().InstancePerLifetimeScope();
}
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
var builder = new ContainerBuilder();
builder.RegisterModule(new AutofacBusinessModule());
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped(sp => {
var actionContext = sp.GetRequiredService<IActionContextAccessor>().ActionContext;
var urlHelperFactory = sp.GetRequiredService<IUrlHelperFactory>();
var urlHelper = urlHelperFactory.GetUrlHelper(actionContext);
return urlHelper;
});
services.AddDistributedMemoryCache();
builder.Populate(services);
ApplicationContainer = builder.Build();
//return the IServiceProvider implementation
return new AutofacServiceProvider(ApplicationContainer);
}
在数据项目中:
public class AutofacBusinessModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacDataModule());
}
}
public class AutofacDataModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AppDbContext>().InstancePerLifetimeScope();
}
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
var builder = new ContainerBuilder();
builder.RegisterModule(new AutofacBusinessModule());
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped(sp => {
var actionContext = sp.GetRequiredService<IActionContextAccessor>().ActionContext;
var urlHelperFactory = sp.GetRequiredService<IUrlHelperFactory>();
var urlHelper = urlHelperFactory.GetUrlHelper(actionContext);
return urlHelper;
});
services.AddDistributedMemoryCache();
builder.Populate(services);
ApplicationContainer = builder.Build();
//return the IServiceProvider implementation
return new AutofacServiceProvider(ApplicationContainer);
}
以及Web项目中的startup.cs
中的ConfigureServices
:
public class AutofacBusinessModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacDataModule());
}
}
public class AutofacDataModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<AppDbContext>().InstancePerLifetimeScope();
}
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
var builder = new ContainerBuilder();
builder.RegisterModule(new AutofacBusinessModule());
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped(sp => {
var actionContext = sp.GetRequiredService<IActionContextAccessor>().ActionContext;
var urlHelperFactory = sp.GetRequiredService<IUrlHelperFactory>();
var urlHelper = urlHelperFactory.GetUrlHelper(actionContext);
return urlHelper;
});
services.AddDistributedMemoryCache();
builder.Populate(services);
ApplicationContainer = builder.Build();
//return the IServiceProvider implementation
return new AutofacServiceProvider(ApplicationContainer);
}
在GenerateExcelFile
方法中:
public static async Task GenerateExcelFile(IApplicationBuilder app, IEnumerable<string> hashSetCodes, ContestViewModel model)
{
...
try
{
var context = app.ApplicationServices.GetRequiredService<AppDbContext>();
var contest = new Contest
{
Name = model.ProjectName,
UserId = 1,
FileGenerationStatus = true,
FilePath = fileInfo.FullName
};
context.Contests.Add(contest);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
不,据我所知不可能 您必须编写一个中间件(或一些其他代码)来将数据从IAApplicationBuilder获取到HttpContext实例 然后可以从控制器内部访问HttpContext实例
希望这能有所帮助。听起来好像您正在尝试获取一个新的
AppDbContext
实例
如果必须将GenerateExcelFile()
保持为静态
,并希望通过参数重用AppDbContext
,则可以使其接受AppDbContext
的实例,而不是iaapplicationbuilder
首先,只需直接注入这样一个服务实例:
private readonly IHostingEnvironment _hostingEnvironment;
private readonly AppDbContext _dbContext;
// ...
public UniqueCodesController(IHostingEnvironment hostingEnvironment, AppDbContext dbContext)
{
_hostingEnvironment = hostingEnvironment;
_dbContext = dbContext;
}
然后更改GenerateExcelFile()
以接受参数AppDbContext
作为补充说明,如果您无法在编译时确定所需的类型,并且希望动态解析某些服务类型,您可以插入一个
IServiceProvider
,而不是IAApplicationBuilder
。通过这种方式,您可以根据需要解析任何实例:
var dbContext= sp.GetRequiredService<AppDbContext>();
// or if you need a service only available within a scope
using(var scope = this._sp.CreateScope()){
var _anotherDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
...
}
通常,当您在DI中注册了某个内容时,您会将其作为参数添加到构造函数中,因此在这种情况下,您的控制器的构造函数也是如此。通常,您会将依赖项放入控制器的构造函数中,并让DI容器解析它。这样不行吗?您认为在哪里需要IApplicationBuilder?你还没有展示这一点,所以理解这个问题有点困难。如果您尝试过此方法,但没有效果,请提供更多详细信息,例如是否存在异常或其他意外行为?你在这里的一切乍一看都是合理的。@MikeZboray我刚刚更新了原始帖子,展示了我在尝试做什么,以及我在尝试时得到了什么。谢谢你的时间:)哇,这是一个结构良好的答案,非常感谢!正如您所提到的,我曾尝试注入一个
IServiceProvider
,以解析AppDbContext
,但涉及到dbContext.contestics.Add(contest)代码>,我得到这个System.IO.FileNotFoundException:未找到配置文件'appsettings.json',它不是可选的。物理路径是“C:\Program Files\IIS Express\appsettings.json”。
。。。有什么线索吗?@j0w我注意到您假设在IIS中运行时,appsettings.json
驻留在当前目录中。由于某些原因,您当前的目录是'C:\Program Files\IIS Express
。我认为不会有C:\ProgramFiles\IIS Express\appsettings.json
文件。结果,它抛出了。如果没有代码,我不知道为什么当前目录会更改为C:\Program Files\IIS Express
。但是,可以使用Assembly.GetExecutingAssembly().Location
来获取基本位置。只要发现我是在IIS
上启动项目,而不是在web项目上启动的,这就是目录不是好目录的原因。现在,我将启动web项目,稍后我将尝试使用IIS启动,如果可能的话,从那里获取appsettings.json
。非常感谢你的帮助!