Customer reported about exceptions that comes from Search Engine when scheduler is trying to delete removed objects.
Exception:
DotNetNuke.Services.Exceptions.Exceptions - Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: P. Path '', line 0, position 0. at Newtonsoft.Json.JsonTextReader.ParseValue() at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at DotNetNuke.Services.Search.SearchEngine.DeleteRemovedObjects() at DotNetNuke.Services.Search.SearchEngineScheduler.DoWork()
Investigating the problem it was detected that customer database contains wrong JSON entries in SearchDeletedItems data table. See below:
Rootcause
To add deleted entries there is a method below. It uses deletedIDocument.ToString() to convert object to JSON entity.
Checking further, I found customer is using third-party module. Using decompiler, I found they invokes DataProvider.Instance().AddSearchDeletedItems() and sends SearchDocument argument type instead of SearchDocumentToDelete.
SearchDocumentToDelete is a base class of SearchDocument.
Problem is that both types overrides ToString(). Base class provides Json object as a string, child class provides comma-separated properties string.
Since module sends object of a child type, it uses wrong implementation of ToString. It makes wrong entries in database and causes failures in search engine.
It is better to protect DNN API's to avoid such inconsistencies. We should clearly writes json to that table regardless of a type that comes to API.
Description of bug
Customer reported about exceptions that comes from Search Engine when scheduler is trying to delete removed objects.
Exception:
DotNetNuke.Services.Exceptions.Exceptions - Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: P. Path '', line 0, position 0. at Newtonsoft.Json.JsonTextReader.ParseValue() at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at DotNetNuke.Services.Search.SearchEngine.DeleteRemovedObjects() at DotNetNuke.Services.Search.SearchEngineScheduler.DoWork()
Investigating the problem it was detected that customer database contains wrong JSON entries in
SearchDeletedItems
data table. See below:Rootcause
To add deleted entries there is a method below. It uses
deletedIDocument.ToString()
to convert object to JSON entity.https://github.com/dnnsoftware/Dnn.Platform/blob/6e346c8e0ab1b765abf7ab0caf98bcd7558d92be/DNN%20Platform/Library/Data/DataProvider.cs#L4074-L4084
Checking further, I found customer is using third-party module. Using decompiler, I found they invokes
DataProvider.Instance().AddSearchDeletedItems()
and sendsSearchDocument
argument type instead ofSearchDocumentToDelete
.SearchDocumentToDelete
is a base class ofSearchDocument
.Problem is that both types overrides
ToString()
. Base class provides Json object as a string, child class provides comma-separated properties string.Since module sends object of a child type, it uses wrong implementation of
ToString
. It makes wrong entries in database and causes failures in search engine.It is better to protect DNN API's to avoid such inconsistencies. We should clearly writes json to that table regardless of a type that comes to API.