Skip to content

Instantly share code, notes, and snippets.

@jstemerdink
Created May 3, 2017 09:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jstemerdink/485eb3b205384ed4d896482820dc0725 to your computer and use it in GitHub Desktop.
Save jstemerdink/485eb3b205384ed4d896482820dc0725 to your computer and use it in GitHub Desktop.

Add the average rating of content to your Find index.

If you are using Episerver Social on your site, you may want to add the average rating of a page to the find index. Samples based on the SocialAlloy project by Episerver.

Read my blog here

Powered by ReSharper image

using System.Collections.Generic;
using System.Linq;
using EPiServer.Core;
using EPiServer.Filters;
using EPiServer.Framework.Web;
using EPiServer.ServiceLocation;
using EPiServer.SocialAlloy.Web.Social.Repositories;
/// <summary>
/// Extension methods for content
/// </summary>
public static class ContentExtensions
{
/// <summary>
/// Gets the rating average for the specified <paramref name="content"/>.
/// </summary>
/// <param name="content">The content.</param>
/// <returns>The average rating for the content.</returns>
public static double GetRatingAverage(this IContent content)
{
ISocialRatingRepository socialRatingRepository =
ServiceLocator.Current.GetInstance<ISocialRatingRepository>();
return socialRatingRepository.GetRatingStatistics(content.ContentGuid.ToString())?.Average ?? 0;
}
}
using System;
using EPiServer.Core;
using EPiServer.Find.Cms;
using EPiServer.ServiceLocation;
using EPiServer.Social.ActivityStreams.Core;
using EPiServer.SocialAlloy.Web.Social.Models;
/// <summary>
/// Class ContentRatedActivityHandler.
/// </summary>
/// <seealso cref="EPiServer.Social.ActivityStreams.Core.IActivityHandler{SocialRatingActivity}" />
public class ContentRatedActivityHandler : IActivityHandler<SocialRatingActivity>
{
/// <summary>
/// Handle the specified activity.
/// </summary>
/// <param name="activity">The activity to be handled</param>
/// <param name="extension">The payload of the activity being handled</param>
public void Handle(Activity activity, SocialRatingActivity extension)
{
IContentRepository contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
IContent content = contentRepository.Get<IContent>(Guid.Parse(activity.Target.Id));
HandleFindIndexing(content);
}
/// <summary>
/// Handles the find indexing.
/// </summary>
/// <param name="content">The content.</param>
private static void HandleFindIndexing(IContent content)
{
bool shouldIndex;
bool ok = ContentIndexer.Instance.TryShouldIndex(content, out shouldIndex);
if (ok && shouldIndex)
{
ContentIndexer.Instance.Index(content);
}
}
}
using EPiServer.Core;
using EPiServer.Find.ClientConventions;
using EPiServer.Find.Framework;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
/// <summary>
/// Class FindInitializationModule.
/// </summary>
/// <seealso cref="EPiServer.Framework.IInitializableModule" />
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class FindInitializationModule : IInitializableModule
{
/// <summary>
/// Initializes this instance.
/// </summary>
/// <param name="context">The context.</param>
/// <remarks>Gets called as part of the EPiServer Framework initialization sequence. Note that it will be called
/// only once per AppDomain, unless the method throws an exception. If an exception is thrown, the initialization
/// method will be called repeatedly for each request reaching the site until the method succeeds.</remarks>
public void Initialize(InitializationEngine context)
{
SearchClient.Instance.Conventions.ForInstancesOf<IContent>().IncludeField(x => x.GetRatingAverage());
}
/// <summary>
/// Resets the module into an uninitialized state.
/// </summary>
/// <param name="context">The context.</param>
/// <remarks><para>
/// This method is usually not called when running under a web application since the web app may be shut down very
/// abruptly, but your module should still implement it properly since it will make integration and unit testing
/// much simpler.
/// </para>
/// <para>
/// Any work done by <see cref="M:EPiServer.Framework.IInitializableModule.Initialize(EPiServer.Framework.Initialization.InitializationEngine)" /> as well as any code executing on <see cref="E:EPiServer.Framework.Initialization.InitializationEngine.InitComplete" /> should be reversed.
/// </para></remarks>
public void Uninitialize(InitializationEngine context)
{
}
}
using EPiServer.Cms.UI.AspNetIdentity;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using EPiServer.Social.ActivityStreams.Core;
using EPiServer.SocialAlloy.Web.Social.Adapters;
using EPiServer.SocialAlloy.Web.Social.Common;
using EPiServer.SocialAlloy.Web.Social.Repositories;
using EPiServer.SocialAlloy.Web.Social.Repositories.Moderation;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using StructureMap;
/// <summary>
/// The SocialInitialization class initializes the IOC container mapping social component
/// interfaces to their implementations.
/// </summary>
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class SocialInitialization : IConfigurableModule
{
/// <summary>
/// Configure the IoC container before initialization.
/// </summary>
/// <param name="context">The context on which the container can be accessed.</param>
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Container.Configure(ConfigureContainer);
}
/// <summary>
/// Initializes this instance.
/// </summary>
/// <param name="context">The instance context.</param>
public void Initialize(InitializationEngine context)
{
IActivityService activityService = context.Locate.Advanced.GetInstance<IActivityService>();
activityService.Watch(new ContentRatedActivityHandler());
}
/// <summary>
/// Resets the module into an uninitialized state.
/// </summary>
/// <param name="context">The context.</param>
/// <remarks><para>
/// This method is usually not called when running under a web application since the web app may be shut down very
/// abruptly, but your module should still implement it properly since it will make integration and unit testing
/// much simpler.
/// </para>
/// <para>
/// Any work done by <see cref="M:EPiServer.Framework.IInitializableModule.Initialize(EPiServer.Framework.Initialization.InitializationEngine)" /> as well as any code executing on <see cref="E:EPiServer.Framework.Initialization.InitializationEngine.InitComplete" /> should be reversed.
/// </para></remarks>
public void Uninitialize(InitializationEngine context)
{
}
/// <summary>
/// Configure the IOC container.
/// </summary>
/// <param name="configuration">The IOC container configuration.</param>
private static void ConfigureContainer(ConfigurationExpression configuration)
{
configuration.For<IUserRepository>().Use(() => CreateUserRepository());
configuration.For<IPageRepository>().Use<PageRepository>();
configuration.For<ISocialCommentRepository>().Use<SocialCommentRepository>();
configuration.For<ISocialRatingRepository>().Use<SocialRatingRepository>();
configuration.For<ISocialSubscriptionRepository>().Use<SocialSubscriptionRepository>();
configuration.For<ISocialActivityAdapter>().Use<SocialActivityAdapter>();
configuration.For<ISocialFeedRepository>().Use<SocialFeedRepository>();
configuration.For<ISocialActivityRepository>().Use<SocialActivityRepository>();
configuration.For<ISocialGroupRepository>().Use<SocialGroupRepository>();
configuration.For<ISocialMemberRepository>().Use<SocialMemberRepository>();
configuration.For<ISocialModerationRepository>().Use<SocialModerationRepository>();
}
/// <summary>
/// Create a UserRepository.
/// </summary>
/// <returns>The created UserRepository instance.</returns>
private static IUserRepository CreateUserRepository()
{
return new UserRepository(
new UserManager<IdentityUser>(new UserStore<IdentityUser>(new ApplicationDbContext<IdentityUser>())));
}
}
IContentResult<SitePageData> contentResult = this.searchClient.Search<SitePageData>()
.Filter(c => c.GetRatingAverage().GreaterThan(0))
.OrderByDescending(c => c.GetRatingAverage()).Take(25)
.GetContentResult();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment