【问题标题】:InvalidOperationException: Unable to resolve service for typeInvalidOperationException:无法解析类型的服务
【发布时间】:2016-12-17 07:47:10
【问题描述】:

我正在为多租户应用程序使用 saaskit 多租户项目。

我能够创建租户上下文并能够访问所有控制器。

但是,有时它会给我以下错误

发生未处理的异常:无法解析服务 尝试激活时键入“LMS.Model.AppTenant” 'LMS.Controllers.OrganizationController'。

对于任何控制器和执行的任何操作方法,此错误都是随机发生的。错误的性质并不特定于任何控制器/操作方法。

我可以看到我的代码成功进入了 TenantResolver,它实际上返回了一个租户,但是当 DI 将其注入我的控制器时,它会抱怨列出的错误

发生此错误后,我的应用程序完全停止并显示白屏。

此问题发生在生产服务器上,而不是本地主机上。

对此有任何帮助!

租户像这样注入到所有控制器中

public class HomeController
    {
        public HomeController(TenantContext<AppTenant> tenantContext)
        {

        }
    }

以下是使tenantContext可注入的扩展类

public static class MultitenancyServiceCollectionExtensions
    {
        public static IServiceCollection AddMultitenancy<TTenant, TResolver>(this IServiceCollection services) 
            where TResolver : class, ITenantResolver<TTenant>
            where TTenant : class
        {
            Ensure.Argument.NotNull(services, nameof(services));

            services.AddScoped<ITenantResolver<TTenant>, TResolver>();

            // Make Tenant and TenantContext injectable
            services.AddScoped(prov => 
                prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenant<TTenant>());

            services.AddScoped(prov =>
                prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenantContext<TTenant>());

            // Ensure caching is available for caching resolvers
            services.AddMemoryCache();

            return services;
        }
    }

对此的任何帮助表示赞赏!

【问题讨论】:

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


    【解决方案1】:

    你不能/不应该这样做。问题在于您的注册:

    // Make Tenant and TenantContext injectable
    services.AddScoped(prov => 
        prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenant<TTenant>());
    
    services.AddScoped(prov =>
        prov.GetService<IHttpContextAccessor>()?.HttpContext?.GetTenantContext<TTenant>());
    

    他们都可以是null!当您注册一个依赖项时,它必须NEVERnull!

    在这种情况下,例如,您必须确保始终返回 Tenant,如果没有租户信息,则返回通用或未初始化的 Tenant 实例。您的TenantContext&lt;AppTenant&gt; 也是如此。它必须始终为非空,但租户可能不必包含有效的租户信息,即您可以在其上拥有 IsValid 属性来检查其是否为有效租户。

    当有人错误键入包含租户的 url 部分或访问没有租户标题的页面(或者您正在处理租户)时,您可能有一个无效的租户。

    您有时会遇到此问题,有时不会遇到此问题的原因是因为服务是按请求(范围)的,因此对于每个请求,它都会尝试再次调用工厂方法,并且每次都可能导致 null。

    【讨论】:

    • 这就是我的问题?为什么它变得空了?当有人键入无效的 url/租户名称时,该部分的处理方式就像您建议的未初始化租户实例(默认租户)一样。那么我需要注册 Singleton OR Transient 吗?
    • 不是单例,它是作用域生命周期的工作。但是从您发布的代码来看,您似乎使用的是旧版本的 Saaskit。代码来自 1.1.3。 1.1.4 的代码看起来略有不同github.com/saaskit/saaskit/blob/1.1.4/src/SaasKit.Multitenancy/…
    • 好的,会检查的!另外,我在AppTenantResolver类的Session中设置了TenanContext,这样我就不需要一次又一次地解析租户。但是对于执行的任何操作方法,此会话值有时会为 null。我设置了 context.Session.SetObjectAsJson("TenantContext", tenantContext); 为什么这个 HttpContext 会话有时会为空?因此,我无法获取租户上下文
    猜你喜欢
    • 2016-09-19
    • 2021-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 2023-01-30
    相关资源
    最近更新 更多