Tuesday, 30 April 2019

Extending Dependency Injection in Sitecore

One of things I noticed when switching over to use Sitecore's dependency injection framework (Microsoft.Extensions.DependencyInjection), was that unlike some other frameworks (Castle Windsor for example) you do not get any logging or messaging in relation to poorly configured services at startup.  This means that the only time you know when something has been poorly configured is when you hit code that tries to inject those services and subsequently throws an error.  By contrast Castle Windsor will display a YSOD detailing configuration issues on startup.

With that in mind I thought I would create my own set of utilities and services that would check the IoC registered services on startup.  Furthermore I wanted to make it extendible so that additional functionality could be injected in at a later date to check for things that I hadn't thought of.

Additionally I wanted it to have the functionality to show a YSOD and stop the application on failure (configurable) but also log all the findings to a separate file.

As an aside; the way that I register services is to have a number of interfaces that act as flags, that indicate what lifestyle the service should be registered with.  

These include:

IService
IHelper
IScoped

I then created my own ServiceCollection extension method(s) to register these service:

       [MethodImpl(MethodImplOptions.NoInlining)]
        public static void AddServices(this IServiceCollection serviceCollection, params Assembly[] assemblies)
        {
            var services = GetTypesImplementing<IService>(assemblies);

            foreach (var controller in services)
            {
                var firstInterface = controller.GetInterfaces()[0];
                serviceCollection.AddTransient(firstInterface, controller);
            }

            var scoped = GetTypesImplementing<IScoped>(assemblies);

            foreach (var controller in scoped)
            {
                var firstInterface = controller.GetInterfaces()[0];
                serviceCollection.AddTransient(firstInterface, controller);
            }

            var helpers = GetTypesImplementing<IHelper>(assemblies);

            foreach (var controller in helpers)
            {
                var firstInterface = controller.GetInterfaces()[0];
                serviceCollection.AddSingleton(firstInterface, controller);
            }
        }

Ok so back to the main thread of this blog: The main class that checks the registered services is called VaidateIoC and is registered in Sitecore's initialize pipeline as follows:


    <pipelines>
      <initialize>
        <processor patch:before="processor[@type='Sitecore.Pipelines.Loader.RegisterjQuery, Sitecore.Kernel']"
                   type="Shared.Library.Pipelines.IoC.ValidateIoC, Shared.Library" resolve="true"/>
      </initialize>
    </pipelines>

The validation code:

 public class ValidateIoC
    {
        private const string CONTAINS_GENERIC_PARAMETER = "Type ContainsGenericParameters == true";

        private const string VALIDATE_IOC_ENABLED = "ValidateIoC.Enabled";

        private const string VALIDATE_IOC_HALT_APPLICATION = "ValidateIoC.HaltApplication";

        private const string VALIDATE_IOC_IGNORED_EXCEPTIONS = "ValidateIoC.IgnoredExceptions";

        public void Process(PipelineArgs args)
        {
            if (!Settings.GetBoolSetting(VALIDATE_IOC_ENABLED, true)) return;

            var serviceCollection = ServiceLocator.ServiceProvider.GetService<IServiceCollection>();
            if (serviceCollection == null) return;

            IoCLogger.Log.Info(string.Format("IoC Validation Started {0:g}", DateTime.Now));

            var result = new IoCMetaData();

            foreach (var service in serviceCollection)
            {
                var serviceType = service.ServiceType;
                if (result.ValidTypes.Any(p => p.ServiceType == serviceType.ToString()))
                {
                    continue;
                }

                try
                {
                    if (serviceType.ContainsGenericParameters)
                    {
                        result.NotValidatedTypes.Add(new ServiceMetaData { ServiceType = serviceType.ToString(), Reason = CONTAINS_GENERIC_PARAMETER });
                        continue;
                    }

                    var xs = ServiceLocator.ServiceProvider.GetServices(service.ServiceType);
                    foreach(var x in xs)
                    {
                        if (x == null) continue;
                        result.ValidTypes.Add(
                            new ValidServiceMetaData { ServiceType = serviceType.ToString(), ConcreteType = x.GetType().FullName});

                        //Run External Tests
                        var validators = ServiceLocator.ServiceProvider.GetServices<IValidateIoCValidator>();
                        foreach (var validator in validators) validator.Validate(x, result, serviceType);
                    }
                }
                catch (KeyNotFoundException)
                {
                    result.ValidTypes.Add(new ValidServiceMetaData { ServiceType = serviceType.ToString() });
                }
                catch (Exception e)
                {
                    result.Problems.Add(new ServiceMetaData { ServiceType = serviceType.ToString(), Reason = e.Message });
                }
            }

            var postProcessValidators = ServiceLocator.ServiceProvider.GetServices<IValidateIoCValidatorPostProcess>();
            foreach (var validator in postProcessValidators) validator.Validate(result);

            IoCLogger.Log.Info(JsonConvert.SerializeObject(result, Formatting.Indented));

            IoCLogger.Log.Info(string.Format("IoC Validation Finished {0:g}", DateTime.Now));

            if (Settings.GetBoolSetting(VALIDATE_IOC_HALT_APPLICATION, false))
            {
                var ignoredServices = Settings.GetSetting(VALIDATE_IOC_IGNORED_EXCEPTIONS, "").Split('|');
                if (result.Problems.Select(p => p.ServiceType).Except(ignoredServices).Any())
                {
                    args.AbortPipeline();
                    throw new ApplicationException("IoC Validation has failed and configuration is set to halt the application.  See IoC Logs for more info.");
                }
            }
        }
    }

This class will iterate through each registered service and try to instantiate it, logging the results to a model. 

Also at this point the class will execute any services with the IValidateIoCValidator interface against the currently selected registered service. 

As an example I created a validator that checked any services registered with the IHelper interface for dependent services that were not registered with an IHelper interface. 

In otherwords I didn't want a singleton with dependent services that were not singletons.

    public class ValidateIHelperInterfaces : IValidateIoCValidator
    {
        private const string ERROR_MESSAGE = "One or More Parameters implements IService or IScoped";

        public void Validate(object x, IoCMetaData result, Type serviceType)
        {
            //Test to see if Singleton uses non-singleton services

            if (x is IHelper)
            {
                var foundServices = false;
                var constructors = x.GetType().GetConstructors();

                foreach (var constructor in constructors)
                {
                    var parameters = constructor.GetParameters();

                    foreach (var parameter in parameters)
                    {
                        if (parameter.ParameterType.GetInterfaces().Contains(typeof(IService)) || parameter.ParameterType.GetInterfaces().Contains(typeof(IScoped)))
                        {
                            foundServices = true;
                            break;
                        }

                        if (foundServices) break;
                    }
                }

                if (foundServices) result.Warnings.Add(new ServiceMetaData { ServiceType = serviceType.ToString(), ConcreteType = x.GetType().FullName, Reason = ERROR_MESSAGE });
            }
        }
    }

After all of the registered services have been checked, additional validators can be run that are not service specific. These are registered with the IValidateIoCValidatorPostProcess interface. 

An example of this is where we have an enumeration, where each enumerate corresponds to a service that implements a different version of a generic interface.  In the code there is a factory class that resolves these dependent services as a collection of services and then passes these off as and when requested.  

My validator checks that there is a service for each enumerate (except Generic).
 
   public class IoCValidateIntegrationServices : IValidateIoCValidatorPostProcess
    {
        private const string ERROR_MESSAGE = "Could not find integration service for {0}";

        public void Validate(IoCMetaData result)
        {
            result.Messages.Add("Validating Integration Services");
            var integrationServices = ServiceLocator.ServiceProvider.GetServices<IIntegration>().ToList();
            foreach (IntegrationType integrationType in Enum.GetValues(typeof(IntegrationType)))
            {
                if (integrationType == IntegrationType.Generic)
                    continue;

                if (integrationServices.All(p => p.IntegrationType != integrationType))
                    result.Problems.Add(new ServiceMetaData { Reason = string.Format(ERROR_MESSAGE, integrationType) });
            }
        }
    }

You end up with logging that looks like:

13700 12:46:43 INFO  IoC Validation Started 2019-04-29 12:46 PM
13700 12:46:47 INFO  {
  "NotValidatedTypes": [
    {
      "Reason": "Type ContainsGenericParameters == true",
      "ServiceType": "Service.Shared.Library.Interfaces.IRepositoryBase`1[T]",
      "ConcreteType": null
    }
  ],
  "Problems": [
    {
      "Reason": "Object reference not set to an instance of an object.",
      "ServiceType": "Glass.Mapper.Sc.IGlassHtml",
      "ConcreteType": null
    }
  ],
  "ValidTypes": [
    {
      "ServiceType": "Sitecore.DependencyInjection.BaseServiceProviderBuilder",
      "ConcreteType": "Sitecore.DependencyInjection.DefaultServiceProviderBuilder"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseItemManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultItemManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseTemplateManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultTemplateManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BasePublishManager",
      "ConcreteType": "Sitecore.Publishing.DefaultPublishManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseHistoryManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultHistoryManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseIndexingManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultIndexingManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLanguageManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultLanguageManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseThemeManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultThemeManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseCacheManager",
      "ConcreteType": "Sitecore.Caching.DefaultCacheManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseFieldTypeManager",
      "ConcreteType": "Sitecore.Data.Fields.DefaultFieldTypeManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLanguageFallbackFieldValuesManager",
      "ConcreteType": "Sitecore.Data.LanguageFallback.DefaultLanguageFallbackFieldValuesManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseProxyManager",
      "ConcreteType": "Sitecore.Data.Proxies.DefaultProxyManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseSerializationManager",
      "ConcreteType": "Sitecore.Data.Serialization.DefaultSerializationManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseValidatorManager",
      "ConcreteType": "Sitecore.Data.Validators.DefaultValidatorManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseStandardValuesManager",
      "ConcreteType": "Sitecore.Data.DefaultStandardValuesManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseJobManager",
      "ConcreteType": "Sitecore.Jobs.DefaultJobManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseControlManager",
      "ConcreteType": "Sitecore.Presentation.DefaultControlManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BasePresentationManager",
      "ConcreteType": "Sitecore.Presentation.DefaultPresentationManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BasePreviewManager",
      "ConcreteType": "Sitecore.Publishing.DefaultPreviewManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseMediaManager",
      "ConcreteType": "Sitecore.Resources.Media.DefaultMediaManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseMediaPathManager",
      "ConcreteType": "Sitecore.Resources.Media.DefaultMediaPathManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseAccessRightManager",
      "ConcreteType": "Sitecore.Security.AccessControl.DefaultAccessRightManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseAuthorizationManager",
      "ConcreteType": "Sitecore.Security.AccessControl.DefaultAuthorizationManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseRolesInRolesManager",
      "ConcreteType": "Sitecore.Security.Accounts.DefaultRolesInRolesManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseUserManager",
      "ConcreteType": "Sitecore.Security.Accounts.DefaultUserManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseDomainManager",
      "ConcreteType": "Sitecore.SecurityModel.DefaultDomainManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseFeedManager",
      "ConcreteType": "Sitecore.Syndication.DefaultFeedManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLayoutManager",
      "ConcreteType": "Sitecore.Visualization.DefaultLayoutManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseRuleManager",
      "ConcreteType": "Sitecore.Visualization.DefaultRuleManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseTicketManager",
      "ConcreteType": "Sitecore.Web.Authentication.DefaultTicketManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseDistributedPublishingManager",
      "ConcreteType": "Sitecore.Publishing.DefaultDistributedPublishingManager"
    },
    {
      "ServiceType": "Sitecore.Data.Managers.LanguageFallbackStrategy",
      "ConcreteType": "Sitecore.Data.Managers.DefaultLanguageFallbackStrategy"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLanguageFallbackManager",
      "ConcreteType": "Sitecore.Data.Managers.DefaultLanguageFallbackManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseEventManager",
      "ConcreteType": "Sitecore.Eventing.DefaultEventManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLinkManager",
      "ConcreteType": "Sitecore.Links.DefaultLinkManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseSiteManager",
      "ConcreteType": "Sitecore.Sites.DefaultSiteManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseScriptFactory",
      "ConcreteType": "Sitecore.CodeDom.Scripts.DefaultScriptFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseCorePipelineManager",
      "ConcreteType": "Sitecore.Pipelines.DefaultCorePipelineManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BasePipelineFactory",
      "ConcreteType": "Sitecore.Pipelines.DefaultPipelineFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseFactory",
      "ConcreteType": "Sitecore.Configuration.DefaultFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseTranslate",
      "ConcreteType": "Sitecore.Globalization.DefaultTranslate"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseRuleFactory",
      "ConcreteType": "Sitecore.Rules.DefaultRuleFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseComparerFactory",
      "ConcreteType": "Sitecore.Data.Comparers.DefaultComparerFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLinkStrategyFactory",
      "ConcreteType": "Sitecore.Links.DefaultLinkStrategyFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseSiteContextFactory",
      "ConcreteType": "Sitecore.Sites.DefaultSiteContextFactory"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseClient",
      "ConcreteType": "Sitecore.DefaultClient"
    },
    {
      "ServiceType": "Sitecore.CodeDom.Scripts.BaseItemScripts",
      "ConcreteType": "Sitecore.CodeDom.Scripts.DefaultItemScripts"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BasePlaceholderCacheManager",
      "ConcreteType": "Sitecore.Caching.Placeholders.DefaultPlaceholderCacheManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseArchiveManager",
      "ConcreteType": "Sitecore.Data.Archiving.DefaultArchiveManager"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseLog",
      "ConcreteType": "Sitecore.Diagnostics.DefaultLog"
    },
    {
      "ServiceType": "Sitecore.Abstractions.BaseAuthenticationManager",
      "ConcreteType": "Sitecore.Security.Authentication.DefaultAuthenticationManager"
    },
    {
      "ServiceType": "Sitecore.Caching.Placeholders.PlaceholderCacheEventHandler",
      "ConcreteType": "Sitecore.Caching.Placeholders.PlaceholderCacheEventHandler"
    },
    {
      "ServiceType": "Sitecore.Caching.BaseCacheConfiguration",
      "ConcreteType": "Sitecore.Caching.DefaultCacheConfiguration"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Data.Managers.ItemProviderBase,Sitecore.Data.Managers.ItemProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Data.Managers.ItemProviderBase, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Data.Managers.ItemProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Data.Managers.TemplateProvider",
      "ConcreteType": "Sitecore.Data.Managers.TemplateProvider"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Publishing.PublishProvider,Sitecore.Publishing.PublishProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Publishing.PublishProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Publishing.PublishProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Data.Managers.HistoryProvider",
      "ConcreteType": "Sitecore.Data.Managers.HistoryProvider"
    },
    {
      "ServiceType": "Sitecore.Data.Managers.IndexingProvider",
      "ConcreteType": "Sitecore.Data.Managers.IndexingProvider"
    },
    {
      "ServiceType": "Sitecore.Data.Managers.LanguageProvider",
      "ConcreteType": "Sitecore.Data.Managers.LanguageProvider"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Data.LanguageFallback.LanguageFallbackFieldValuesProvider,Sitecore.Data.LanguageFallback.LanguageFallbackFieldValuesCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Data.LanguageFallback.LanguageFallbackFieldValuesProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Data.LanguageFallback.LanguageFallbackFieldValuesCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Data.StandardValuesProvider,Sitecore.Data.StandardValuesProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Data.StandardValuesProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Data.StandardValuesProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Presentation.ControlProvider,Sitecore.Presentation.ControlProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Presentation.ControlProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Presentation.ControlProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Presentation.PresentationProvider,Sitecore.Presentation.PresentationProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Presentation.PresentationProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Presentation.PresentationProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Publishing.PreviewProvider,Sitecore.Publishing.PreviewProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Publishing.PreviewProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Publishing.PreviewProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Resources.Media.MediaProvider",
      "ConcreteType": "Service.Shared.SharedSource.SitecoreProviders.CustomMediaProvider"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Resources.Media.MediaPathProvider,Sitecore.Resources.Media.MediaPathProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Resources.Media.MediaPathProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Resources.Media.MediaPathProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Security.AccessControl.AccessRightProvider,Sitecore.Security.AccessControl.AccessRightProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Security.AccessControl.AccessRightProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Security.AccessControl.AccessRightProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Security.AccessControl.AuthorizationProvider,Sitecore.Security.AccessControl.AuthorizationProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Security.AccessControl.AuthorizationProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Security.AccessControl.AuthorizationProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Security.Accounts.RolesInRolesProvider,Sitecore.Security.Accounts.RolesInRolesProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Security.Accounts.RolesInRolesProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Security.Accounts.RolesInRolesProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Security.Accounts.UserProvider,Sitecore.Security.Accounts.UserProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Security.Accounts.UserProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Security.Accounts.UserProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.SecurityModel.DomainProvider,Sitecore.SecurityModel.DomainProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.SecurityModel.DomainProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.SecurityModel.DomainProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Eventing.EventProvider,Sitecore.Configuration.Providers.ProviderCollectionBase`1[Sitecore.Eventing.EventProvider]]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Eventing.EventProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Configuration.Providers.ProviderCollectionBase`1[[Sitecore.Eventing.EventProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]], Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Links.LinkProvider,Sitecore.Links.LinkProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Links.LinkProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Links.LinkProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Sites.SiteProvider,Sitecore.Sites.SiteProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Sites.SiteProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Sites.SiteProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Data.Archiving.ArchiveProvider,Sitecore.Data.Archiving.ArchiveProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Data.Archiving.ArchiveProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Data.Archiving.ArchiveProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "Sitecore.Configuration.ProviderHelper`2[Sitecore.Security.Authentication.AuthenticationProvider,Sitecore.Security.Authentication.AuthenticationProviderCollection]",
      "ConcreteType": "Sitecore.Configuration.ProviderHelper`2[[Sitecore.Security.Authentication.AuthenticationProvider, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Security.Authentication.AuthenticationProviderCollection, Sitecore.Kernel, Version=10.0.0.0, Culture=neutral, PublicKeyToken=null]]"
    },
    {
      "ServiceType": "System.Web.HttpContextBase",
      "ConcreteType": "System.Web.HttpContextWrapper"
    },
    {
      "ServiceType": "Sitecore.Services.Core.Security.IUserService",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Security.UserService"
    },
    {
      "ServiceType": "System.Web.Http.ExceptionHandling.IExceptionLogger",
      "ConcreteType": "Sitecore.Services.Infrastructure.Web.Http.ExceptionHandling.SitecoreExceptionLogger"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Web.Http.ExceptionHandling.SitecoreExceptionLogger",
      "ConcreteType": "Sitecore.Services.Infrastructure.Web.Http.ExceptionHandling.SitecoreExceptionLogger"
    },
    {
      "ServiceType": "Sitecore.Services.Core.Diagnostics.ILogger",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Diagnostics.SitecoreLogger"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.IHandlerProvider",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Handlers.HandlerProvider"
    },
    {
      "ServiceType": "Sitecore.Services.Core.ComponentModel.DataAnnotations.IEntityValidator",
      "ConcreteType": "Sitecore.Services.Core.ComponentModel.DataAnnotations.EntityValidator"
    },
    {
      "ServiceType": "System.Web.Http.ExceptionHandling.ExceptionLogger",
      "ConcreteType": "Sitecore.Services.Infrastructure.Web.Http.ExceptionHandling.SitecoreExceptionLogger"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.Controllers.AggregateDiscoveryController",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Controllers.AggregateDiscoveryController"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Reflection.BuilderMapping",
      "ConcreteType": "Sitecore.Services.Infrastructure.Reflection.BuilderMapping"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.Configuration.IConfigurationSectionProvider",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Configuration.ConfigurationSectionReader"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Net.Http.IRequestOrigin",
      "ConcreteType": "Sitecore.Services.Infrastructure.Net.Http.HttpRequestOrigin"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.Configuration.ConfigurationReader",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Configuration.ConfigurationReader"
    },
    {
      "ServiceType": "System.Web.Http.HttpConfiguration",
      "ConcreteType": "System.Web.Http.HttpConfiguration"
    },
    {
      "ServiceType": "System.Web.Routing.RouteCollection",
      "ConcreteType": "System.Web.Routing.RouteCollection"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Web.Http.IHttpConfiguration",
      "ConcreteType": "Sitecore.Services.Infrastructure.Web.Http.ServicesConfigurator"
    },
    {
      "ServiceType": "Sitecore.Services.Core.Configuration.ConfigurationSettings",
      "ConcreteType": "Sitecore.Services.Core.Configuration.ConfigurationSettings"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.ConfigurationSettingsAdapter",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.ConfigurationSettingsAdapter"
    },
    {
      "ServiceType": "System.Reflection.Assembly[]",
      "ConcreteType": "System.Reflection.Assembly[]"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.IRuntimeSettings",
      "ConcreteType": "Sitecore.Services.Infrastructure.RuntimeSettings"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.RestrictedControllerProvider",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.RestrictedControllerProvider"
    },
    {
      "ServiceType": "Sitecore.Services.Infrastructure.Sitecore.Configuration.ConfigurationSectionReader",
      "ConcreteType": "Sitecore.Services.Infrastructure.Sitecore.Configuration.ConfigurationSectionReader"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.AlternatingImageTextController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.AlternatingImageTextController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.HomepageHeroController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.HomepageHeroController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.NavigationController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.NavigationController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.PromoModuleController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.PromoModuleController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.HomepageRichTextController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.HomepageRichTextController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.StoreNewsController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.StoreNewsController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.SimpleBannerController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.SimpleBannerController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.VideoImageController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.VideoImageController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.GenericHeroController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.GenericHeroController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.TrustPilotController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.TrustPilotController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.RichTextController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.RichTextController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.StorageVaultController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.StorageVaultController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.BeforeAndAfterController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.BeforeAndAfterController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.FOneMiniController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.FOneMiniController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.GenericLeadFormController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.GenericLeadFormController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.GlobalController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.GlobalController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.LocationController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.LocationController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.MetaController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.MetaController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.SEOController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.SEOController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.PageController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1Mini.Controllers.PageController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1MiniApi.Controllers.AddLinkController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1MiniApi.Controllers.AddLinkController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1MiniApi.Controllers.ImagePickerController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1MiniApi.Controllers.ImagePickerController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Areas.C1MiniApi.Controllers.MegaMenuController",
      "ConcreteType": "Service.C1Mini.Web.Areas.C1MiniApi.Controllers.MegaMenuController"
    },
    {
      "ServiceType": "Service.C1Mini.Web.Modules.RichText.Services.IRichTextModuleRepository",
      "ConcreteType": "Service.C1Mini.Web.Modules.RichText.Services.SitecoreRichTextModuleRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.UserData.Services.IUserDataRepository",
      "ConcreteType": "Service.FOne.Data.UserData.Services.MongoDbUserDataRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.UserData.Services.IRegistrationStateService",
      "ConcreteType": "Service.FOne.Data.UserData.Services.SessionRegistrationStateService"
    },
    {
      "ServiceType": "Service.FOne.Data.UserData.Services.ISignInSessionService",
      "ConcreteType": "Service.FOne.Data.UserData.Services.SignInSessionService"
    },
    {
      "ServiceType": "Service.FOne.Data.Locations.Services.ILocationRepository",
      "ConcreteType": "Service.FOne.Data.Locations.Services.MongoDbLocationRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.ContactCard.Services.IContactCardRepository",
      "ConcreteType": "Service.FOne.Data.ContactCard.Services.ContactCardRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.PostalCodeExceptions.Services.IPostalCodeExceptionRepository",
      "ConcreteType": "Service.FOne.Data.PostalCodeExceptions.Services.SQLPostalCodeExceptionRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.MultiLocation.Services.IMultiLocationStateService",
      "ConcreteType": "Service.FOne.Data.MultiLocation.Services.SessionMultiLocationStateService"
    },
    {
      "ServiceType": "Service.FOne.Data.MultiLocationManager.Services.IMultiLocationSiteRepository",
      "ConcreteType": "Service.FOne.Data.MultiLocationManager.Services.MongoMultiLocationSiteRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.MultiLocationManager.Services.IMultiLocationContentManager",
      "ConcreteType": "Service.FOne.Data.MultiLocationManager.Services.SitecoreMultiLocationContentManager"
    },
    {
      "ServiceType": "Service.FOne.Data.Factories.Authentication.IFOnePasswordValidatorFactory",
      "ConcreteType": "Service.FOne.Data.Factories.Authentication.FOnePasswordValidatorFactory"
    },
    {
      "ServiceType": "Service.FOne.Data.Boards.Services.IBoardsRepository",
      "ConcreteType": "Service.FOne.Data.Boards.Services.MongoDbBoardsRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.Authentication.Services.IForgotPasswordService",
      "ConcreteType": "Service.FOne.Data.Authentication.Services.ForgotPasswordService"
    },
    {
      "ServiceType": "Service.FOne.Data.Authentication.Services.ISocialUserAuthorizationRepository",
      "ConcreteType": "Service.FOne.Data.Authentication.Services.SocialUserAuthorizationRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.Authentication.Services.IUsersRepository",
      "ConcreteType": "Service.FOne.Data.Authentication.Services.UsersRepository"
    },
    {
      "ServiceType": "Service.FOne.Data.ProfanityFiltering.Services.IProfanityFilterService",
      "ConcreteType": "Service.FOne.Data.ProfanityFiltering.Services.WebPurifyProfanityFilterService"
    },
    {
      "ServiceType": "Service.FOne.Data.Interfaces.IEstimateCalculatorResultsModelFactory",
      "ConcreteType": "Service.FOne.Data.Product.EstimateCalculatorResultsModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Data.GeoIp.Services.IIpInfoService",
      "ConcreteType": "Service.FOne.Data.GeoIp.Services.IpInfoService"
    },
    {
      "ServiceType": "Service.FOne.Data.PostalCodeExceptions.Services.IPostCodeExceptionSqlDataContext",
      "ConcreteType": "Service.FOne.Data.PostalCodeExceptions.Services.PostalCodeExceptionsSqlDataContext"
    },
    {
      "ServiceType": "Service.Shared.Library.Pipelines.IoC.Validators.IValidateIoCValidator",
      "ConcreteType": "Service.Shared.Library.Pipelines.IoC.Validators.ValidateConstructorArguments"
    },
    {
      "ServiceType": "Service.Shared.Library.Pipelines.IoC.Validators.IValidateIoCValidator",
      "ConcreteType": "Service.Shared.Library.Pipelines.IoC.Validators.ValidateIHelperInterfaces"
    },
    {
      "ServiceType": "Service.Shared.Library.Pipelines.IoC.Validators.IValidateIoCValidator",
      "ConcreteType": "Service.mNET.Web.Hubs.Validation.IoCHubValidation"
    },
    {
      "ServiceType": "Service.Shared.Library.Interfaces.IRenderingContext",
      "ConcreteType": "Service.Shared.Library.Helpers.RenderingContext"
    },
    {
      "ServiceType": "Service.Shared.Library.Interfaces.ISitecoreContextFactory",
      "ConcreteType": "Service.Shared.Library.Factory.SitecoreContextFactory"
    },
    {
      "ServiceType": "Service.Shared.Library.Interfaces.ISitecoreServiceFactory",
      "ConcreteType": "Service.Shared.Library.Factory.SitecoreServiceFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.AccountController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.AccountController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.AccountManagementController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.AccountManagementController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.BlogController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.BlogController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.CalloutController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.CalloutController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.FOneBaseController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.FOneBaseController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.BoardsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.BoardsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.CommentsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.CommentsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.EstimateCalculatorController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.EstimateCalculatorController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.MultiLocationManagerController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.MultiLocationManagerController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.RoomVisualizerController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.RoomVisualizerController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.SafFinderController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.SafFinderController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.SearchController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.SearchController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.StoreNewsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.StoreNewsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.FlooringGuideController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.FlooringGuideController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.FormsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.FormsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.GenericController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.GenericController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.InspirationController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.InspirationController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.ProductsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.ProductsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.GlobalController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.GlobalController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.LocationController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.LocationController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.HeroController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.HeroController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.PromoModuleController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.PromoModuleController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.MetaController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.MetaController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOne.Controllers.SSOController",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Controllers.SSOController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.FOneBaseApiController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.FOneBaseApiController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.ComparisonController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.ComparisonController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.EstimateCalculatorController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.EstimateCalculatorController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.FlooringGuideCalculatorController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.FlooringGuideCalculatorController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.InspirationController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.InspirationController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.GeneriServicerpetOneController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.GeneriServicerpetOneController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.BoardsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.BoardsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.WFFMController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.WFFMController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.XDbController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.XDbController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.LocationsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.LocationsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.SAFFinderController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.SAFFinderController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.SearchController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.SearchController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.SocialMediaController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.SocialMediaController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.BlogController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.BlogController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.CommentsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.CommentsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.ProductsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.ProductsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.TrustPilotController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.TrustPilotController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.ModalsController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.ModalsController"
    },
    {
      "ServiceType": "Service.FOne.Web.Areas.FOneApi.Controllers.UserController",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Controllers.UserController"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IChatbotLocationServices",
      "ConcreteType": "Service.FOne.Web.Services.ChatbotLocationServices"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Trustpilot.Services.ITrustpilotService",
      "ConcreteType": "Service.FOne.Web.Modules.Trustpilot.Services.TrustpilotService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Zillow.Services.IZillowService",
      "ConcreteType": "Service.FOne.Web.Modules.Zillow.Services.ZillowService"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISitecoreItemHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Utilities.SitecoreItemHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ITransactionalEmailHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Utilities.TransactionalEmailHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.SSO.Services.ISsoService",
      "ConcreteType": "Service.FOne.Web.Modules.SSO.Services.FOneSsoService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Social.Services.ISocialShareRepository",
      "ConcreteType": "Service.FOne.Web.Modules.Social.Services.InspirationSocialShareRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Social.Services.ISocialShareRepository",
      "ConcreteType": "Service.FOne.Web.Modules.Social.Services.SocialShareRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISocialShareRepositoryFactory",
      "ConcreteType": "Service.FOne.Web.Modules.Social.Factories.SocialShareRepositoryFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.SiteSettings.Services.IGetItemService",
      "ConcreteType": "Service.FOne.Web.Modules.SiteSettings.Services.GetItemService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Search.Services.ISearchService",
      "ConcreteType": "Service.FOne.Web.Modules.Search.Services.ProfilingSolrSearchService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Search.Services.ISearchService",
      "ConcreteType": "Service.FOne.Web.Modules.Search.Services.SolrSearchService"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISearchServiceFactory",
      "ConcreteType": "Service.FOne.Web.Modules.Search.Factories.SearchServiceFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.RoomVisualizer.Services.IRoomVisualizerService",
      "ConcreteType": "Service.FOne.Web.Modules.RoomVisualizer.Services.RoomVisualizerService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.MetaData.Services.IMetaDataRepository",
      "ConcreteType": "Service.FOne.Web.Modules.MetaData.Services.SitecoreMetaDataRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.ContactCard.Services.IContactCardSearchServiceRepository",
      "ConcreteType": "Service.FOne.Web.Modules.ContactCard.Services.ContactCardSearchServiceRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.FlooringGuide.Calculators.Services.IFlooringGuideCalculatorService",
      "ConcreteType": "Service.FOne.Web.Modules.FlooringGuide.Calculators.Services.FlooringGuideCalculatorService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.FlooringGuide.Calculators.Services.ISessionFlooringGuideCalculatorService",
      "ConcreteType": "Service.FOne.Web.Modules.FlooringGuide.Calculators.Services.SessionFlooringGuideCalculatorService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Redirect.Services.IAccountRedirectService",
      "ConcreteType": "Service.FOne.Web.Modules.Redirect.Services.AccountRedirectService"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Products.Helpers.ProductHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductSolrHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Products.Helpers.ProductSolrHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISolrProductQueryBase",
      "ConcreteType": "Service.FOne.Web.Modules.Products.Helpers.SolrProductQueryBase"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Products.Compare.Services.IProductService",
      "ConcreteType": "Service.FOne.Web.Modules.Products.Compare.Services.ProductService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Products.Compare.Services.IProductsCompareService",
      "ConcreteType": "Service.FOne.Web.Modules.Products.Compare.Services.ProductsCompareService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Origination.Services.IOriginationService",
      "ConcreteType": "Service.FOne.Web.Modules.Origination.Services.OriginationService"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISiteSettingsProvider",
      "ConcreteType": "Service.FOne.Web.Modules.Localization.Helpers.SiteSettingsProvider"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Comments.Services.ICommentRepository",
      "ConcreteType": "Service.FOne.Web.Modules.Comments.Services.MongoCommentRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IMultiLocationUtilities",
      "ConcreteType": "Service.FOne.Web.Modules.MultiLocation.Utilities.MultiLocationUtilities"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.LMS.Services.ILmsService",
      "ConcreteType": "Service.FOne.Web.Modules.LMS.Services.ServiceLmsService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Inspiration.Services.IInspirationItemRepository",
      "ConcreteType": "Service.FOne.Web.Modules.Inspiration.Services.SitecoreInspirationItemRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ICalloutExtensions",
      "ConcreteType": "Service.FOne.Web.Modules.Inspiration.Utilities.CalloutExtensions"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IInspirationSearchIndex",
      "ConcreteType": "Service.FOne.Web.Modules.Inspiration.Index.InspirationSearchIndex"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Generic.Services.IBeforeAndAfterGalleryService",
      "ConcreteType": "Service.FOne.Web.Modules.Generic.Services.SitecoreBeforeAndAfterGalleryService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Generic.Services.IStoreNewsService",
      "ConcreteType": "Service.FOne.Web.Modules.Generic.Services.StoreNewsService"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Generic.Services.IVideoImageGalleryService",
      "ConcreteType": "Service.FOne.Web.Modules.Generic.Services.SitecoreVideoImageGalleryService"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IStoreNewsIndex",
      "ConcreteType": "Service.FOne.Web.Modules.Generic.Index.StoreNewsIndex"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Blog.Services.IBlogRepository",
      "ConcreteType": "Service.FOne.Web.Modules.Blog.Services.SitecoreBlogRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBlogItemProvider",
      "ConcreteType": "Service.FOne.Web.Modules.Blog.Helpers.BlogItemProvider"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBlogSearchIndex",
      "ConcreteType": "Service.FOne.Web.Modules.Blog.Index.BlogSearchIndex"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBoardsFlooringCalculatorHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Boards.Helpers.BoardsFlooringCalculatorHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBoardHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Boards.Helpers.BoardHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Account.Management.BeforeAndAfterPhotos.Services.IBeforeAndAfterPhotosRepository",
      "ConcreteType": "Service.FOne.Web.Modules.Account.Management.BeforeAndAfterPhotos.Services.SitecoreBeforeAndAfterPhotosRepository"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.ISocialMedia",
      "ConcreteType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.Facebook"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.ISocialMedia",
      "ConcreteType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.GooglePlus"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.ISocialMedia",
      "ConcreteType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.Twitter"
    },
    {
      "ServiceType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.ISocialMediaStateService",
      "ConcreteType": "Service.FOne.Web.Modules.Account.SocialMedia.Services.SocialMediaStateService"
    },
    {
      "ServiceType": "Service.Shared.Library.Pipelines.IoC.Validators.IValidateIoCValidatorPostProcess",
      "ConcreteType": "Service.FOne.Web.Modules.Account.SocialMedia.Factories.IoCValidateSocialMediaServices"
    },
    {
      "ServiceType": "Service.Shared.Library.Pipelines.IoC.Validators.IValidateIoCValidatorPostProcess",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.IoCValidateIntegrationServices"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISocialMediaFactory",
      "ConcreteType": "Service.FOne.Web.Modules.Account.SocialMedia.Factories.SocialMediaFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IFooterViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Global.FooterViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IHeaderViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Global.HeaderViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ICommentViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Comments.CommentViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IHeroViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Blog.Hero.HeroViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBlogHeaderViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Blog.Header.HeaderViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBlogFooterViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Blog.Footer.FooterViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBlogDetailViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Blog.Detail.BlogDetailViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IEmailRecoveryPasswordResetViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.EmailRecoveryPasswordResetViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IRecoverEmailViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.SignIn.RecoverEmailViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IRegistrationStep2ViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.Registration.RegistrationStep2ViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IEmailPreferencesViewModelOrchestrator",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.Management.EmailPreferencesViewModelOrchestrator"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IMyProfileViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.Management.MyProfileViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IMyContactInfoViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.Management.MyContactInfoViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IMyStoreViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.Management.MyStoreViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IStoreNewsDetailsModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.StoreNews.StoreNewsDetailsModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IStoreNewsListingModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.StoreNews.StoreNewsListingModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IHomeInspirationListingViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Inspiration.HomeInspirationListingViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductCategoryShopStickNavViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.ProductCategoryShopStickNavViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IQuickInfoModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.QuickInfoModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISimpleMultiReviewModuleViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.SimpleMultiReviewModuleViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IWhatsTrendingViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.WhatsTrendingViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IComparisonCategoryTableModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.ComparisonCategoryTableModelFactoryFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductCategoryFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.ProductCategoryFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductInstanceViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Products.ProductInstanceViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IListingViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.MultiLocationManager.Listing.ListingViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IMultiLocationMapAndListingViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Location.MultiLocationMapAndListingViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IStoreInformationViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Location.StoreInformationViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISingleStoreLocationViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Location.SingleStoreLocationViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IStoreLocationViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Location.StoreLocationViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IGenericListingCalloutViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Generic.GenericListingCallout.GenericListingCalloutViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISocialAndInteractionViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Generic.SocialAndInteraction.SocialAndInteractionViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IFreeEstimateFormViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Forms.FreeEstimateFormViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISendToStoreFormViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Forms.SendToStoreFormViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IDynamicInspirationCalloutViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Callouts.DynamicInspirationCalloutViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IInspirationCalloutViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Callouts.InspirationCalloutViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ITrustpilotViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Callouts.TrustpilotViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IEstimatesListingViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Boards.EstimatesListingViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IBoardDetailViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Modules.Boards.BoardDetailViewModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ISAFFinderOptionFilter",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Models.SAFFinder.SAFFinderOptionFilter"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductDetailModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Models.Product.ProductDetailModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IProductListingModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Models.Product.ProductListingModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.ITrendingProductModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOneApi.Models.Product.TrendingProductModelFactory"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IXDbHelper",
      "ConcreteType": "Service.FOne.Web.Modules.Utilities.XDbHelper"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IDivisionProductSolrUrl",
      "ConcreteType": "Service.FOne.Web.Modules.Products.Helpers.DivisionProductSolrUrl"
    },
    {
      "ServiceType": "Service.FOne.Web.Interfaces.IRegistrationStep1ViewModelFactory",
      "ConcreteType": "Service.FOne.Web.Areas.FOne.Models.Account.Registration.RegistrationStep1ViewModelFactory"
    },
    {
      "ServiceType": "Microsoft.Extensions.DependencyInjection.IServiceCollection",
      "ConcreteType": "Microsoft.Extensions.DependencyInjection.ServiceCollection"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.CalendarController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.CalendarController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.CalloutController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.CalloutController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.ContactDirectoryController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.ContactDirectoryController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.DashboardController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.DashboardController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.DiscussionsController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.DiscussionsController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.ErrorController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.ErrorController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.HelpCenterController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.HelpCenterController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.MessagingController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.MessagingController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.MetaController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.MetaController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.mNETBaseController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.mNETBaseController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.NotificationsController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.NotificationsController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.ProfileAndSettingsController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.ProfileAndSettingsController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.SSOController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.SSOController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.GroupsController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.GroupsController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.CustomSectionController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.CustomSectionController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.Pages.SignInController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.Pages.SignInController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNET.Controllers.Core.Modules.GlobalModulesController",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Controllers.Core.Modules.GlobalModulesController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNETApi.Controllers.ResetPasswordController",
      "ConcreteType": "Service.mNET.Web.Areas.mNETApi.Controllers.ResetPasswordController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNETApi.Controllers.BookmarksController",
      "ConcreteType": "Service.mNET.Web.Areas.mNETApi.Controllers.BookmarksController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNETApi.Controllers.MessagingContactsController",
      "ConcreteType": "Service.mNET.Web.Areas.mNETApi.Controllers.MessagingContactsController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNETApi.Controllers.CalendarController",
      "ConcreteType": "Service.mNET.Web.Areas.mNETApi.Controllers.CalendarController"
    },
    {
      "ServiceType": "Service.mNET.Web.Areas.mNETApi.Controllers.FileUploadController",
      "ConcreteType": "Service.mNET.Web.Areas.mNETApi.Controllers.FileUploadController"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ISendDiscussionEmailHelper",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Utilities.SendDiscussionEmailHelper"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IWebpageHelpers",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Utilities.WebpageHelpers"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.BlueVoltRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.CompassDataWarehouse"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.CompassSignUpRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.CTSORepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.CventRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.ServiceNewsWireRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.IMarketRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.LitmosRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.PalmRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.MoundRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.ProductClaimsReportingRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.ProductGatewayRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.RebateTrackerRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.RewardBucksRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.RewardsRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.ImageRelayRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.LmsRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.SalesLogixRepositoryModern"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.SalesLogixRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.SpigitRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegration",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Services.SupplierListingRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IIntegrationOrchestrator",
      "ConcreteType": "Service.mNET.Web.Modules.Core.SSO.Factory.IntegrationFactory"
    },
    {
      "ServiceType": "Service.Shared.Alerts.Business.NotificationProcessor.TokenProcessor.TokenProcessors.ITokenProcessor",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Notifications.Token_Processors.Messages.SenderNameTokenProcessor"
    },
    {
      "ServiceType": "Service.Shared.Alerts.Business.NotificationProcessor.TokenProcessor.TokenProcessors.ITokenProcessor",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Notifications.Token_Processors.Discussions.ReplyPosterNameTokenProcessor"
    },
    {
      "ServiceType": "Service.Shared.Alerts.Business.DigestMessageProcessor.DigestMessageTypeProcessor.TokenProcessors.IMessageTypeProcessor",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Notifications.Digest.MessageTypeProcessors.DiscussionProcessor"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Impersonation.Services.IImpersonationService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Impersonation.Services.SitecoreImpersonationService"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IFileViewFactory",
      "ConcreteType": "Service.mNET.Web.Modules.Core.File_Upload.Factories.FileViewFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IFileUploadServiceFactory",
      "ConcreteType": "Service.mNET.Web.Modules.Core.File_Upload.Factories.FileUploadServiceFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMembershipUserSearchService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Contacts.Services.MembershipUserSearchService"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IContactFactory",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Contacts.Factories.ContactFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Bookmarks.Services.IUserBookmarkRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Bookmarks.Services.MongoUserBookmarkRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Search.Services.ISearchService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Search.Services.SolrSearchService"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IDefaultMessagingService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Service.Services.DefaultMessagingService"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Messaging.Data.Services.IMongoDbMessageDataRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Data.Services.MongoDbMongoDbMessageDataRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IConversationViewBuilder",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Business.PresentationBuilder.Services.ConversationViewBuilder"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMessageViewBuilder",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Business.PresentationBuilder.Services.MessageViewBuilder"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMessageProcessorOrchestrator",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Business.MessageProcessor.Factories.MessageProcessorOrchestrator"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IConversationManagerOrchestrator",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Business.ConversationManager.Factories.ConversationManagerOrchestrator"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IConversationProcessorOrchestrator",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Messaging.Business.ConversationProcessor.Factories.ConversationProcessorOrchestrator"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Groups.Services.IGroupSearchService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Services.SolrGroupsSearchService"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Groups.Ideas.Services.IChallengeRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Ideas.Services.ChallengeRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMongoDbIdeaRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Ideas.Services.MongoDbIdeaRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IDefaultGroupDocService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Docs.Service.DefaultGroupDocService"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMongoDocDataProvider",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Docs.Data.MongoDocDataProvider"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Groups.Events.Services.IGroupEventRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Events.Services.SitecoreGroupEventRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupEventSearchIndex",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Events.Indexes.GroupEventSearchIndex"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Groups.Announcements.Services.IGroupAnnouncementSearchService",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Announcements.Services.SolrAnnouncementSearchService"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ISolrAnnouncementSearchIndex",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Announcements.Indexes.SolrAnnouncementSearchIndex"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Discussions.Services.IDiscussionRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Discussions.Services.DiscussionRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IDiscussionSearchIndex",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Discussions.Indexes.DiscussionSearchIndex"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.Cvent.Services.ICventRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Cvent.Services.CventRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.CustomSection.Services.ICustomSectionRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.CustomSection.Services.CustomSectionRepository"
    },
    {
      "ServiceType": "Service.mNET.Web.Modules.Core.ContactDirectory.Services.IContactDirectoryRepository",
      "ConcreteType": "Service.mNET.Web.Modules.Core.ContactDirectory.Services.ContactDirectoryRepository"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.GroupDocHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.IdeaHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.DashboardHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.DiscussionsHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.FirstRunHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.NotificationHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.SearchHub"
    },
    {
      "ServiceType": "Microsoft.AspNet.SignalR.Hubs.IHub",
      "ConcreteType": "Service.mNET.Web.Hubs.MessagingHub"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMyConsultantWidgetJsonModelFactory",
      "ConcreteType": "Service.mNET.Web.Hubs.Models.Dashboard.MyConsultantWidget.MyConsultantWidgetJsonModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupActivityDataJsonModelFactory",
      "ConcreteType": "Service.mNET.Web.Hubs.Models.Dashboard.GroupActivityWidget.GroupActivityDataJsonModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IRebateTrackerWidgetJsonModelFactory",
      "ConcreteType": "Service.mNET.Web.Hubs.Models.Dashboard.RebateTrackerWidget.RebateTrackerWidgetJsonModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IClaimsTrackingWidgetJsonModelFactory",
      "ConcreteType": "Service.mNET.Web.Hubs.Models.Dashboard.ClaimsTrackingWidget.ClaimsTrackingWidgetJsonModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ISelectAffiliationViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.SSO.SelectAffiliation.SelectAffiliationViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IManageSmartBookmarksFormViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ProfileAndSettings.SmartBookmarks.ManageSmartBookmarksFormViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IProfileAndSettingsNavigationViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ProfileAndSettings.Navigation.ProfileAndSettingsNavigationViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IManageExternalUsersModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ProfileAndSettings.ManageExternalUsers.ManageExternalUsersModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.INotificationsListingViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Notifications.NotificationsListing.NotificationsListingViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IUpcomingEventsRightRailCalloutViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.UpcomingEventsRightRailCallout.UpcomingEventsRightRailCalloutViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupsNavigationViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupsNavigation.GroupsNavigationViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupsLanding.GroupViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupPersonViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupPerson.GroupPersonViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupEventsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupEvents.GroupEventsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupEventsRightRailCalloutViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupEventsRightRailCallout.GroupEventsRightRailCalloutViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IConferenceListingViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupEventDetail.ConferenceListingViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupEventDetailViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupEventDetail.GroupEventDetailViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupDocsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupDocs.GroupDocsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupDiscussionsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupDiscussions.GroupDiscussionsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IGroupAnnouncementsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Groups.GroupAnnouncements.GroupAnnouncementsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IDiscussionListingViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Discussions.DiscussionListing.DiscussionListingViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IDiscussionDetailBreadcrumbsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Discussions.DiscussionDetail.DiscussionDetailBreadcrumbsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ISmartBookmarksWidgetViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.SmartBookmarkWidget.SmartBookmarksWidgetViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IRecentlyViewedPagesWidgetViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.RecentlyViewedPagesWidget.RecentlyViewedPagesWidgetViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IEventRegistrationReminderWidgetViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.EventRegistrationReminderWidget.EventRegistrationReminderWidgetViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ICVENTEventRegistrationReminderWidgetViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.CVENTEventRegistrationReminderWidget.CVENTEventRegistrationReminderWidgetViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IDashboardCustomizeWidgetsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.CustomizeWidgets.DashboardCustomizeWidgetsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ICountdownWidgetViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.CountdownWidget.CountdownWidgetViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ICircleOfExcellenceViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.Dashboard.CircleOfExcellenceWidget.CircleOfExcellenceViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.INewsDetailViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.CustomSection.NewsDetail.NewsDetailViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ICustomSectionResourcesFullViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.CustomSection.CustomSectionResourcesFull.CustomSectionResourcesFullViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IContactDirectoryStoresViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ContactDirectory.Stores.ContactDirectoryStoresViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IContactDirectoryStoreDetailViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ContactDirectory.StoreDetail.ContactDirectoryStoreDetailViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IContactDirectoryPersonDetailViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ContactDirectory.PersonDetail.ContactDirectoryPersonDetailViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IContactDirectoryHeaderNavigationViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ContactDirectory.HeaderNavigation.ContactDirectoryHeaderNavigationViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IContactDirectoryPeopleViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Modules.ContactDirectory.ContactDirectoryPeople.ContactDirectoryPeopleViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IHeaderViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Global.Header.HeaderViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IBreadcrumbsViewModelFactory",
      "ConcreteType": "Service.mNET.Web.Areas.mNET.Models.Core.Global.Breadcrumbs.BreadcrumbsViewModelFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.ISolrGroupSearchIndex",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Groups.Indexes.SolrGroupSearchIndex"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.IMongoDbCollectionFactory",
      "ConcreteType": "Service.mNET.Web.Modules.Core.Discussions.Factories.MongoDbCollectionFactory"
    },
    {
      "ServiceType": "Service.mNET.Web.Interfaces.INewsSearchIndex",
      "ConcreteType": "Service.mNET.Web.Modules.Core.CustomSection.Indexes.NewsSearchIndex"
    },
    {
      "ServiceType": "Service.mNET.Data.VisitedNews.Repositories.IVisitedNewsRepository",
      "ConcreteType": "Service.mNET.Data.VisitedNews.Repositories.VisitedNewsRepository"
    },
    {
      "ServiceType": "Service.mNET.Data.Core.WidgetData.Services.IWidgetDataRepository",
      "ConcreteType": "Service.mNET.Data.Core.WidgetData.WidgetDataRepository"
    },
    {
      "ServiceType": "Service.mNET.Data.Core.Cvent.Services.ICventService",
      "ConcreteType": "Service.mNET.Data.Core.Cvent.Services.CventService"
    },
    {
      "ServiceType": "Service.mNET.Data.Core.Contacts.Services.ISitecoreContactCardCreatorService",
      "ConcreteType": "Service.mNET.Data.Core.Contacts.Services.SitecoreContactCardCreatorService"
    },
    {
      "ServiceType": "Service.mNET.Data.Core.Contacts.Services.IContactRepository",
      "ConcreteType": "Service.mNET.Data.Core.Contacts.Services.SitecoreContactRepository"
    },
    {
      "ServiceType": "Service.mNET.Data.Core.Bookmarks.Services.IBookmarksService",
      "ConcreteType": "Service.mNET.Data.Core.Bookmarks.Services.BookmarksService"
    }
  ],
  "Messages": [
    "Hub Service.mNET.Web.Hubs.GroupDocHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.IdeaHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.DashboardHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.DiscussionsHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.FirstRunHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.NotificationHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.SearchHub has Empty Constructor",
    "Hub Service.mNET.Web.Hubs.MessagingHub has Empty Constructor",
    "Validating Social Media Services",
    "Validating Integration Services"
  ],
  "Warnings": []
}
13700 12:46:47 INFO  IoC Validation Finished 2019-04-29 12:46 PM

Any results found in the Problems collection would be consider failures and would cause the YSOD to appear and the application to halt.  However, you can also configure the validator to ignore some error messages

I pushed the code to a git repo https://github.com/jwsadler/ValidateSitecoreIoC.git let me know what you think.

Monday, 29 April 2019

Using a custon xUnit Theory test to load data from Solr


For one of my tests I needed the ability to be able to load JSON data taken from solr. I found the following blog entry by Andrew Lock: https://andrewlock.net/creating-a-custom-xunit-theory-test-dataattribute-to-load-data-from-json-files/ and extended what he did to make it work for Solr data.

In my version I am tightly coupling the attribute to a specific data model, as unfortunately there is not a generic version of the DataAttribute.

 public class ProductListJsonFileAttribute : JsonFileDataAttribute
    {
        public ProductListJsonFileAttribute(string filePath)
            : base(filePath)
        {
        }

        public ProductListJsonFileAttribute(string filePath, string propertyName)
            : base(filePath, propertyName)
        {
        }

        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            if (testMethod == null) throw new ArgumentNullException(nameof(testMethod));

            // Get the absolute path to the JSON file
            var path = _filePath;

            if (!File.Exists(path)) throw new ArgumentException($"Could not find file at path: {path}");

            // Load the file
            var fileData = File.ReadAllText(_filePath);

            if (string.IsNullOrEmpty(_propertyName))
            {
                return new List<object[]>{new object[]{ JsonConvert.DeserializeObject<List<ProductSearchResultsItem>>(fileData) } };
            }

            // Only use the specified property as the data
            var allData = JObject.Parse(fileData);
            var data = allData[_propertyName];
            return new List<object[]> { new object[] { data.ToObject<List<ProductSearchResultsItem>>() } };
        }
    }

To use this in a test, do something like:
        [Theory]
        [ProductListJsonFile(@".\Resources\productdata.json", "docs")]
        public void TestAttribute(List<ProductSearchResultsItem> productItems)
        {
            productItems.Count.Should().BeGreaterThan(0);
        }

With the JSON file looking something like this:
{
  "docs": [
    {"ProductGroup": "Textured Saxony",
      "productgroup_sc": "Textured Saxony",
      "ProductInstanceID": "26605020",
      "Size": "12"},
    {"ProductGroup": "Textured Briton",
      "productgroup_sc": "Textured Briton",
      "ProductInstanceID": "26605021",
      "Size": "14"},
    {"ProductGroup": "Textured Flax",
      "productgroup_sc": "Textured Flax",
      "ProductInstanceID": "26605022",
      "Size": "16"}]
}