HomeDev guideAPI Reference
Dev guideUser GuideLegal TermsGitHubNuGetDev CommunitySubmit a ticketLog In

Alloy MVC with Optimizely Graph Client

Create a standard Alloy MVC sample site and use Optimizely Graph Service and Optimizely Graph Client (OG Client).

Use a few lines of C# code and a dedicated package to build GraphQL search queries for Optimizely Graph, similar to Search & Navigation.

This tutorial uses Visual Studio Code with extensions. You can use whatever IDE you prefer.

Add the Optimizely Graph Client tools

This tool allows you to generate schema's models after indexing your data.

Create a new folder called ContentGraph:

mkdir ContentGraph

Go to the folder ContentGraph:

cd ContentGraph

Create a manifest file by running the dotnet new command:

dotnet new tool-manifest

Install Optimizely Graph Client tools locally:

dotnet tool install Optimizely.Graph.Client.Tools

Create Alloy MVC site

Create a new folder for the site called AlloyMvcGraphQL:

mkdir AlloyMvcGraphQL

Go to the folder AlloyMvcGraphQL:

cd AlloyMvcGraphQL

Create the Alloy MVC site:

dotnet new epi-alloy-mvc

Add the latest CMS package:

dotnet add package EPiServer.Cms

Start the site:

dotnet run

Open your browser, go to the site https://localhost:5000, add the admin user, and make sure the site is working properly.

Install the required packages for Optimizely Graph and OG Client

Add the Optimizely Graph Client:

dotnet add package Optimizely.Graph.Client

(Optional) Generate the model classes that will be used:

dotnet ogschema appsettings.json

Add Optimizely.ContentGraph.Cms:

dotnet add package Optimizely.ContentGraph.Cms

Update Startup.cs to use Optimizely Graph and OG Client

Add using:

using EPiServer.DependencyInjection;
using EPiServer.ContentGraph.Extensions;

Update constructor to handle IConfiguration:

private readonly IConfiguration _configuration;

public Startup(IWebHostEnvironment webHostingEnvironment, IConfiguration configuration)
{
  _webHostingEnvironment = webHostingEnvironment;
   _configuration = configuration;
 }

In ConfigureServices method add:

        services.ConfigureContentApiOptions(o =>
        {
            o.IncludeInternalContentRoots = true;
            o.IncludeSiteHosts = true;
            o.EnablePreviewFeatures = true;
            o.SetValidateTemplateForContentUrl(true);
        });
        services.AddContentDeliveryApi(); // required, for further configurations, please visit: https://docs.developers.optimizely.com/content-cloud/v1.5.0-content-delivery-api/docs/configuration
        services.AddContentGraph();
        services.AddContentGraphClient(); //use graph client

Update search functionality in Alloy

In Alloy, use Optimizely Graph in the search controller.

Update SearchPageController in Controller folder to use Optimizely query

using AlloyMvcGraphQL.Models.Pages;
using AlloyMvcGraphQL.Models.ViewModels;
using EPiServer.ContentGraph.Extensions;
using EPiServer.ContentGraph.Api;
using Microsoft.AspNetCore.Mvc;
using EPiServer.ContentGraph.Api.Querying;
using GraphModels = Optimizely.ContentGraph.DataModels;
namespace AlloyMvcGraphQL.Controllers;

public class SearchPageController : PageControllerBase<SearchPage>
{
    private readonly GraphQueryBuilder _contentGraphClient;
    private static Lazy<LocaleSerializer> _lazyLocaleSerializer = new Lazy<LocaleSerializer>(() => new LocaleSerializer());

    public SearchPageController(GraphQueryBuilder contentGraphClient)
    {
        _contentGraphClient = contentGraphClient;
    }

    public ViewResult Index(SearchPage currentPage, string q)
    {
        var searchHits = new List<SearchContentModel.SearchHit>();
        var total = 0;
				var facets = new List<SearchContentModel.SearchFacet>();
        if (q != null)
        {
            var locale = _lazyLocaleSerializer.Value.Parse(currentPage.Language.TwoLetterISOLanguageName.ToUpper());

            var result = _contentGraphClient
            .OperationName("Alloy_Sample_Query")
            .ForType<ProxyModels.SitePageData>()
            .Fields(_=>_.Name, _=>_.Url, _=> _.MetaDescription)
            .Facet(_=>_.ContentType)
            .Total()
            .GetResultAsync<ProxyModels.SitePageData>().Result;
            
            var searchWords = q.Split(" ");
            foreach (var item in result.Content.Hits)
            {
                searchHits.Add(new SearchContentModel.SearchHit()
                {
                    Title = item.Name,
                    Url = item.Url,
                    Excerpt = item.MetaDescription.Length <= 500 ? item.MetaDescription : item.MetaDescription.Substring(0,500);
                });
            }
            facets = result.Content.Facets["ContentType"].Select(x=> new SearchContentModel.SearchFacet { 
                    Name = x.Name,
                    Count = x.Count
                });
            total = result.Content.Total;
        }

        var model = new SearchContentModel(currentPage)
        {
            Hits = searchHits,
            NumberOfHits = total,
            Facets = facets,
            SearchedQuery = q
        };

        return View(model);
    }

Go to to the search page and try it out

Start the site

dotnet run

Start the site, open your browser, and go to https://localhost:5000/en/search