.Net Core 2.1 - 无法访问已处置的对象。对象名称:' IServiceProvider'

时间:2018-05-31 08:14:25

标签: c# asp.net .net asp.net-core

我刚刚将.NET Core 2.0迁移到.NET Core 2.1。一切都很顺利,但是当我尝试登录时,我得到了以下错误:

  
      
  • $ exception {System.ObjectDisposedException:无法访问已处置的对象。   对象名称:' IServiceProvider'。
  •   

在这段代码中会发生这种情况:

public class AppContractResolver : DefaultContractResolver
{

    private readonly IServiceProvider _services;

    public AppContractResolver(IServiceProvider services)
    {
        _services = services;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var httpContextAccessor = _services.GetService<IHttpContextAccessor>();
        var user = httpContextAccessor.HttpContext.User;

        List<JsonProperty> properies = base.CreateProperties(type, memberSerialization).ToList();

        properies = FilterOneClaimGranted(type, properies, user);

        return properies;
    }

它发生在这一行:

var httpContextAccessor = _services.GetService<IHttpContextAccessor>();

这适用于.NET Core 2.0

我尝试将HttpContextAccessor添加到我的启动中,但这不起作用。

那么,我该如何解决这个问题?

如果您需要更多代码,请与我们联系。我很乐意提供更多,但我不知道你可能需要什么或不需要什么,所以我没有添加很多代码。&#39;

编辑

我已将services.AddHttpContextAccessor();添加到我的初创公司,但这似乎不起作用。仍然得到错误。

编辑2:

完整的堆栈跟踪:

- $exception    {System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
   at WebAPI.Extensions.AppContractResolver.CreateProperties(Type type, MemberSerialization memberSerialization) in C:\Users\luukw\Desktop\stage\blacky-api\Blacky\Extensions\Resolver\AppContractResolver.cs:line 25
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(Type objectType)
   at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract(Type objectType)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(Type type)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContractSafe(Type type)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Microsoft.AspNetCore.Mvc.Formatters.JsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)}    System.ObjectDisposedException

7 个答案:

答案 0 :(得分:10)

在我的案例中,问题出在Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider services)
{
   var svc = services.GetService<IService>(); // <-- exception here
}

只需将services.GetService<>()替换为app.ApplicationServices.GetService<>()

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   var svc = app.ApplicationServices.GetService<IService>(); // no exception
}

希望有所帮助

答案 1 :(得分:9)

我建议不要打电话  services.GetService< IHttpContextAccessor>(),将IHttpContextAccessor注入构造函数并使用aprivate字段存储值。

public AppContractResolver(IServiceProvider services, 
                             IHttpContextAccessor  httpContextAccessor )
{
   _services = services;
   this.httpContextAccessor =httpContextAccessor ;
}

还必须手动注册HttpContextAccessor。 在Startup.cs中的RegisterServices中添加services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

答案 2 :(得分:2)

我收到了这个错误,花了很长时间才解决,所以我要把它贴在这里。

这是引发错误的代码:

using var context = this.DbFactory.CreateDbContext();                
SqlParameter[] parameter =
{
    new SqlParameter("@ord_cust_id", ordCustId)
};
products = await context.GetProduct.FromSqlRaw<ProductEntity>($"{spName}  @ord_cust_id", parameter).AsNoTracking().ToListAsync();

抛出的异常在最后一行。由于上下文是由 DbFactory 创建的,因此没有任何意义,因此无法处理它。

找了好久,发现DbFactory的作用域是“Transient”,改成Singleton,异常解决。

这是启动时的代码:

 services.AddDbContextFactory<CDSEntities>(options =>
 {                
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
 }, ServiceLifetime.Singleton); //changed to Singlton instead of Transient

答案 3 :(得分:1)

对我来说,它适用于:

 public void ConfigureServices(IServiceCollection services)
{
  …
  services.AddHttpContextAccessor();
  …
}

然后:

     public void Configure(IApplicationBuilder app, IHttpContextAccessor accessor)
    {
    ...
    ...accessor.HttpContext.RequestService

     ...

    }

答案 4 :(得分:0)

我认为IServiceProvider实现可能在某个地方无意中被用于using语句或被彻底处置。

要测试是否是这种情况,您可以尝试在IHttpContextAccessor方法之后或之内尝试解析ConfigureServices

如果它在那里解决,你需要逐步找出IServiceProvider被处置的位置。

答案 5 :(得分:0)

如果创建任何临时服务,例如services.AddTransient ...,则.net核心将处置服务提供者。从.net core 2.2开始,这是一个错误。

答案 6 :(得分:0)

尝试在 Startup ➢ ConfigureServices 方法中获取服务时遇到了类似的异常:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<INotification>(provider =>
    {
        var hubContext = (IHubContext<NotificationHub>)provider
                  .GetService(typeof(IHubContext<NotificationHub>));

        // ↓↓↓ Exception: cannot access a disposed object. Object name: 'IServiceProvider'.
        var mediator = (IMediator)provider.GetService(typeof(IMediator)); 

        hubContext.SetListener(() =>  
            mediator.Send(new ...);
            ...
        });
    }
    ...
}
  

仅供参考:NotificationHub 是我实现自定义 INotificaiton 服务的自定义通知类。


通过创建本地范围服务解决了问题:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<INotification>(provider =>
    {
        var hubContext = (IHubContext<NotificationHub>)provider
                  .GetService(typeof(IHubContext<NotificationHub>));

          var myScope = provider.CreateScope(); // <<< creating a scoped sertvice
          var mediator = (IMediator)myScope.ServiceProvider.GetService(typeof(IMediator));

          hubContext.SetListener(() =>  
             mediator.Send(new ...);
             ...
        });
    }
    ...
}