Server side rendering of Questions & Answers

Add Server side rendering of Questions & Answers

Register a named HttpClient

Add a named HttpClient in Startup.cs and ConfigureServices(IServiceCollection services) or the equivalent in Program.cs if you have converted to that.

services.AddHttpClient("RekSsrHtml", httpClient =>
    {
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/html"));
        httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("cms-backend-proxy");
        httpClient.DefaultRequestHeaders.Add("Origin", "https://your-domain.example.com");
        httpClient.BaseAddress = new Uri(siteSettings.RekSsrHtmlBaseAddress);
        httpClient.Timeout = TimeSpan.FromSeconds(5);
    })
    .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
    {
        AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli,
        AllowAutoRedirect = false,
        UseCookies = false,
    });

Cache the calls

Please cache these calls for at least 5 minutes. If you want to use FusionCache for that:

services.AddFusionCache();

Fetch the Questions & Answers HTML

Then, when you are creating the response for a page that has content that Rek.ai could have created a Q&A item for.

// Retrieve IFusionCache fusionCache, IHttpContextAccessor httpContext and
// IHttpClientFactory httpClientFactory in the Dependency Injection style your app uses
var path = this.httpContext.HttpContext!.Request.Path.ToString();
var cacheKey = "RekSsrHtml" + path;
 
var ssrHtml = await this.fusionCache.GetOrSetAsync(
    cacheKey,
    async _ =>
    {
        var httpClient = this.httpClientFactory.CreateClient("RekSsrHtml");
 
        // Parameter needs a leading /, but no trailing /
        var subTree = string.Concat("/", path.TrimStart('/')).TrimEnd('/');
 
        var predictionUrl = $"predict?p={siteSettings.RekProjectId}&secret={siteSettings.RekSecretKey}&entitytype=rekai-qna&subtree=^{subTree}$&unranked=true&format=html";
 
        // Optional: Add a h2 element above the questions
        predictionUrl += "&headertext=Your%20heading";
        predictionUrl += "&headerid=id-of-heading";
        predictionUrl += "&headerfontclass=class-of-heading";
        predictionUrl += "&headerheadinglevel=2";
 
        // Optional: Hide answer links
        predictionUrl += $"&hideanswerlinktopageifsamepage=true&currentp={subTree}";
 
        var httpResponseMessage = await httpClient.GetAsync(predictionUrl, httpContext.HttpContext!.RequestAborted);
 
        if (httpResponseMessage.IsSuccessStatusCode)
        {
            return await httpResponseMessage.Content.ReadAsStringAsync(httpContext.HttpContext!.RequestAborted);
        }
 
        return "<!-- Error from Rek.ai HTTP call -->";
    },
    options => options.SetDuration(TimeSpan.FromMinutes(5)));

If Q&A items were found to be sourced from the current page; ssrHtml now contains structured data in a <script type="application/ld+json">-element and a HTML version of the items.

Typically you would copy this to a ViewModel property and use Html.Raw(Model.SsrHtmlPropertyName) in the CSHTML view, making it fully visible to search engines and AI tools.

Add styles and interactivity

If items were found you need to also render this script to get styles and interactivity in place:

<script>
    __rekai.ready(function() {
        var options = {};
        var questionOptions = window.__rekai.getQuestionsOptions();
        questionOptions.serversideRendering = true;
 
        window.__rekai.addCssStylesForQuestions(questionOptions);
        window.__rekai.addEventListenersForQuestions(options, questionOptions);
    });
</script>