如何在控制器中访问IApplicationBuilder?

时间:2019-04-01 19:20:51

标签: c# asp.net-core dependency-injection autofac

想知道,是否可以在startup.cs之外访问IApplicationBuilder属性?像在控制器中一样?

我知道它仅用于定义应用程序管道,那么解决方案是什么?诸如注册打包实例的服务,然后注入服务而不是IApplicationBuilder的东西?

我正试图从Autofac找回我的DbConext。代码如下:

Business项目中:

 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();
        }
    }

DbContext

public class AppDbContext : DbContext
    {
        private const string DbContextName = "AppDbConnectionString";
        public DbSet<Contest> Contests { get; set; }

        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {
        }

        public AppDbContext()
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (optionsBuilder.IsConfigured) return;

            var configuration = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .Build();
            var connectionString = configuration.GetConnectionString(DbContextName);
            optionsBuilder.UseSqlServer(connectionString,
                x => x.MigrationsAssembly("Cri.CodeGenerator.Data"));
        }

        public virtual void Commit()
        {
            base.SaveChanges();
        }
    }

以及Web项目中ConfigureServices中的startup.cs

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);

}

我肯定会丢失一些东西,但是当涉及到DI和.net核心时真的是新手...

-编辑-

在我的Controller

  private readonly IHostingEnvironment _hostingEnvironment;
        private readonly IApplicationBuilder _app;


        private const int NumberOfCharactersRepetion = 4;

        public UniqueCodesController(IHostingEnvironment hostingEnvironment, IApplicationBuilder app)
        {
            _hostingEnvironment = hostingEnvironment;
            _app = app;
        }

...

if (selectedAnswer == FileExtension.XLSX.GetStringValue())
                {
                    await FilesGenerationUtils.GenerateExcelFile(_app, uniqueCodesHashSet, model);
                }

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);
                    }

}

但是当我运行该应用程序时,我收到此消息:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Builder.IApplicationBuilder' while attempting to activate 'Cri.CodeGenerator.Web.Controllers.UniqueCodesController'.

2 个答案:

答案 0 :(得分:1)

不,据我所知,这是不可能的。

您将必须编写中间件(或一些其他代码)才能将数据从IApplicationBuilder传递到HttpContext实例。

然后可以从控制器内部访问HttpContext实例。

希望这会有所帮助。

答案 1 :(得分:1)

听起来像您正在尝试获取AppDbContext的新实例。

如果您必须将GenerateExcelFile()保留为static,并想通过参数重用AppDbContext,则可以使其接受AppDbContext的实例而不是{ {1}}。

首先,只需直接注入这样的服务实例:

IApplicationBuilder

然后更改 private readonly IHostingEnvironment _hostingEnvironment; private readonly AppDbContext _dbContext; // ... public UniqueCodesController(IHostingEnvironment hostingEnvironment, AppDbContext dbContext) { _hostingEnvironment = hostingEnvironment; _dbContext = dbContext; } 以接受参数GenerateExcelFile()

    public static async Task GenerateExcelFile(IApplicationBuilder app, IEnumerable<string>hashSetCodes, ContestViewModel model)
    public static async Task GenerateExcelFile(AppDbContext dbContext, IEnumerable hashSetCodes, ContestViewModel model)
    {
        ...

        try{
            var context = app.ApplicationServices.GetRequiredService();
            var contest = new Contest
            {
                Name = model.ProjectName,
                UserId = 1,
                FileGenerationStatus = true,
                FilePath = fileInfo.FullName
            };
            context.Contests.Add(contest);
            context.Contests.Add(contest);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

    }

最后,您可以按以下方式调用它:

AppDbContext

请注意,如果在编译时无法确定所需的类型,并且想动态解析某些服务类型,则您可以注入 await FilesGenerationUtils.GenerateExcelFile(_dbContext, uniqueCodesHashSet, model); 而不是{{1} } 。这样,您可以根据需要解析任何实例:

IServiceProvider

以您的代码为例,您可以将IApplicationBuilder传递给 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>(); ... } ,在IServiceProvider方法中,可以通过以下方式解析GenerateExcelFile(IServiceProvider sp, IEnumerable<string> hashSetCodes, ContestViewModel model)

GenerateExcelFile()