"An item with the same key has already been added"

Vote:
 

This is my scenario:

I am using UnifiedSearchFor to search in content types together with a few custom types. For one of the custom types (Employee) I want to show some additional info in the search hit compared to a hit for e.g a standard content page.

To do this I have added the following conventions:

SearchClient.Instance.Conventions.UnifiedSearchRegistry
.Add();
SearchClient.Instance.Conventions
.ForInstancesOf()
.IncludeField(e => e.EmployeeMetaData());
SearchClient.Instance.Conventions.UnifiedSearchRegistry
.ForInstanceOf()
.ProjectMetaDataFrom(e => e.EmployeeMetaData());

where the extensionmethod EmployeeMetaData looks something like this:

private static IDictionary EmployeeMetaData(this Employee e)
        {                           
            var metaData = new Dictionary
            {
                {"Titel", e.Title},
                {"Telefon", e.Phone},
                {"Mobil", e.CellPhone},
                {"E-post", e.Email},
            };

            return metaData;
        }

So far so good, the UnifiedSearchHit.MetaData contains the info I want to show. However, when I call Client.Get(id) I get: "System.ArgumentException: An item with the same key has already been added". 

Stack trace:

[ArgumentException: An item with the same key has already been added.]
   System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) +52
   System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +10925834
   System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) +10

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
   System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +92
   System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +108
   EPiServer.Find.Json.DictionaryConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) +637
   Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) +327
   Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) +1671
   Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) +517
   Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) +184
   Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) +791
   Newtonsoft.Json.Serialization.JsonSerializerProxy.DeserializeInternal(JsonReader reader, Type objectType) +75
   Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) +46
   EPiServer.Find.Api.SearchHitConverter.PopulateItemProperty(JsonReader reader, JsonSerializer serializer, Type objectType, Object item) +99
   EPiServer.Find.Api.SearchHitConverter.PopulateProperty(JsonReader reader, JsonSerializer serializer, Type objectType, String propertyName, Object item) +65
   EPiServer.Find.Json.IgnoredPropertiesHandlingConverterBase.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) +425
   Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) +791
   Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) +1144
   Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) +46
   Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader) +128
   EPiServer.Find.Api.GetCommand`1.Execute() +370
   EPiServer.Find.Client.GetWithMeta(DocumentId id, Action`1 commandAction) +329
   EPiServer.Find.Client.Get(DocumentId id, Action`1 commandAction) +56
   EPiServer.Find.Client.Get(DocumentId id) +55

Is this some bug or am I simply doing this the wrong way?

#90237
Sep 04, 2014 10:57
Vote:
 

Any particular reason you are putting the values in a dictionary? The way I see it, would it not be better to create a MetaData class and populate that instead? That would not mess up the deserialization and it would also make it a lot easier to query.

EDIT: Right, because of ProjectMetaDataFrom. I guess I should have read the entire question ;-)

#90342
Edited, Sep 08, 2014 8:48
Vote:
 

Hi,

So this is a bug then. Problem occurs when we are deserializing the dictionary and it is static like that. Meaning it is already there. We need to fail silently here then I assume.

I have added a bug for this. We will look at it as soon as possible.

/Marcus

#90352
Sep 08, 2014 9:56
Vote:
 

Ok, thanks! I forgot to mention that we are currently using version 8.0.3.411 of Find, if you need it for the bug report.

/Gustav

#90361
Sep 08, 2014 11:49
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.