Relatude Help

Deciding per request: selectors

A selector looks at the request before anything else, for every page. The first selector that returns a target wins. Return null to pass the page on:

.AddRendering(o => o
    .Select((http, m) => http.Request.Query["view"] == "print" && m.Content is IArticle ? new RazorViewTarget("ArticlePrint") : null)
    .Select((http, m) => http.Request.Query["format"] == "json" ? new ResultTarget((_, c) => Results.Json(new { c.Content.Name })) : null))

Print views, A/B tests and a theme per site all start here. A selector that needs a service takes it from http.RequestServices.

A selector is also how code overrides a template, and the only way a plain ITemplate renders. It tells templates apart by name or id:

.AddRendering(o => o
    // every page with the template "Campaign": a Blazor component
    .Select((http, m) => m.Template?.Name == "Campaign"
        ? new ResultTarget((_, c) => new RazorComponentResult<CampaignPage>(new { Content = c.Content }))
        : null)
    // per page: a long article gets another view; null leaves the page to its template
    .Select((http, m) => m.Template?.Name == "Article" && m.Content is IArticle { Body.Length: > 20_000 } ? new RazorViewTarget("ArticleLong") : null))

Editors see a template's name and may change it. For a template that always renders the same way, a kind of its own is sturdier, because editors then see what renders it.