Add simpler API for invoking prerendering without using tag helper #1090

Closed
opened 2025-08-09 17:18:50 +00:00 by fergalmoran · 0 comments
Owner

Originally created by @SteveSandersonMS on 1/26/2017

Although the asp-prerender-module tag helper is usually the most convenient and natural way to invoke prerendering, there are some cases where you'd want to do it from controller code, or from a code block in your Razor page. For example, you might want to receive back additional custom data values from prerendering, and then maybe use them to set the page title or similar. Or you might want to change how the globals values are serialized and delivered to the client.

Currently it is possible to do this by invoking Prerenderer.RenderToString directly. However it's inconvenient, because you have to duplicate some non-obvious logic from the tag helper. For example, to run prerendering from controller code, currently you need something like this:

var requestFeature = Request.HttpContext.Features.Get<IHttpRequestFeature>();
var unencodedPathAndQuery = requestFeature.RawTarget;
var unencodedAbsoluteUrl = $"{Request.Scheme}://{Request.Host}{unencodedPathAndQuery}";
var prerenderResult = await Prerenderer.RenderToString(
    hostEnv.ContentRootPath,
    nodeServices,
    new JavaScriptModuleExport("ClientApp/dist/main-server"),
    unencodedAbsoluteUrl,
    unencodedPathAndQuery,
    /* custom data parameter */ null,
    /* timeout milliseconds */ 15*1000,
    Request.PathBase.ToString()
);

ViewData["SpaHtml"] = prerenderResult.Html;
ViewData["Title"] = prerenderResult.Globals["pageTitle"];

We should consider migrating this logic out of PrerenderTagHelper and into some new DI service class that PrerenderTagHelper starts using. Then developers will be able to grab instances of that new service class and do custom prerendering much more easily. Ideally, you'd be able to do something like this directly in a Razor view:

@inject Microsoft.AspNetCore.SpaServices.Prerendering.IPrerenderer prerenderer
@{
    var prerenderResult = await prerenderer.RenderToString("ClientApp/dist/main-server");
}
...
<title>@prerenderResult.Globals["pageTitle"]</title>
<app>@Html.Raw(prerenderResult.Html)</app>

There could be an options param for overriding things like the request URL, timeout, etc., but by default it would use values from the context automatically like asp-prerender-module already does.

*Originally created by @SteveSandersonMS on 1/26/2017* Although the `asp-prerender-module` tag helper is usually the most convenient and natural way to invoke prerendering, there are some cases where you'd want to do it from controller code, or from a code block in your Razor page. For example, you might want to receive back additional custom data values from prerendering, and then maybe use them to set the page title or similar. Or you might want to change how the `globals` values are serialized and delivered to the client. Currently it is possible to do this by invoking `Prerenderer.RenderToString` directly. However it's inconvenient, because you have to duplicate some non-obvious logic from the tag helper. For example, to run prerendering from controller code, currently you need something like this: ```csharp var requestFeature = Request.HttpContext.Features.Get<IHttpRequestFeature>(); var unencodedPathAndQuery = requestFeature.RawTarget; var unencodedAbsoluteUrl = $"{Request.Scheme}://{Request.Host}{unencodedPathAndQuery}"; var prerenderResult = await Prerenderer.RenderToString( hostEnv.ContentRootPath, nodeServices, new JavaScriptModuleExport("ClientApp/dist/main-server"), unencodedAbsoluteUrl, unencodedPathAndQuery, /* custom data parameter */ null, /* timeout milliseconds */ 15*1000, Request.PathBase.ToString() ); ViewData["SpaHtml"] = prerenderResult.Html; ViewData["Title"] = prerenderResult.Globals["pageTitle"]; ``` We should consider migrating this logic out of `PrerenderTagHelper` and into some new DI service class that `PrerenderTagHelper` starts using. Then developers will be able to grab instances of that new service class and do custom prerendering much more easily. Ideally, you'd be able to do something like this directly in a Razor view: ```csharp @inject Microsoft.AspNetCore.SpaServices.Prerendering.IPrerenderer prerenderer @{ var prerenderResult = await prerenderer.RenderToString("ClientApp/dist/main-server"); } ... <title>@prerenderResult.Globals["pageTitle"]</title> <app>@Html.Raw(prerenderResult.Html)</app> ``` There could be an options param for overriding things like the request URL, timeout, etc., but by default it would use values from the context automatically like `asp-prerender-module` already does.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/JavaScriptServices#1090
No description provided.