Anders G. Nordby

Senior Web Developer at CGI

More on Indexing MetaData with Find

After figuring out how to index meta data with Find (see previous post: http://andersnordby.wordpress.com/2014/09/17/episerver-find-indexing-metadata-with-pagedata/), I thought more about the situation, and decided that it would probably be best to index the PageData object and the MetaData object together in a new custom object for this purpose, thus making sure that I get the correct number of hits etc.

So I created the following class:

public class CourseWithMetaData
{
	[Id]
	public Guid CourseGuid { get; set; }
	public CoursePage CoursePage { get; set; }
	public CourseContainer MetaData { get; set; }
	public string SearchTitle { get; set; }
}

This was indexed (as described in my previous post) like this:

ContentIndexer.Instance.Conventions.ForInstancesOf<CoursePage>()
	.ShouldIndex(new EPiServerFindIndexing().CoursePageIndexingWithMetaData);

…using this class for handling the indexing of my custom object:

public class EPiServerFindIndexing
{
	private readonly ICourseDelegate _courseDelegate = 
		ServiceLocator.Current.GetInstance<ICourseDelegate>();

	public bool CoursePageIndexingWithMetaData(CoursePage coursePage)
	{
		var metaData = GetMetaDataAsync(coursePage);
		var courseWithMetaData = new CourseWithMetaData
		{
			CourseGuid = new Guid(coursePage.KursId),
			CoursePage = coursePage,
			MetaData = metaData,
			SearchTitle = coursePage.Name
		};

		SearchClient.Instance.Index(courseWithMetaData);
		return false;
	}

	private CourseContainer GetMetaDataAsync(CoursePage coursePage)
	{
		return _courseDelegate.GetAsync(new Guid(coursePage.KursId)).Result;
	}
}

This worked perfectly, and looking at my indexed items from the Find GUI confirmed that everything was fine with my objects and the data they contained. However, when trying to fetch them, I was in for a surprise. I wrote the following code for retreiving all courses:

public List<CoursePage> GetAllCourses()
{
	var result = _client.Search<CourseWithMetaData>()
		.Select(x => x.CoursePage)
		.GetResult();

	return result.ToList();
}

This crashed with this (to me mysterious!) error message:

Server Error in ‘/’ Application. Property ‘PagePendingPublish’ does not exist, can only assign values to existing properties Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

With excellent help from Johan Kronberg on EPiServer World, I was able to learn what to do about this. Link to discussion: http://world.episerver.com/Modules/Forum/Pages/thread.aspx?id=85490

One solution is to fetch the PageData content using the ContentRepository, like this:

public List<CoursePage> GetAllCourses()
{
	var result = _client.Search<CourseWithMetaData>()
		.Select(x => _contentRepository.Get<CoursePage>(x.CoursePage.PageLink))
		.GetResult();

	return result.ToList();
}

However, I most likely do not need the whole PageData object in return. A better way is to create custom objects for whatever I want in return from the search, and populate these using projections. An example of a light-wight object to return:

public class CourseListItem
{
	public PageReference PageReference { get; set; }
	public DateTime StartTime { get; set; }
	public string Location { get; set; }
}

The code to search for (and return) these items:

public List<CourseListItem> GetAllCourses()
{
	var result = _client.Search<CourseWithMetaData>()
		.Select(x => new CourseListItem
		{
			PageReference = x.CoursePage.PageLink,
			StartTime = x.CoursePage.StartTime,
			Location = x.CoursePage.LocationPostalName
		})
		.GetResult();

	return result.ToList();
}

This works perfectly!

Follow

Get every new post delivered to your Inbox.