Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET Core 2中的依赖项注入引发异常_C#_Asp.net Core_Dependency Injection_.net Core_Asp.net Core 2.0 - Fatal编程技术网

C# ASP.NET Core 2中的依赖项注入引发异常

C# ASP.NET Core 2中的依赖项注入引发异常,c#,asp.net-core,dependency-injection,.net-core,asp.net-core-2.0,C#,Asp.net Core,Dependency Injection,.net Core,Asp.net Core 2.0,当我尝试在Startup.cs文件的Configure方法中使用自定义DbContext时,我收到以下异常。我在版本2.0.0-preview1-005977中使用ASP.NET核心 未处理的异常:系统。异常:无法为“Communicator.Backend.Data.CommunicatorContext”类型的“Communicator.Backend.Data.CommunicatorContext”解析类型为“Communicator.Backend.Startup”的方法“Config

当我尝试在
Startup.cs
文件的
Configure
方法中使用自定义DbContext时,我收到以下异常。我在版本2.0.0-preview1-005977中使用ASP.NET核心

未处理的异常:系统。异常:无法为“Communicator.Backend.Data.CommunicatorContext”类型的“Communicator.Backend.Data.CommunicatorContext”解析类型为“Communicator.Backend.Startup”的方法“Configure”的参数“dbContext”的服务。-->System.InvalidOperationException:无法从根提供程序解析作用域服务“Communicator.Backend.Data.CommunicatorContext”

当我尝试接收其他实例时,也会抛出此异常

未处理的异常:系统。异常:无法解析“Communicator.Backend.Services.ILdapService”类型的服务。

以下是我的
ConfigureServices
Configure
方法

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddCookieAuthentication();
    services.Configure<LdapConfig>(Configuration.GetSection("Ldap"));
    services.AddScoped<ILdapService, LdapService>();
    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CommunicatorContext dbContext, ILdapService ldapService)
{
    app.UseAuthentication();
    app.UseWebSockets();
    app.Use(async (context, next) =>
    {
        if (context.Request.Path == "/ws")
        {
            if (context.WebSockets.IsWebSocketRequest)
            {
                WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                await Echo(context, webSocket);
            }
            else
            {
                context.Response.StatusCode = 400;
            }
        }
        else
        {
            await next();
        }
    });
    app.UseMvc();
    DbInitializer.Initialize(dbContext, ldapService);
}
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(options=>options.UseSqlServer(Configuration.GetConnectionString(“DefaultConnection”));
services.AddCookieAuthentication();
services.Configure(Configuration.GetSection(“Ldap”));
services.addScope();
services.AddMvc();
}
public void Configure(IApplicationBuilder应用程序、IHostingEnvironment环境、ILoggerFactory loggerFactory、CommunicationorContext dbContext、ILdapService ldapService)
{
app.UseAuthentication();
app.UseWebSockets();
应用程序使用(异步(上下文,下一步)=>
{
if(context.Request.Path==“/ws”)
{
if(context.WebSockets.IsWebSocketRequest)
{
WebSocket WebSocket=等待上下文.WebSocket.AcceptWebSocketAsync();
等待回声(上下文、webSocket);
}
其他的
{
context.Response.StatusCode=400;
}
}
其他的
{
等待下一个();
}
});
app.UseMvc();
初始化(dbContext,ldapService);
}
引用文档

ASP.NET核心依赖项注入在 应用程序的启动。您可以通过以下方式请求这些服务: 在
启动
类的 构造函数或其
配置
配置服务
方法之一

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddCookieAuthentication();
    services.Configure<LdapConfig>(Configuration.GetSection("Ldap"));
    services.AddScoped<ILdapService, LdapService>();
    services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CommunicatorContext dbContext, ILdapService ldapService)
{
    app.UseAuthentication();
    app.UseWebSockets();
    app.Use(async (context, next) =>
    {
        if (context.Request.Path == "/ws")
        {
            if (context.WebSockets.IsWebSocketRequest)
            {
                WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
                await Echo(context, webSocket);
            }
            else
            {
                context.Response.StatusCode = 400;
            }
        }
        else
        {
            await next();
        }
    });
    app.UseMvc();
    DbInitializer.Initialize(dbContext, ldapService);
}
按照以下顺序查看
启动
类中的每个方法 他们被称为,可能需要以下服务: 参数:

  • 在构造函数中:
    IHostingEnvironment
    ILoggerFactory
  • ConfigureServices
    方法中:
    IServiceCollection
  • Configure
    方法中:
    iaapplicationbuilder
    IHostingEnvironment
    iLogger工厂
    IApplicationLifetime
您正在尝试解析启动期间不可用的服务

...CommunicatorContext dbContext, ILdapService ldapService) {
这会给你带来错误。如果需要访问实现,则需要执行以下操作之一:

  • 修改
    ConfigureServices
    方法,并从服务集合访问它们。i、 e

    public IServiceProvider ConfigureServices(IServiceCollection services) {
        services.AddDbContext<CommunicatorContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        services.AddCookieAuthentication();
        services.Configure<LdapConfig>(Configuration.GetSection("Ldap"));
        services.AddScoped<ILdapService, LdapService>();
        services.AddMvc();
    
        // Build the intermediate service provider
        var serviceProvider = services.BuildServiceProvider();
    
        //resolve implementations
        var dbContext = serviceProvider.GetService<CommunicatorContext>();
        var ldapService = serviceProvider.GetService<ILdapService>();
        DbInitializer.Initialize(dbContext, ldapService);
    
        //return the provider
        return serviceProvider();
    }
    

  • 来自NKosi的解决方案之所以有效,是因为在没有参数的情况下调用
    services.BuildServiceProvider()
    您自己不会传递
    validateScopes
    。由于此验证已禁用,因此不会引发异常。这并不意味着问题不存在

    EF Core
    DbContext
    已注册到范围限定的生活方式。在ASP原生DI中,容器作用域连接到
    IServiceProvider
    的实例。通常,当您从控制器使用
    DbContext
    时,没有问题,因为ASP为每个请求创建一个新的作用域(IServiceProvider的新实例),然后使用它来解决此请求中的所有问题。但是,在应用程序启动期间,您没有请求范围。您有一个
    IServiceProvider
    的实例,它没有作用域(或者换句话说,在根作用域中)。这意味着您应该自己创建一个范围。您可以这样做:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
        using (var scope = scopeFactory.CreateScope())
        {
            var db = scope.ServiceProvider.GetRequiredService<CommunicatorContext>();
            var ldapService = scope.ServiceProvider.GetRequiredService<ILdapService>();
            // rest of your code
        }
        // rest of Configure setup
    }
    
    public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
    {
    var scopeFactory=app.ApplicationServices.GetRequiredService();
    使用(var scope=scopeFactory.CreateScope())
    {
    var db=scope.ServiceProvider.GetRequiredService();
    var ldapService=scope.ServiceProvider.GetRequiredService();
    //代码的其余部分
    }
    //配置设置的其余部分
    }
    
    ConfigureServices
    方法可以保持不变

    编辑

    您的解决方案将在2.0.0 RTM中工作,无需任何更改,因为将为Configure方法创建RTM范围内的服务提供程序

    在Program.cs的
    .UseStartup()


    为我工作


    或者,您可以在
    配置方法中创建服务范围:

    var scopeFactory = ApplicationServices.GetService<IServiceScopeFactory>();
    using (var scope = scopeFactory.CreateScope())
    {
        var dbContext = scope.ServiceProvider.GetService<CommunicatorDbContext>();
        DbInitializer.Initializer(dbContext, ldapService);
    }
    
    var scopeFactory=ApplicationServices.GetService();
    使用(var scope=scopeFactory.CreateScope())
    {
    var dbContext=scope.ServiceProvider.GetService();
    初始化器(dbContext,ldapService);
    }
    

    虽然,正如在Slack中提到的,不要这样做;-)

    在ASP.NET Core 2.0及更新版本中,您只需将所需的作用域服务注入
    配置
    构造函数,就像您最初尝试的那样:

    public void Configure(
        IApplicationBuilder app,
        IHostingEnvironment env,
        ILoggerFactory loggerFactory,
        CommunicatorContext dbContext,
        ILdapService ldapService)
    {
      // ...
    }
    

    由于中的改进,这要容易得多。

    谢谢,这解决了我的问题。如果我可以添加更多,在测试了这两个选项之后,我发现我仍然需要修改
    ConfigureServices
    ,从返回
    void
    (默认情况下)到返回
    IServiceProvider
    ,以便第二个选项工作。有类似的问题。制作
    ConfigureServices()
    返回
    public void Configure(
        IApplicationBuilder app,
        IHostingEnvironment env,
        ILoggerFactory loggerFactory,
        CommunicatorContext dbContext,
        ILdapService ldapService)
    {
      // ...
    }