Skip to content

Pages and Direct Rendering

Mike Christensen edited this page Aug 28, 2026 · 1 revision

Pages and direct rendering

Every routable class derives from BasePage. A page can use an embedded template or override Render to write the entire response itself.

Minimal page

public sealed class Health : BasePage
{
   public override Task Render(HttpResponse response)
   {
      response.ContentType = "text/plain; charset=utf-8";
      return response.WriteAsync("OK");
   }
}

The middleware initially assigns text/html; a direct page may replace the content type and status code.

Request data

After construction, Imp assigns the current HttpRequest to BasePage.Request. It exposes headers, cookies, claims, path, query, form-reading methods, services, and the surrounding HttpContext.

public override Task Render(HttpResponse response)
{
   var user = Request.HttpContext.User;
   // Render using application data and the resolved user.
}

Do not capture Request in singleton services or retain a page object beyond its request.

PreRender

Override PreRender for synchronous preparation that must happen before postback handling and rendering:

public override void PreRender(HttpResponse response)
{
   if (record is null)
      response.StatusCode = StatusCodes.Status404NotFound;
}

PreRender cannot be asynchronous. Load asynchronous data in a dynamic method, a postback, middleware before Imp, or reconsider the service boundary. Avoid blocking on asynchronous work.

Output safety

Direct rendering bypasses a view engine's automatic encoding. Encode all untrusted text:

var title = HtmlEncoder.Default.Encode(model.Title);
await response.WriteAsync($"<h1>{title}</h1>");

Encode according to context: HTML text, HTML attributes, JavaScript, CSS, and URLs have different rules. Prefer structured HTML/template output over concatenating large documents. Sanitize user-authored HTML with a maintained allow-list sanitizer before treating it as markup.

Direct pages versus templates

Direct rendering is appropriate for tiny responses, diagnostics, redirects, or custom fallback pages. Embedded templates are easier to review and compose for normal HTML pages. A page with [PageTemplate] uses the template and does not call its Render override.

Response ownership

Imp writes the response after lifecycle/postback processing. If a page redirects or otherwise completes a response during a postback, remember that Imp will continue into its render stage. Design postbacks to render a result page, or ensure custom behavior is compatible with the remaining pipeline.

Clone this wiki locally