Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
This isn't the latest version of this article. For the current release, see the .NET 9 version of this article.
Important
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 9 version of this article.
This article provides guidance for component library authors considering support for static server-side rendering (static SSR).
Blazor encourages the development of an ecosystem of open-source and commercial component libraries, formally called Razor class libraries (RCLs). Developers might also create reusable components for sharing components privately across apps within their own companies. Ideally, components are developed for compatibility with as many hosting models and rendering modes as possible. Static SSR introduces additional restrictions that can be more challenging to support than interactive rendering modes.
Static SSR is a mode in which components run when the server handles an incoming HTTP request. Blazor renders the component as HTML, which is included in the response. Once the response is sent, the server-side component and renderer state is discarded, so all that remains is HTML in the browser.
The benefit of this mode is cheaper, more scalable hosting, because no ongoing server resources are required to hold component state, no ongoing connection must be maintained between browser and server, and no WebAssembly payload is required in the browser.
All existing components can still be used with static SSR. However, the cost of this mode is that event handlers, such as @onclick
†, can't be run for the following reasons:
†There's a special exception for the @onsubmit
event handler for forms, which is always functional, regardless of render mode.
This is equivalent to how components behave during prerendering, before Blazor's SignalR circuit or the .NET WebAssembly runtime is started.
For components whose only role is to produce read-only DOM content, these behaviors for static SSR are completely sufficient. However, library authors must consider what approach to take when including interactive components in their libraries.
There are three main approaches:
Don't use interactive behaviors (Basic)
For components whose only role is to produce read-only DOM content, the developer isn't required to take any special action. These components naturally work with any render mode.
Examples:
<video>
element, making it more convenient to use in a Razor component.Require interactive rendering (Basic)
You can choose to require that your component is only used with interactive rendering. This limits the applicability of your component, but means that you may freely rely on arbitrary event handlers. Even then, you should still avoid declaring a specific @rendermode
and permit the app author who consumes your library to select one.
Examples:
Use interactive behaviors, but design for static SSR and progressive enhancement (Advanced)
Many interactive behaviors can be implemented using only HTML capabilities. With a good understanding of HTML and CSS, you can often produce a useful baseline of functionality that works with static SSR. You can still declare event handlers that implement more advanced, optional behaviors, which only work in interactive render modes.
Examples:
<a>
links). When used with interactive rendering, the component may add live sorting and filtering.<a>
links and state is held only in URL query parameters, the component can work without @onclick
.<input type=file>
. When used with interactive rendering, the component could also display upload progress.For any of these strategies, there's also the option of implementing interactive features with JavaScript.
To choose among these approaches, reusable Razor component authors must make a cost/benefit tradeoff. Your component is more useful and has a broader potential user base if it supports all render modes, including static SSR. However, it takes more work to design and implement a component that supports and takes best advantage of each render mode.
In most cases, reusable component authors should not specify a render mode, even when interactivity is required. This is because the component author doesn't know whether the app enables support for InteractiveServer, InteractiveWebAssembly, or both with InteractiveAuto. By not specifying a @rendermode
, the component author leaves the choice to the app developer.
Even if the component author thinks that interactivity is required, there may still be cases where an app author considers it sufficient to use static SSR alone. For example, a map component with drag and zoom interactivity may seem to require interactivity. However, some scenarios may only call for rendering a static map image and avoiding drag/zoom features.
The only reason why a reusable component author should use the @rendermode
directive on their component is if the implementation is fundamentally coupled to one specific render mode and would certainly cause an error if used in a different mode. Consider a component with a core purpose of interacting directly with the host OS using Windows or Linux-specific APIs. It might be impossible to use such a component on WebAssembly. If so, it's reasonable to declare @rendermode InteractiveServer
for the component.
Reusable Razor components are free to declare @attribute [StreamRendering]
for streaming rendering ([StreamRendering]
attribute API). This results in incremental UI updates during static SSR. Since the same data-loading patterns produce incremental UI updates during interactive rendering, regardless of the presence of the [StreamRendering]
attribute, the component can behave correctly in all cases. Even in cases where streaming static SSR is suppressed on the server, the component still renders its correct final state.
Reusable Razor components may use links and enhanced navigation. HTML <a>
tags should produce equivalent behaviors with or without an interactive Router component and whether or not enhanced navigation is enabled/disabled at an ancestor level in the DOM.
Reusable Razor components may include forms (either <form>
or <EditForm>
), as these can be implemented to work equivalently across both static and interactive render modes.
Consider the following example:
<EditForm Enhance FormName="NewProduct" Model="Model" OnValidSubmit="Save">
<DataAnnotationsValidator />
<ValidationSummary />
<p><label>Name: <InputText @bind-Value="Model!.Name" /></label></p>
<button type="submit">Submit</button>
</EditForm>
@code {
[SupplyParameterFromForm]
private Product? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
private async Task Save()
{
...
}
}
The Enhance, FormName, and SupplyParameterFromFormAttribute APIs are only used during static SSR and are ignored during interactive rendering. The form works correctly during both interactive and static SSR.
HttpContext is only available during static SSR, so don't rely on HttpContext when creating components that work across render modes. The HttpContext API doesn't make sense to use during interactive rendering either because there's no active HTTP request in flight at those times. It's meaningless to think about setting a HTTP status code or writing to the HTTP response.
Reusable components are free to receive an HttpContext when available, as follows:
[CascadingParameter]
public HttpContext? Context { get; set; }
The value is null
during interactive rendering and is only set during static SSR.
In many cases, there are better alternatives than using HttpContext. If you need to know the current URL or to perform a redirection, the APIs on NavigationManager work with all render modes. If you need to know the user's authentication state, use Blazor's AuthenticationStateProvider service (AuthenticationStateProvider
documentation) over using HttpContext.User.
ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback:
Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreTraining
Module
Render API responses in ASP.NET Core Blazor Web apps - Training
Render API responses in ASP.NET Core Blazor Web apps