London Dev Meetup Rescheduled! Due to unavoidable reasons, the event has been moved to 21st May. Speakers remain the same—any changes will be communicated. Seats are limited—register here to secure your spot!

Ravindra S. Rathore
Sep 22, 2019
  35
(0 votes)

Rebuild the index for selected sites in Episerver Find | Admin Tool

Hi

Last Friday, I wrote a blog post related to "Reindex a target site in Find" using is works job. It works well but you need to update the site definition every time when you want to rebuild the indexes for any site.

So I received some feedback to convert it to Episerver Admin Tool and now I converted it to Episerver Admin Tool. Where you can rebuild the indexes for selected sites.

Here is the final structure of my solution.

To create a new GUI Plugin Episerver provide a template for Webforms but not for MVC so you need to create it manually. Below I mentioned the steps for creating a GUI plugin using MVC.

FYI - You can refer this blog post to create a custom GUI Plugin using MVC

Create a Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using EPiServer.Find.Cms;
using EPiServer.Find.Helpers.Text;
using EPiServer.PlugIn;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using ReindexTargetSite_AdminTool.AdminTools.FindIndexPlugin.ViewModels;

namespace ReindexTargetSite_AdminTool.AdminTools.FindIndexPlugin
{
    [GuiPlugIn(
        Area = PlugInArea.AdminMenu,
        Url = "/custom-plugins/my-plugin",
        DisplayName = "Rebuild Find Index")]
    [Authorize(Roles = "CmsAdmins")]
    public class RebuildFindIndexController : Controller
    {
        public static string Message { get; set; }
        public static string ExecutionCompleteMessage { get; set; }

        private ISiteDefinitionRepository _siteDefinitionRepository;
        public RebuildFindIndexController(ISiteDefinitionRepository siteDefinitionRepository)
        {
            _siteDefinitionRepository = siteDefinitionRepository ?? ServiceLocator.Current.GetInstance<ISiteDefinitionRepository>();

        }
        public ActionResult Index()
        {
            var siteDefinitions = _siteDefinitionRepository.List();
            var siteList = new List<SiteDefinition>();
            if (siteDefinitions.Any())
            {

                foreach (var site in siteDefinitions)
                {
                    siteList.Add(site);
                }

            }

            var model = new RebuildFindIndexViewModel
            {
                Sites = siteList
            };
            return View("~/AdminTools/FindIndexPlugin/Views/Index.cshtml", model);
        }

        [HttpPost]
        public async Task<ActionResult> InitiateRebuildIndex(Guid[] selectedObjects)
        {
            Message = null;
            ExecutionCompleteMessage = null;

            string selectedSite = Request.Form["SelectedSite"];

            _ = Task.Run(() => StartRebuild(selectedObjects));
            return View("~/AdminTools/FindIndexPlugin/Views/Index.cshtml");
        }

        private void StartRebuild(Guid[] selectedSite)
        {
            foreach (var site in selectedSite)
            {
                SiteDefinition.Current = _siteDefinitionRepository.List().FirstOrDefault(i => i.Id.Equals(site));

                if (SiteDefinition.Current != null && !string.IsNullOrEmpty(SiteDefinition.Current.Name))
                {
                    var statusReport = new StringBuilder();

                    // ReIndex the indexes for the sites
                    ContentIndexer.ReIndexResult reIndexResult = ContentIndexer.Instance.ReIndex(
                        status =>
                        {
                            if (status.IsError)
                            {
                                string errorMessage = status.Message.StripHtml();
                                if (errorMessage.Length > 0)
                                    statusReport.Append($"{errorMessage}");
                            }

                            Message =
                                $"Indexing job [{(SiteDefinition.Current.Name)}] [content]: {status.Message.StripHtml()}";
                        },
                        () => false);
                }
            }

            ExecutionCompleteMessage = Message;
        }
        [HttpGet]
        public ActionResult GetMessage()
        {
            return Json(new { RunningMessage = Message, StopExecution = ExecutionCompleteMessage }, JsonRequestBehavior.AllowGet);
        }
    }
}

Create a ViewModel

using System;
using System.Collections.Generic;
using EPiServer.Web;

namespace ReindexTargetSite_AdminTool.AdminTools.FindIndexPlugin.ViewModels
{
    public class RebuildFindIndexViewModel
    {
        public IEnumerable<Guid> SelectedSites { get; set; }
        public IEnumerable<SiteDefinition> Sites { get; set; }
    }
}

Create a View

@using System.Web.Mvc
@using System.Web.Mvc.Html
@inherits System.Web.Mvc.WebViewPage<ReindexTargetSite_AdminTool.AdminTools.FindIndexPlugin.ViewModels.RebuildFindIndexViewModel>
@{
    Layout = null;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
    var messageInterval = setInterval(function () {
        $.get('/custom-plugins/my-plugin/get-message').done(function (result) {
            $(".job-started").show();
            if (result.StopExecution == null) {
                $('#runningStatus').html(result.RunningMessage);

            } else {
                $('#runningStatus').html(result.StopExecution);
                clearInterval(messageInterval);
                $(".job-started").html("Index rebuild successfully");
                $("#runningStatus").hide();
            }
        });
    }, 10000)
</script>
@if (Model != null && Model.Sites != null && Model.Sites.Any())
{
    <h2>Site Listing</h2>

    using (Html.BeginForm("InitiateRebuildIndex", "RebuildFindIndex", FormMethod.Post))
    {

        foreach (var site in Model.Sites)
        {
            <input type="checkbox" title="@site.Name" name="selectedObjects" value="@site.Id">
            <label for="selectedObjects">@site.Name</label>
            <br />

        }
        @*@Html.DropDownList("SelectedSite", new SelectList(Model.Sites, "Value", "Text"))*@
        <input type="submit" value="Rebuild" />
    }
}
else
{
    <h2 class="job-started">Schedule job started</h2>
    <div id="runningStatus"></div>
}

Create an initialization Module 

using System.Web.Mvc;
using System.Web.Routing;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;

namespace ReindexTargetSite_AdminTool.AdminTools.FindIndexPlugin.Initialization
{
    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class PluginRouteInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
             RouteTable.Routes.MapRoute(
             null,
             "custom-plugins/my-plugin",
             new { controller = "RebuildFindIndex", action = "Index" });
             RouteTable.Routes.MapRoute(
                 null,
                 "custom-plugins/my-plugin/initiate-rebuild-index",
                 new { controller = "RebuildFindIndex", action = "InitiateRebuildIndex" });
             RouteTable.Routes.MapRoute(
                 null,
                 "custom-plugins/my-plugin/get-message",
                 new { controller = "RebuildFindIndex", action = "GetMessage" });
        }

        public void Uninitialize(InitializationEngine context)
        {
            //Add uninitialization logic
        }
    }
}

That's it from a code point of view. Now you just need to login into you Episerver and go to Admin view and select the new plugin "Rebuild Find Index"

Now select the sites and click on the "Rebuild" button.

It will rebuild the indexes for the selected sites.

FYI - I will add the link once i upload this to Github.

I hope it helps

Thanks

Ravindra S. Rathore

Sep 22, 2019

Comments

Please login to comment.
Latest blogs
Content Compliance Without the Chaos: How Optimizely CMP Empowers Financial Services Marketers

In financial services, content isn’t just about telling your story — it’s about telling it right. Every blog post, product update, or social post i...

abritt | May 22, 2025 |

Opal – Optimizely’s AI-Powered Marketing Assistant

Overview Opal is Optimizely’s AI assistant designed to accelerate and enhance the entire marketing workflow. Integrated natively across...

abritt | May 22, 2025 |

Integrating Address Validation in Optimizely Using Smarty

Address validation is a crucial component of any ecommerce platform. It ensures accurate customer data, reduces shipping errors, and improves the...

PuneetGarg | May 21, 2025

The London Dev Meetup is TOMORROW!!

The rescheduled London Dev Meetup is happening tomorrow, Wednesday, 21st May, at 6pm! This meetup will be Candyspace 's first, and the first one he...

Gavin_M | May 20, 2025

From Agentic Theory to Practicality: Using Optimizely Opal’s Instructions Feature

A practical look at Optimizely Opal’s Instructions feature — from built-in agents to creating and managing custom instruction workflows. Ideal for...

Andy Blyth | May 19, 2025 |

Common Mistakes in Headless Projects with Optimizely

Adopting a headless architecture with Optimizely is a major shift from the traditional MVC-based development that has been the standard for years....

Szymon Uryga | May 19, 2025