【问题标题】:.Net Core 2.1 - Cannot access a disposed object.Object name: 'IServiceProvider'.Net Core 2.1 - 无法访问已处置的对象。对象名称:'IServiceProvider'
【发布时间】:2018-05-31 08:14:25
【问题描述】:

我刚刚将 .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 添加到我的启动中,但没有成功。

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

如果您需要更多代码,请告诉我。我很乐意提供更多,但我不知道您可能需要或不需要什么,因此我没有添加很多代码。'

编辑

我已将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

【问题讨论】:

  • 只是想查一下,你是不是用.net core 2.1的方式注册了services.AddHttpContextAccessor();
  • 我已经尝试添加它,但没有奏效。仍然有同样的错误
  • 而不是调用 AddHttpContextAccessor 尝试手动注册它,在我的情况下有所帮助: services.AddSingleton()
  • @Vitaly 不,不起作用:(
  • 你应该尽量避免将IServiceProvider 传递给你的类,而是传递你需要使用的实际东西。它解决了一些边缘情况(比如你的情况),并且可以更容易地查看你的类实际使用的依赖项。

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


【解决方案1】:

在我的情况下,问题出现在Startup.cs

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

只需将services.GetService&lt;&gt;() 替换为app.ApplicationServices.GetService&lt;&gt;()

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

希望对你有帮助

【讨论】:

  • 谢谢,我有一个 ServiceLocator,我可以进行此更改:private static IServiceProvider _provider; public static void Init(IServiceProvider provider) { _provider = provider; } public static T Resolve&lt;T&gt;() =&gt; (T)_provider.GetService(typeof(T)); "To:" private static IApplicationBuilder _app; public static void Init(IApplicationBuilder app) { _app = app; } public static T Resolve&lt;T&gt;() =&gt; (T)_app.ApplicationServices.GetService(typeof(T));
  • 天啊:app.ApplicationServices 是最令人惊奇的发现!感谢您的建议为我节省了更多时间继续研究、反复试验。
  • :'(我花了很多时间,但我提高了耐心:D 谢谢!
【解决方案2】:

我建议不要打电话 services.GetService&lt;IHttpContextAccessor&gt;(),将IHttpContextAccessor注入构造函数,并使用私有字段存储值。

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

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

【讨论】:

  • IServiceProvider 已被框架注册。这是容器本身
  • @MatanShahar 仅供参考,答案已更新,现在包含正确信息。
【解决方案3】:

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

【讨论】:

  • 任何 Github 链接到这个问题?
  • Bug 似乎在 .net core 3 中消失了
【解决方案4】:

我遇到了这个错误,并且花了很长时间才解决,所以我将在此处发布。

这是引发错误的代码:

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

【讨论】:

    【解决方案5】:

    对我来说,它适用于:

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

    然后:

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

    【讨论】:

      【解决方案6】:

      我在尝试在 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 ...);
                   ...
              });
          }
          ...
      }  
      

      【讨论】:

        【解决方案7】:

        就我而言,调用者方法中缺少“await”运算符。

            public async Task<OrderResponse> CreateOrder(){
            //Do something
            var response = **await** CreateOrderItem();
            return response;
        }
        
        public async Task<ItemResponse> CreateOrderItem(){
            //Do something
        }
        

        CreateOrder() 中缺少“await”

        【讨论】:

        • 这对我很有用,我在控制器方法中也发生了同样的事情。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-08-19
        • 1970-01-01
        • 1970-01-01
        • 2018-07-16
        • 2022-01-11
        • 2020-04-23
        相关资源
        最近更新 更多