You have created custom SolrNet calls, but may have encountered the following exception:
Exception has been thrown by the target of an invocation. ---> Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type ISolrOperations1, key "Some_index" ---> System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
The issue is both Sitecore and SolrNet relies on a ServiceLocator to get Solr operations. When using SolrNet you initialize it like so:
Startup.Init(_url); _solr = ServiceLocator.Current.GetInstance< />>();
Sitecore also initializes a custom locator provider.
ServiceLocator.SetLocatorProvider((ServiceLocatorProvider) (() => (IServiceLocator) new DefaultServiceLocator< />string, object>>(this.Operations)));
Depending on which gets executed last, ServiceLocator.Current.GetInstance either resolves to Sitecore s locator or SolrNet s locator.
Solution
The solution is to create a service locator wrapper which switches between SolrNet s service locator and Sitecore s locator. We will then replace Sitecore s DefaultSolrStartUp that sets the locator provider to our wrapper. Lastly, we will replace the InitializeSolrProvider which calls the DefaultSolrStartUp to our own SharedSolrStartUp.
Service Locator wrapper
public class SharedServiceLocator : IServiceLocator { private const string SitecoreSolrDll = "Sitecore.ContentSearch.SolrProvider"; IServiceLocator _sitecoreLocator; IServiceLocator _solrLocator; public SharedServiceLocator(IServiceLocator solrLocator) { _solrLocator = solrLocator; } public void SetSitecoreServiceLocator(IServiceLocator sitecoreLocator) { _sitecoreLocator = sitecoreLocator; } [MethodImplAttribute(MethodImplOptions.NoInlining)] IEnumerableobject> IServiceLocator.GetAllInstances(Type serviceType) { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetAllInstances(serviceType); } [MethodImplAttribute(MethodImplOptions.NoInlining)] IEnumerable IServiceLocator.GetAllInstances() { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetAllInstances(); } [MethodImplAttribute(MethodImplOptions.NoInlining)] object IServiceLocator.GetInstance(Type serviceType) { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetInstance(serviceType); } [MethodImplAttribute(MethodImplOptions.NoInlining)] object IServiceLocator.GetInstance(Type serviceType, string key) { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetInstance(serviceType, key); } [MethodImplAttribute(MethodImplOptions.NoInlining)] TService IServiceLocator.GetInstance() { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetInstance(); } [MethodImplAttribute(MethodImplOptions.NoInlining)] TService IServiceLocator.GetInstance(string key) { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetInstance(key); } [MethodImplAttribute(MethodImplOptions.NoInlining)] object IServiceProvider.GetService(Type serviceType) { return (Assembly.GetCallingAssembly().FullName.StartsWith(SitecoreSolrDll) ? _sitecoreLocator : _solrLocator).GetService(serviceType); } }
Shared Solr StartUp
Let's replace Sitecore s DefaultSolrStartUp and set the locator provider to our wrapper. The majority of this code is borrowed from Sitecore's DefaultSolrStartUp.
public class SharedSolrStartUp : ISolrStartUp, IProviderStartUp { private readonly DefaultSolrLocator< />string, object>> operations; private readonly ISolrCache solrCache; private SharedServiceLocator _sharedServiceLocator; protected internal virtual DefaultSolrLocator< />string, object>> Operations { get { return this.operations; } } public SharedSolrStartUp(SharedServiceLocator sharedServiceLocator) { if (SolrContentSearchManager.EnableHttpCache) this.solrCache = (ISolrCache)new HttpRuntimeCache(); this.operations = new DefaultSolrLocator< />string, object>>(); _sharedServiceLocator = sharedServiceLocator; } public virtual void AddCore(string coreId, Type documentType, string coreUrl) { ISolrConnection connection = this.CreateConnection(coreUrl); this.Operations.AddCore(coreId, documentType, coreUrl, connection); } public virtual void Initialize() { if (!SolrContentSearchManager.IsEnabled) throw new InvalidOperationException("Solr configuration is not enabled. Please check your settings and include files."); this.Operations.DocumentSerializer = (ISolrDocumentSerializer< />string, object>>)new SolrFieldBoostingDictionarySerializer(this.Operations.FieldSerializer); this.Operations.HttpWebRequestFactory = SolrContentSearchManager.HttpWebRequestFactory; this.Operations.SchemaParser = (ISolrSchemaParser)new Sitecore.ContentSearch.SolrProvider.Parsers.SolrSchemaParser(); foreach (string core in SolrContentSearchManager.Cores) { this.AddCore(core, typeof(Dictionarystring, object>), string.Format("{0}/{1}", (object)SolrContentSearchManager.ServiceAddress, (object)core)); if (SolrContentSearchManager.EnableHttpCache) this.Operations.HttpCache = this.solrCache; this.Operations.CoreAdmin = this.BuildCoreAdmin(); _sharedServiceLocator.SetSitecoreServiceLocator(new DefaultServiceLocator< />string, object>>(this.Operations)); ServiceLocator.SetLocatorProvider(() => _sharedServiceLocator); SolrContentSearchManager.SolrAdmin = (ISolrCoreAdmin)this.Operations.CoreAdmin; SolrContentSearchManager.Initialize(); } public virtual bool IsSetupValid() { if (!SolrContentSearchManager.IsEnabled) return false; ISolrCoreAdminEx admin = this.BuildCoreAdmin(); return SolrContentSearchManager.Cores.Selectstring, CoreResult>((Funcstring, CoreResult>)(defaultIndex => admin.Status(defaultIndex).First())).All ((Funcbool>)(status => status.Name != null)); } protected virtual ISolrCoreAdminEx BuildCoreAdmin() { return this.Operations.BuildCoreAdmin(this.CreateConnection(SolrContentSearchManager.ServiceAddress)); } protected virtual ISolrConnection CreateConnection(string serverUrl) { SolrConnection solrConnection = new SolrConnection(serverUrl); solrConnection.Timeout = SolrContentSearchManager.ConnectionTimeout; if (this.solrCache != null) solrConnection.Cache = this.solrCache; return (ISolrConnection)solrConnection; } } }
Initialize pipeline
Here we will initialize SolrNet as well as Sitecore's.
using Microsoft.Practices.ServiceLocation; using Sitecore.ContentSearch.SolrProvider; using Sitecore.ContentSearch.SolrProvider.SolrNetIntegration; using Sitecore.Pipelines; using SolrNet; namespace YourNameSpace { public class InitializeSharedSolrProvider { public void Process(PipelineArgs args) { if (!SolrContentSearchManager.IsEnabled) return; if (IntegrationHelper.IsSolrConfigured()) { IntegrationHelper.ReportDoubleSolrConfigurationAttempt(this.GetType()); } else { Startup.Init("your solr url"); Startup.Init("your solr url"); //Place any custom SolrNet init prior to this linevar sharedSolrStartUp = new SharedSolrStartUp(new SharedServiceLocator(ServiceLocator.Current)); //init Sitecore's solr sharedSolrStartUp.Initialize(); } } } }
Sitecore Configuration
Lastly, we'll patch Sitecore to use your InitializeSharedSolrProvider pipeline.
"YourNameSpace.InitializeSharedSolrProvider, Assembly" patch:instead="*[@type='Sitecore.ContentSearch.SolrProvider.Pipelines.Loader.InitializeSolrProvider, Sitecore.ContentSearch.SolrProvider']"/>