Blazor Interview Prep

Blazor Interview Questions and Answers (2026)

Blazor interview questions usually center on one core decision — Server vs WebAssembly — and how that choice ripples through everything else: component lifecycle, dependency injection scope, and how state and JS interop behave differently under each hosting model. Here are the ones that come up most.

  1. What's the difference between Blazor Server and Blazor WebAssembly?

    Blazor Server runs your component code entirely on the server; the browser holds a thin client that renders a DOM diff sent over a persistent SignalR connection, and every UI interaction is sent back to the server over that connection for processing. Blazor WebAssembly downloads the compiled .NET runtime and your app's assemblies to the browser via WebAssembly, then runs entirely client-side with no ongoing server dependency for UI logic. Server offers fast initial load, full .NET/server-resource access, and small download size, but requires a constant low-latency connection and doesn't scale per-server as well since server memory is held per active circuit. WebAssembly offers offline capability and reduced server load after initial download, but has a heavier initial payload and, historically, slower cold-start due to runtime download and JIT/interpreter execution (mitigated by AOT compilation).

  2. What are the Blazor component lifecycle methods, and in what order do they run?

    On initial render: the constructor runs, parameters are set (SetParametersAsync), then OnInitialized/OnInitializedAsync runs once, followed by OnParametersSet/OnParametersSetAsync, then the component renders (BuildRenderTree), and finally OnAfterRender/OnAfterRenderAsync runs after the component's markup is added to the DOM (useful for JS interop that needs the actual rendered elements). On subsequent updates (e.g., a parent re-renders and passes new parameters), only OnParametersSet(Async) and the render/OnAfterRender steps re-run — OnInitialized never runs again for the same component instance. OnAfterRender receives a firstRender boolean so you can run one-time DOM-dependent setup (like initializing a JS chart library) only once.

  3. How does `@bind` work in Blazor, and how do you customize it?

    @bind is compiler sugar that expands to both a value assignment and a change event handler — <input @bind="Name" /> on a text input expands roughly to setting value from Name and wiring onchange to update Name. By default it uses onchange (fires on blur/Enter), but you can specify @bind:event="oninput" to update on every keystroke instead. @bind:format lets you specify a display format for values like dates. For custom components, you implement two-way binding by exposing a Value parameter plus a matching ValueChanged EventCallback<T> (and typically a ValueExpression for validation support), following Blazor's naming convention so @bind-Value="SomeProp" works on your own components exactly like built-in ones.

    <input @bind="Name" @bind:event="oninput" />
    @code { private string Name = ""; }
  4. What's the difference between `[Parameter]` and `[CascadingParameter]`?

    [Parameter] properties are set explicitly by a parent component passing values through attributes in markup (<ChildComponent Title="Hello" />), requiring every intermediate component in the tree to pass the value down manually if a deeply nested descendant needs it. [CascadingParameter] receives a value from the nearest ancestor <CascadingValue> in the render tree automatically, without every intermediate component needing to know about or re-declare it — useful for cross-cutting concerns like theme, current user/auth state, or a shared form's EditContext. Cascading parameters trade explicitness for convenience: they make data flow implicit and can be harder to trace, so they're best reserved for genuinely cross-cutting values rather than as a general substitute for normal parameter passing.

  5. How does dependency injection work in Blazor, and are lifetimes the same as ASP.NET Core?

    Services are registered the same way, via builder.Services.AddScoped/AddSingleton/AddTransient in Program.cs, and injected into components with @inject IMyService MyService (which is sugar for a property with [Inject]). The lifetime semantics differ subtly by hosting model: in Blazor Server, a "scope" corresponds to a user's SignalR circuit (roughly, one browser tab session) rather than one HTTP request, so a scoped service persists for the whole duration that circuit is connected — much longer-lived than a typical ASP.NET Core scoped request. In Blazor WebAssembly, everything effectively runs in a single client-side scope since there's no server request boundary, so scoped and singleton behave almost identically within one browser session. This distinction matters for state leakage — a "scoped" service in Blazor Server can inadvertently hold state across many user interactions within a session.

  6. What is JS interop, and how do you call JavaScript from Blazor (and vice versa)?

    JS interop lets Blazor call JavaScript functions and JavaScript call back into .NET, necessary for browser APIs Blazor doesn't wrap (localStorage, canvas, third-party JS libraries, file downloads). You inject IJSRuntime and call InvokeAsync<T>("functionName", args) to invoke a JS function defined in a loaded script. For JS-to-.NET calls, you pass a DotNetObjectReference wrapping a component instance, and JS calls back via DotNet.invokeMethodAsync, targeting a .NET method marked [JSInvokable]. Blazor WebAssembly also supports synchronous JS interop (IJSInProcessRuntime) since there's no network round-trip, whereas Blazor Server calls are always asynchronous since they cross the SignalR connection. Excess JS interop calls in Blazor Server can hurt performance due to per-call network latency, so batching/minimizing round-trips matters more there than in WASM.

    await JSRuntime.InvokeVoidAsync("console.log", "Hello from Blazor");
  7. What is `EventCallback`, and why does Blazor prefer it over plain delegates for component events?

    EventCallback (and EventCallback<T>) is Blazor's wrapper for exposing component "events" as parameters that a parent can bind a handler to (<Child OnSave="HandleSave" />), used instead of raw Action/EventHandler delegates because it integrates with Blazor's rendering system — invoking an EventCallback automatically triggers a re-render of the component that owns the handler (and correctly propagates exceptions and async completion), which a plain delegate invocation wouldn't reliably do without manual StateHasChanged() calls. It also supports async handlers naturally (EventCallback wraps a Task-returning delegate), so a parent's async Task HandleSave() method just works when invoked by the child, with the child able to await the whole handler's completion if needed.

    [Parameter] public EventCallback<string> OnSave { get; set; }
    private async Task Submit() => await OnSave.InvokeAsync(Name);
  8. What is a `RenderFragment`, and how do child content and templated components use it?

    RenderFragment is a delegate type representing a chunk of UI markup that can be passed around and rendered later, essentially Blazor's version of a "UI as a value" — it's what backs ChildContent, the implicit parameter that captures whatever markup is nested inside a component's tags (<MyCard>Some content</MyCard>). RenderFragment<T> is a generic version that takes a context parameter, enabling templated components where the parent supplies a template referencing data the child provides — e.g., a generic <Grid> component exposing a RowTemplate parameter of type RenderFragment<RowData> so each consumer customizes row rendering while the grid controls iteration. This is how components like built-in <AuthorizeView> (with Authorized/NotAuthorized templates) or custom generic list/grid components let the caller inject arbitrary markup parameterized by runtime data.

  9. What are the common approaches to state management in Blazor?

    For state scoped to a single component tree, cascading parameters or simply passing state down via normal parameters suffices. For state shared across otherwise-unrelated components (e.g., a shopping cart accessible from header and page components), a common pattern is a scoped or singleton injectable "state container" service that raises a StateChanged/OnChange event, which subscribing components handle by calling StateHasChanged(). For persisting state across page navigations or reloads, options include browser storage via JS interop (localStorage/sessionStorage), or in Blazor Server, keeping it server-side in the scoped DI container tied to the circuit. Larger apps sometimes adopt Flux/Redux-style libraries (e.g., Fluxor) for more structured, predictable state updates, though a simple injectable state service is sufficient for most line-of-business apps.

  10. What role does SignalR play in Blazor Server?

    Blazor Server uses a persistent SignalR connection (typically WebSockets, falling back to Server-Sent Events or long polling) as the transport between the browser and server: user interactions (clicks, input) are serialized and sent to the server, the server re-executes the relevant component logic against its in-memory render tree, computes a UI diff, and sends that diff back to the browser's lightweight JS client to patch the real DOM — no full page reload and minimal data transferred (just the diff, not full HTML). This is why Blazor Server requires a stable, low-latency connection to feel responsive, and why connection loss (e.g., a mobile client on a flaky network) visibly disrupts the app until it reconnects, potentially losing in-memory circuit state if the reconnect window expires.

  11. How does routing work in Blazor?

    Routable components declare their own routes via the @page directive at the top of the component (@page "/products/{id:int}"), and the Router component in App.razor scans the specified assembly for all components with @page directives to build the route table at app startup, matching the current URL against them client-side (no full server round-trip per navigation, even in Blazor Server). Route parameters are captured into component parameters matching the route segment names, optionally with type constraints ({id:int}). Navigation between routable components is handled by NavigationManager.NavigateTo(...) or <NavLink> (which also applies an "active" CSS class automatically), and since routing is handled client-side by the Blazor runtime, navigating between Blazor pages doesn't trigger a full browser page reload, preserving app/circuit state where applicable.

  12. What are the key performance considerations for choosing between Blazor hosting models?

    Blazor Server has near-instant initial load (just a small bootstrap script, not the whole runtime) but each UI interaction incurs network round-trip latency and consumes server memory/CPU per active circuit, which limits how many concurrent users a given server can comfortably host and makes it unsuitable for high-latency or offline scenarios. Blazor WebAssembly has a larger initial download (the .NET runtime plus app assemblies, though trimming and Brotli compression mitigate this, and .NET 8+ supports AOT compilation for near-native execution speed at the cost of larger payload) but then runs entirely client-side with no per-interaction server round-trip and no per-user server resource cost, scaling better for large concurrent audiences. A newer hybrid, "Blazor United"/render-mode-per-component in .NET 8+, lets you mix server-side rendering, static SSR, and interactive Server/WebAssembly per component, letting you choose the right tradeoff granularly rather than app-wide.

Practicing for a real interview? Get live AI help with your answers, in the browser, free to start.

Start a free session