Blazor Integration with ASP.NET Core
15 questions found
How does Blazor integrate with ASP.NET Core's hosting model, and what are the two primary interactive render modes?
Beginner
Blazor runs on top of the same ASP.NET Core hosting infrastructure (Kestrel, middleware pipeline, DI container) as any other ASP.NET Core app. Interactive Server mode executes component logic on the server, communicating UI updates to the browser over a persistent SignalR connection; Interactive WebAssembly mode downloads the .NET runtime to the browser and executes component logic entirely client-side, with no ongoing server connection required for UI interactivity.
// Program.cs
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode();
Real-world example
An internal admin dashboard chooses Interactive Server mode for its fast initial load and simpler debugging on a reliable corporate network, while a public marketing site with occasional interactive widgets uses WebAssembly for those specific components.
Common follow-ups: What is the newer Interactive Auto render mode, and how does it combine both approaches?;How does Blazor share the same middleware pipeline as MVC controllers in the same app?
ASP.NET Core Middleware & Request Pipeline;SignalR & Real-Time Communication
How do you mix Blazor components with traditional MVC controllers and Razor Pages within the same ASP.NET Core application?
Intermediate
Since .NET 8's unified hosting model, a single ASP.NET Core project can register both MapControllers()/MapRazorPages() and MapRazorComponents<App>() in the same Program.cs, letting traditional server-rendered pages and interactive Blazor components coexist -- useful for incrementally adopting Blazor within an existing MVC application, or exposing both a JSON API (via controllers) and an interactive UI (via Blazor) from one codebase.
var app = builder.Build();
app.MapControllers(); // traditional REST API endpoints
app.MapRazorPages(); // traditional server-rendered pages
app.MapRazorComponents<App>() // Blazor interactive components
.AddInteractiveServerRenderMode();
Real-world example
A team incrementally migrates a legacy MVC application to Blazor by adding new features as interactive Blazor components while leaving existing, stable MVC controllers and views entirely untouched within the same running application.
Common follow-ups: What routing conflicts can arise between MVC routes and Blazor component routes?;How do you share layout/authentication state consistently across both UI paradigms?
Controllers vs Minimal APIs;Authentication
How does dependency injection work identically for both Blazor components and MVC controllers, given they're both hosted in the same ASP.NET Core DI container?
Advanced
Both consume the exact same IServiceCollection registrations from Program.cs -- a service registered once via AddScoped/AddSingleton/AddTransient is resolvable both in an MVC controller's constructor and a Blazor component's @inject directive, since both ultimately resolve from the same underlying DI container, though the practical meaning of 'Scoped' differs (per-HTTP-request for MVC, per-user-circuit for Blazor Server, or effectively per-app-instance for Blazor WebAssembly).
// Registered once, used in both paradigms
builder.Services.AddScoped<IProductService, ProductService>();
// MVC controller
public class ProductsController(IProductService service) : ControllerBase { }
// Blazor component
@inject IProductService ProductService
Real-world example
A shared IProductService is injected identically into both a legacy MVC controller serving a JSON API and a new Blazor component rendering an interactive product list, with both consuming the exact same business logic without duplication.
Common follow-ups: How does Scoped lifetime differ in practical meaning between MVC requests and Blazor Server circuits?;What happens if a service assumes HTTP request-scoped behavior but is used in Blazor Server?
Dependency Injection;RESTful Web APIs & Controllers
How does authentication state flow from ASP.NET Core's cookie/JWT authentication into a Blazor component via AuthenticationStateProvider?
Intermediate
AuthenticationStateProvider is the abstraction Blazor components use (via the <AuthorizeView> component or @attribute [Authorize]) to access the current user's authentication state -- for Blazor Server, this integrates directly with the same HttpContext.User established by ASP.NET Core's standard authentication middleware during the initial page request; for Blazor WebAssembly, a custom AuthenticationStateProvider typically manages a token stored client-side since there's no persistent server-side HttpContext to rely on.
@page "/profile"
@attribute [Authorize]
<AuthorizeView>
<Authorized>
<p>Welcome, @context.User.Identity.Name</p>
</Authorized>
<NotAuthorized>
<p>Please log in.</p>
</NotAuthorized>
</AuthorizeView>
Real-world example
A Blazor Server admin page uses [Authorize(Roles="Admin")] at the component level, seamlessly reusing the exact same cookie-based identity already established by ASP.NET Core Identity for the rest of the application's MVC pages.
Common follow-ups: How does a custom AuthenticationStateProvider work differently for Blazor WebAssembly's token-based auth?;How do you access the current user's claims imperatively inside a component's code?
Authentication;Authorization
How does Blazor Server's SignalR-based interactivity affect load balancing and horizontal scaling decisions for an ASP.NET Core deployment?
Advanced
Since a Blazor Server circuit maintains persistent server-side state tied to one specific server instance via its SignalR connection, load balancers must be configured for sticky sessions (routing all of a user's requests to the same server instance for the circuit's lifetime), and horizontal scaling requires either sticky-session-aware load balancing or a backplane (like Azure SignalR Service or a Redis-backed SignalR backplane) to allow circuit state to be coordinated across multiple server instances -- a fundamentally different scaling consideration than a typical stateless ASP.NET Core Web API.
// Program.cs: configuring a Redis backplane for SignalR to support Blazor Server scaling
builder.Services.AddSignalR().AddStackExchangeRedis(builder.Configuration.GetConnectionString("Redis"));
// Load balancer configuration (conceptual): enable sticky sessions for the SignalR connection
Real-world example
A Blazor Server application scaling from one to five server instances behind a load balancer requires enabling sticky sessions and adding a Redis-backed SignalR backplane, a deployment complexity that a stateless REST API sibling service never needed to consider.
Common follow-ups: What happens to a user's Blazor Server session if their sticky-session server instance restarts?;How does Blazor WebAssembly avoid this scaling consideration entirely?
SignalR & Real-Time Communication;Caching
How do you call an existing ASP.NET Core minimal API or controller endpoint from a Blazor WebAssembly component using HttpClient?
Intermediate
Blazor WebAssembly components inject a configured HttpClient (registered in Program.cs with a BaseAddress pointing to the hosting API), then call standard HttpClient methods (GetFromJsonAsync, PostAsJsonAsync) just like any other .NET client application would, since WebAssembly components run entirely in the browser and communicate with the backend purely over HTTP, unlike Blazor Server which can directly inject and call backend services in-process.
// Program.cs (Blazor WebAssembly client project)
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
// Component
@inject HttpClient Http
@code {
private Product[]? products;
protected override async Task OnInitializedAsync() {
products = await Http.GetFromJsonAsync<Product[]>("api/products");
}
}
Real-world example
A Blazor WebAssembly storefront fetches its product catalog by calling the same /api/products minimal API endpoint that a separate mobile app also consumes, since WebAssembly components communicate purely over HTTP just like any other API client.
Common follow-ups: Why can't Blazor WebAssembly directly inject and call backend services in-process the way Blazor Server can?;How do you handle CORS if the WebAssembly app is hosted separately from its API?
CORS (Cross-Origin Resource Sharing);Content Negotiation & Output Formatters
How does prerendering work when a Blazor component is embedded within a traditional Razor Pages or MVC view, and what is the purpose of Component Tag Helpers?
Advanced
The <component> tag helper (render-mode="ServerPrerendered" or similar) lets you embed an interactive Blazor component directly within an otherwise traditional server-rendered Razor Page or MVC view, rendering the component's initial HTML on the server as part of the page response (so users see content immediately), then 'hydrating' it into a fully interactive component once the client-side runtime (SignalR connection or WASM) initializes -- letting teams add small pockets of Blazor interactivity to an existing traditional application without a full rewrite.
<!-- Inside a traditional Razor Page (.cshtml) -->
<component type="typeof(WeatherWidget)" render-mode="ServerPrerendered" />
<!-- WeatherWidget.razor renders its initial HTML immediately,
then becomes fully interactive after the SignalR connection establishes -->
Real-world example
A legacy MVC e-commerce site adds a small interactive 'live inventory count' Blazor component embedded within an existing traditional product detail Razor view, incrementally introducing Blazor without rewriting the entire page.
Common follow-ups: What issues can arise if component code isn't safe to run twice (prerender phase and real render phase)?;How does this differ from the newer unified .razor-component-only hosting model in .NET 8+?
ASP.NET Core Middleware & Request Pipeline;Diagnostics & Performance
How do you configure CORS correctly when a Blazor WebAssembly app is hosted on a different origin than its backend API?
Intermediate
Since Blazor WebAssembly runs entirely in the browser, cross-origin calls from the WASM app to a separately-hosted API are subject to the exact same browser CORS restrictions as any other JavaScript-based SPA -- the API must explicitly configure a CORS policy (via AddCors/UseCors) allowing the WebAssembly app's origin, exactly as you would for a React or Angular frontend.
// API's Program.cs
builder.Services.AddCors(options => {
options.AddPolicy("BlazorClient", policy =>
policy.WithOrigins("https://blazor-app.mycompany.com").AllowAnyMethod().AllowAnyHeader());
});
app.UseCors("BlazorClient");
Real-world example
A Blazor WebAssembly app deployed to a static hosting CDN calls a separately-deployed ASP.NET Core API on a different domain, requiring the API to explicitly whitelist the WebAssembly app's origin via standard CORS configuration, identical to any JavaScript SPA integration.
Common follow-ups: Does Blazor Server have the same CORS considerations as WebAssembly?;How does hosting both the API and WASM app from the same ASP.NET Core project avoid this CORS configuration entirely?
CORS (Cross-Origin Resource Sharing);Hosting Models: Kestrel
IIS & Reverse Proxies
How does JS interop in a Blazor component hosted within ASP.NET Core differ in performance characteristics between Server and WebAssembly render modes?
Advanced
In Blazor Server, every IJSRuntime.InvokeAsync call is a real network round-trip over the SignalR connection between browser and server, adding latency proportional to network conditions -- making frequent, chatty JS interop calls a potential bottleneck. In Blazor WebAssembly, JS interop happens entirely in-process within the browser (WASM calling into JS directly), making it dramatically faster since there's no network hop involved, though still not free due to WASM-to-JS marshaling overhead.
// Identical code, very different performance characteristics depending on render mode:
await JS.InvokeVoidAsync("updateChart", chartData);
// Blazor Server: network round-trip over SignalR
// Blazor WebAssembly: in-process, no network latency
Real-world example
A Blazor Server app calling JS interop on every mouse-move event for a drawing feature experiences noticeable lag due to round-trip overhead, prompting the team to switch that specific interactive component to WebAssembly render mode instead.
Common follow-ups: How would you batch multiple JS interop calls to reduce round-trip overhead in Blazor Server?;What is Interactive Auto mode's trade-off regarding this performance difference?
SignalR & Real-Time Communication;Diagnostics & Performance
How do you share validation logic between a Blazor form (using EditForm and DataAnnotationsValidator) and a corresponding ASP.NET Core Web API's model validation?
Intermediate
Since both Blazor's EditForm/DataAnnotationsValidator and ASP.NET Core's [ApiController] automatic model validation read the same System.ComponentModel.DataAnnotations attributes ([Required], [StringLength], [Range]) on a shared DTO/model class, defining validation rules once on a model referenced by both the Blazor client project and the API project (via a shared class library) ensures consistent validation behavior on both the client (immediate UX feedback) and server (authoritative enforcement) without duplicating rules.
// Shared/ProductDto.cs (referenced by both Blazor client and API projects)
public class ProductDto {
[Required, StringLength(100)] public string Name { get; set; }
[Range(0.01, 10000)] public decimal Price { get; set; }
}
<!-- Blazor component -->
<EditForm Model="product" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText @bind-Value="product.Name" />
</EditForm>
Real-world example
A shared ProductDto class in a common library is referenced by both the Blazor WebAssembly client (for instant client-side form validation feedback) and the ASP.NET Core API (for authoritative server-side validation), guaranteeing both layers enforce identical rules.
Common follow-ups: Why must server-side validation still be enforced even with client-side validation in place?;How does this shared-model pattern work when Blazor Server and the API are the same project?
Model Binding & Validation;Content Negotiation & Output Formatters