Self referencing loop error

Vote:
 

Hi!

I'm writing a scheduled job for reindexing truffler index for some particular page types.

I have several pagetypes, marked with IShouldBeIndexed interface, so I'm doing following:

var client = SearchHandler.Instance.Client;

//Getting pagetypes that are implementing IShouldBeIndexed interface
var types = Assembly.GetAssembly(typeof(PageTypes.Intranet.BasePageData)).GetTypes().Where(x => x.IsClass && x.GetInterface(typeof(IShouldBeIndexed).Name) != null);

if (!types.Any())
{
	return "Failed: not found types to index.";
}

//Adding filter criteria for each pagetype
PropertyCriteriaCollection criterias = new PropertyCriteriaCollection();
foreach (var type in types)
{
	var pageTypeId = PageTypeResolver.Instance.GetPageTypeID(type);
	if (pageTypeId != null)
	{
		int? pageTypeID = pageTypeId.Value;

		PropertyCriteria pageTypeCriteria = new PropertyCriteria();
		pageTypeCriteria.Condition = EPiServer.Filters.CompareCondition.Equal;
		pageTypeCriteria.Name = "PageTypeID";
		pageTypeCriteria.Type = PropertyDataType.PageType;
		pageTypeCriteria.Value = pageTypeID.ToString(CultureInfo.InvariantCulture);

		criterias.Add(pageTypeCriteria);
	}
}

//Getting pages
var pages = DataFactory.Instance.FindPagesWithCriteria(PageReference.RootPage, criterias);

//Adding pages to index
if (pages.Any())
{
	client.Index(pages);
	return pages.Count().ToString(CultureInfo.InvariantCulture) + "items indexed.";
}

 

But constantly having error message like this:

 

Self referencing loop detected with type 'EPiServer.Core.PropertyCategory'. Path 'Property[0].Parent'.

 

Any ideas how to solve it?

#60636
Aug 20, 2012 17:01
Vote:
 

Try using PageIndexer.Instance.Index(pages); instead, I know they've done some work making sure PropertyCategory gets serialized correctly to JSON. You should also be using EPiServer Find (you can find it on NuGet) and not the Truffler NuGet package.

Frederik

#60637
Aug 20, 2012 19:13
Vote:
 

Thanks, that helped.

#60646
Aug 21, 2012 8:32
Vote:
 

While late I thought I'd add a little more detail for anyone that may be interested.

The general Find .NET API exposes IClient and the Client class which implements IClient. It doesn't however expose an instance of those types. The general EPiServer integration, Find.Framework (the name Framework is meant to match EPiServer Framework/online center), adds the SearchClient class which exposes an instance of IClient. Finally the CMS integration (Find.Cms) contains an initialization module that interacts with the SearchClient.Instance object to modify how some CMS specific classes are handled during serialization. 

If one obtains an instance of the Client through for instance the static CreateFromConfig method it will be a vanilla client that doesn't know anything about specific types such as PageData. It will simply do it's best to index and search for any type of CLR object. However, since complex non-POCO objects such as PageData often contain circular references (A.PropertyB.PropertyA == A) and other obstacles for serialization some special handling, typically through modifications of the client's conventions is needed. For CMS objects, this will be taken care of by the CMS integration given that we're using SearchClient.Instance.

In other words, while your answer solves the problem Frederik, an alternative answer could be to use SearchClient.Instance.Index() to index pages. Which answer is best depends on context. In this case I think the PageIndexer option is the best one, but I'd like to elaborate on the difference.

The PageIndexer class is a component whose job is to... wait for it... index pages. However, while it will ultimately call SearchClient.Instance.Index() it will also take care of other logic specific to the CMS integration such as (optionally) index page files, (optionally) index other pages that are configured as related to a page being indexed etc. This means that:

PageIndexer.Instance.Index() will index a page in the same way as if the indexing was triggered by an event, such as the page being published.

SearchClient.Instance.Index() will index a page and only that page. While it will serialize it using conventions set up by the CMS integrations initialization module it will in all other respects index it as any other CLR object and not apply any other logic such.

Client.CreateFromConfig().Index() will index a page exactly as it would be serialized by JSON.NET out of the box, meaning that it will most likely fail, and even if it doesn't it won't index some additional fields (such as SiteID) that other parts of the CMS integration relies on.

#60739
Aug 22, 2012 21:45
Vote:
 

Wow, thanks for so much detailed answer Joel.

#60833
Aug 28, 2012 10:10
Vote:
 

I'm also getting the error when i run 'EPiServer Find CMS Indexing Job'.
Not sure how I can resolve this. Do I need to write my own 'Indexing job' that uses PageIndexer.Instance.Index(pages); ?

 

Job History:

2013-11-01 09:54:03 OK Indexing job [SITE.se] [Page]: Reindexing completed.
ExecutionTime: 0minutes 5seconds
Number of pages indexed: 96
Number of page errors: 0
Number of batch errors: 1
An exception occured while indexing (Batch): Self referencing loop detected with type 'EPiServer.Core.PropertyLongString'. Path '__data[1][0].Parent'. The loop was detected in the member 0 in type EPiServer.Core.PropertyData[]. To correct this you can exclude one of the properties (or otherwise mapped fields) that are causing the loop by modifying the Client class' conventions. You may also modify the serializer to ignore self references. If you require the fields causing the loop to be serialized you may annotate the one of the classes in the loop with [JsonObject(IsReference = true)] or modify the JsonContract for one of the types to use IsReference = true which also can be done by modifying the Client class' conventions.. (see log for more information)
Indexing job [SITE.se] [File]: Reindexing completed.
ExecutionTime: 0minutes 40seconds
Number of files indexed: 13
Number of file errors: 9
Number of batch errors: 1
EPiServer.Find.Cms.FileIndexer+ReIndexResult



"To correct this you can exclude one of the properties (or otherwise mapped fields) that are causing the loop by modifying the Client class'

How do I know wich class and property to exclude when the error message says ''EPiServer.Core.PropertyLongString'. Path '__data[1][0].Parent'' ?


"You may also modify the serializer to ignore self references"
How do I modyfi the serializer?

 

"(see log for more information)"
I've enabled EPiServers 'Log Service' but it won't give me any information.. what log should I look for?.

 

// Jocke

#76759
Edited, Nov 01, 2013 10:25
Vote:
 

This is annoying, I've just brute-forced all my pages-properties with [JsonIgnore] and still get the message..

Searched for PropertyLongString in my project and commented the code, cleaned dirty properties in admin-mode, empty the recycle bin..

 

What more can I do?.
In the History Message it says "Number of batch errors: 1" (and not page errors). What does this mean?, are all my pages correct?.

#76816
Nov 03, 2013 19:12
Vote:
 

Problem solved!

I recreated my site and now the same code runs like... perfect :)

 

#77524
Nov 20, 2013 16:38
Vote:
 

I'm getting similar error that I'm unable to identify a cause of

EPiServer.Find.SelfReferencingLoopException: Self referencing loop detected with type 'EPiServer.Core.PropertyCategory'. Path 'PageTargetFrame.Parent[0].Parent'. The loop was detected in the member 0 in type EPiServer.Core.PropertyData[]. To correct this you can exclude one of the properties (or otherwise mapped fields) that are causing the loop by modifying the Client class' conventions. You may also modify the serializer to ignore self references. If you require the fields causing the loop to be serialized you may annotate the one of the classes in the loop with [JsonObject(IsReference = true)] or modify the JsonContract for one of the types to use IsReference = true which also can be done by modifying the Client class' conventions. ---> Newtonsoft.Json.JsonSerializationException: Self referencing loop detected with type 'EPiServer.Core.PropertyCategory'. Path 'PageTargetFrame.Parent[0].Parent'.
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IWrappedCollection values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value)
at EPiServer.Find.Api.BulkActionConverter.WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeConvertable(JsonWriter writer, JsonConverter converter, Object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value)
at EPiServer.Find.Json.Serializer.SerializeToStringBuilder(JsonSerializer serializer, Object value, StringBuilder buffer)
--- End of inner exception stack trace ---
at EPiServer.Find.Json.Serializer.SerializeToStringBuilder(JsonSerializer serializer, Object value, StringBuilder buffer)
at EPiServer.Find.Api.BulkCommand.Execute()
at EPiServer.Find.Client.Index(IEnumerable objectsToIndex)
at EPiServer.Find.Cms.PageIndexer.Index(IEnumerable`1 pages, IndexOptions options)
at EPiServer.Find.Cms.Module.IndexingModule.IndexPageQueue()

We rely heavily on Find to get latest list of sub pages (articles) etc. When person publishes a page it doesnt automatically appear in our sub pages. However, after few hours page gets index ok and shows up ok. Error above doesnt happen on our dev environment and UAT which makes it very heard to debug. 

Any ideas?

#79120
Dec 10, 2013 7:06
Vote:
 

I have made PageTargetFrame to be [JsonIgnore] since I don't use it so it was fine to be omitted and that has resolved this issue. (for now).

Don't understand the core issue here though.

#79366
Dec 16, 2013 0:25
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* 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.