A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Ravindra S. Rathore
Sep 22, 2019
  101
(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
A day in the life of an Optimizely OMVP: Learning Optimizely Just Got Easier: Introducing the Optimizely Learning Centre

On the back of my last post about the Opti Graph Learning Centre, I am now happy to announce a revamped interactive learning platform that makes...

Graham Carr | Jan 31, 2026

Scheduled job for deleting content types and all related content

In my previous blog post which was about getting an overview of your sites content https://world.optimizely.com/blogs/Per-Nergard/Dates/2026/1/sche...

Per Nergård (MVP) | Jan 30, 2026

Working With Applications in Optimizely CMS 13

💡 Note:  The following content has been written based on Optimizely CMS 13 Preview 2 and may not accurately reflect the final release version. As...

Mark Stott | Jan 30, 2026

Experimentation at Speed Using Optimizely Opal and Web Experimentation

If you are working in experimentation, you will know that speed matters. The quicker you can go from idea to implementation, the faster you can...

Minesh Shah (Netcel) | Jan 30, 2026