Blazor Auto Mode + Vertical Slices: The New Full-Stack Standard in .NET 10

Why Blazor Auto Mode Changes Everything

Read this article on Medium.

Blazor Auto Mode represents a major shift in how full-stack .NET applications are built. Instead of choosing between Server-Side Rendering (SSR) or WebAssembly (WASM), Auto Mode starts with SSR for fast initial load and SEO, then seamlessly hands off to WASM for rich client-side interactivity. The result is a best-of-both-worlds experience — but only if your architecture can support it.

This flexibility also exposes a hard truth: most Blazor applications are not structured to survive multiple hosting models. UI logic becomes duplicated, data-loading strategies diverge, and components quietly accumulate hosting-specific assumptions. Auto Mode doesn’t create these problems — it reveals them.

This is where Vertical Slice Architecture becomes essential. By organizing code around features instead of layers, vertical slices make it possible to build one UI, one feature, one flow that works consistently across SSR and WASM. In .NET 10, this combination isn’t just powerful — it’s the new full-stack standard.

What Actually Happens in Blazor Auto Mode

At runtime, Blazor Auto Mode follows a clear but often misunderstood lifecycle.

When a request hits the server:

  1. The page is rendered using SSR
  2. HTML is streamed to the browser immediately
  3. The application becomes visible and usable before WASM is loaded

Behind the scenes:

  • The WebAssembly payload downloads asynchronously
  • Components hydrate incrementally
  • Interactivity transitions to WASM without a page reload

Conceptually, the flow looks like this:

Request → SSR → Streamed HTML → Partial Hydration → WASM Interactivity

What’s important is what doesn’t change:

  • Routing remains the same
  • Razor components are the same
  • Dependency injection still applies
  • Business logic doesn’t move

Auto Mode is not two applications — it’s one application that changes how it executes. If your architecture assumes a single execution model, problems start to surface immediately.

The Architectural Problem Auto Mode Exposes

Blazor Auto Mode is unforgiving to weak architecture.

Common issues appear quickly:

  • Conditional UI logic for SSR vs WASM
  • Duplicate data-fetching paths
  • Components that behave differently depending on hosting
  • Business logic leaking into the UI layer

These patterns often worked by accident when applications targeted a single hosting model. Auto Mode removes that safety net.

The core issue is not Blazor — it’s layer-based architecture. When controllers, services, repositories, and UI are separated by technical concerns instead of feature boundaries, it becomes difficult to reason about how a single piece of functionality behaves end-to-end.

Vertical Slice Architecture flips that model. Each feature owns:

  • Its UI
  • Its data contracts
  • Its behavior
  • Its execution flow

This makes the feature hosting-agnostic. Whether the UI is rendered via SSR, hydrated into WASM, or updated via SignalR becomes an implementation detail — not an architectural concern.

Auto Mode doesn’t require a new way of writing UI — it requires a better way of organizing code.

Why Vertical Slices Fit Blazor Auto Mode Perfectly

Blazor Auto Mode works best when features are self-contained and execution-agnostic. Vertical Slice Architecture provides exactly that.

In a traditional layered design, the UI depends on services, services depend on repositories, and behavior is scattered across the solution. This structure assumes a single execution model. When Auto Mode introduces SSR-first rendering followed by WASM hydration, those assumptions break down, forcing developers to introduce conditional logic and duplicate data-loading paths.

Vertical slices reverse the dependency flow.

Each slice represents a complete feature, containing:

  • The UI
  • The request or command
  • The handler
  • Data access
  • Mapping and validation

Because all behavior is localized, the slice does not care how it is executed — only what it does.

From Auto Mode’s perspective, this is ideal:

  • SSR can render the UI immediately
  • WASM can hydrate and continue execution
  • SignalR can push updates
  • The same handler and DTOs are reused in every case

No branching. No hosting checks. No duplicated logic.

Feature Ownership Instead of Layer Ownership

Vertical slices shift ownership from technical layers to features.

Instead of asking: “Which service does this belong to?”

You ask: “Which feature owns this behavior?”

This matters in Auto Mode because:

  • UI and behavior evolve together
  • Data contracts remain stable across hosting models
  • Changes to one feature don’t ripple across unrelated areas

A feature becomes a unit of reasoning, not just a unit of deployment.

Hosting-Agnostic by Design

Auto Mode doesn’t require components to know whether they’re running on the server or in the browser. Vertical slices embrace this by keeping hosting concerns at the edges.

The slice core:

  • Contains no SSR-specific logic
  • Contains no WASM-specific logic
  • Does not depend on HttpContext or browser APIs

Only the entry point changes:

  • SSR may call the handler directly
  • WASM may call the same handler through an endpoint

The slice remains unchanged.

Key Insight: Auto Mode works when features don’t care where they run.

One UI, One Flow, One Mental Model

Perhaps the biggest advantage of combining Auto Mode with vertical slices is cognitive simplicity.

There is:

  • One Razor page
  • One command or query
  • One handler
  • One result

That flow works:

  • On first render
  • After hydration
  • During real-time updates
  • Across future hosting changes

As Blazor continues to evolve, this architecture absorbs change instead of reacting to it.

Why This Matters in .NET 10

.NET 10 pushes Blazor further toward:

  • Streaming rendering
  • Partial hydration
  • Real-time interactivity
  • Hybrid execution models

Vertical slices align with this direction naturally. They encourage:

  • Feature-level thinking
  • Clear boundaries
  • Long-term maintainability

Auto Mode isn’t just a rendering feature — it’s a forcing function for better architecture. Vertical Slice Architecture is how you meet that challenge head-on.

Slice Structure That Works in Both SSR and WASM

If Blazor Auto Mode is the execution model, vertical slices are the organizational model. To support both SSR and WASM cleanly, a slice must be structured so that nothing inside it assumes where it’s running.

The goal is simple: one feature, one flow, one structure.

The Core Rule

A slice should not know whether it is being executed on the server or in the browser.

This rule drives every structural decision.

A Hosting-Agnostic Slice Layout

A well-structured slice groups everything required to deliver a feature in one place:

Features/
Orders/
CreateOrder/
CreateOrderPage.razor
CreateOrderCommand.cs
CreateOrderHandler.cs
CreateOrderEndpoint.cs
OrderDto.cs
Mapping.cs

Each file has a single responsibility:

  • Page: Displays the UI and captures user intent
  • Command: Represents the action being taken
  • Handler: Contains business logic
  • Endpoint: Exposes the slice to WASM clients
  • DTOs: Define shared contracts
  • Mapping: Translates between entities and DTOs

Nothing here is SSR-specific or WASM-specific.

UI Lives With the Feature

The Razor page belongs in the slice.

This avoids:

  • Centralized “Pages” folders
  • Feature logic spread across the solution
  • UI components drifting away from their behavior

In Auto Mode, this matters because:

  • SSR renders the page immediately
  • WASM hydrates the same component
  • The UI remains consistent throughout

There is no second UI and no alternate rendering path.

Handlers Are the Slice’s Center of Gravity

The handler is where behavior lives.

Whether the UI:

  • Calls the handler directly (SSR), or
  • Calls it through an API endpoint (WASM),

The logic remains identical.

This eliminates:

  • Duplicate service methods
  • Conditional data-loading code
  • UI-level business logic

The slice becomes execution-agnostic by design.

Endpoints Are Just Adapters

Endpoints exist for one reason: to bridge WASM to the slice.

They should:

  • Be thin
  • Translate input into commands or queries
  • Return results or status codes

They should not contain business logic.

In SSR, endpoints may not even be used — and that’s fine. The slice still functions.

Shared Contracts Make the UI Portable

DTOs used by the UI belong in a shared location referenced by:

  • The server
  • The WASM client
  • The Blazor UI

This guarantees:

  • Strong typing
  • Compile-time safety
  • No drift between client and server

Auto Mode thrives on this alignment.

Why This Structure Scales

This slice structure:

  • Supports SSRWASM, and future hosting models
  • Encourages feature ownership
  • Makes testing straightforward
  • Keeps complexity localized

Most importantly, it allows Auto Mode to do what it does best — change execution without changing architecture.

Building the UI Once (Auto Mode Friendly)

One of the biggest promises of Blazor Auto Mode is a single UI that works everywhere. The mistake many teams make is trying to help Auto Mode by adding conditional logic for SSR and WASM. In practice, this does the opposite.

The correct approach is simpler: build the UI once and let the architecture do the work.

The Rule: No Hosting Checks in UI

An Auto Mode–friendly UI:

  • Does not check whether it’s running on the server or client
  • Does not branch based on rendering mode
  • Does not contain business logic
  • Expresses intent, not execution

If a component needs to know how it’s running, something else is leaking into the UI.

A Slice-Owned Page

Because the page lives inside the slice, it naturally aligns with the feature it represents:

@page "/orders/create"

<EditForm Model="model" OnValidSubmit="Submit">
<InputText @bind-Value="model.Product" />
<InputNumber @bind-Value="model.Quantity" />
<button type="submit">Create Order</button>
</EditForm>

@if (result is not null)
{
<p>Order created successfully.</p>
}

This page does one thing: capture user intent.

It doesn’t know:

  • Where the data is saved
  • How validation works
  • Whether it’s SSR or WASM

And it doesn’t need to.

UI Talks to the Slice, Not the Stack

The code-behind communicates with the slice through a single abstraction:

@code {
private CreateOrderModel model = new();
private OrderResult? result;

private async Task Submit()
{
result = await orderClient.Create(model);
}
}

That client may:

  • Call a handler directly (SSR)
  • Call an endpoint (WASM)

The UI doesn’t care.

This separation is what allows Auto Mode to seamlessly hand off execution without breaking behavior.

Why This Works with Streaming and Hydration

Because the UI:

  • Is declarative
  • Has no hosting branches
  • Depends only on DTOs and results

Blazor can:

  • Stream the page immediately
  • Hydrate components incrementally
  • Transition interactivity to WASM

Without rerunning logic or duplicating state.

The UI becomes renderable at any time, in any mode.

Avoiding the Common Anti-Patterns

Auto Mode exposes bad habits quickly. Avoid:

  • Calling EF or DbContext from UI
  • Injecting HttpClient directly into every page
  • Switching behavior based on OperatingSystem.IsBrowser()
  • Reimplementing logic for WASM

If your UI is doing more than expressing intent and rendering results, the slice boundary has been crossed.

Why This Matters

When the UI is written once:

  • SSR becomes fast and predictable
  • WASM hydration becomes seamless
  • Real-time updates are easier
  • Testing becomes simpler

Most importantly, your application gains architectural stability in the face of new Blazor capabilities.

Commands, Not Controllers: The Slice Core

Blazor Auto Mode works best when features are expressed as intent, not endpoints. This is why commands and queries sit at the heart of a vertical slice, while controllers quietly fade into the background.

In a slice-based system, controllers are optional. Commands are not.

Why Controllers Break Down in Auto Mode

Traditional controllers tend to:

  • Mix HTTP concerns with business logic
  • Encourage shared “service” layers
  • Push behavior away from the feature that owns it

This isn’t a problem when you only have one execution model. Auto Mode changes that.

When UI can execute:

  • Directly on the server (SSR)
  • Through an endpoint (WASM)
  • Via real-time events (SignalR)

The controller stops being the center of gravity.

Commands Express Intent

command represents what the user wants to do, not how it’s done.

public record CreateOrderCommand(
string Product,
int Quantity
);

This command:

  • Is hosting-agnostic
  • Contains only the data required for the action
  • Can be created by SSR UI, WASM UI, or background processes

It is the language of the feature.

Handlers Own the Behavior

The handler is where intent becomes action.

public class CreateOrderHandler
{
private readonly AppDbContext _db;

public CreateOrderHandler(AppDbContext db)
=> _db = db;

public async Task<OrderResult> Handle(CreateOrderCommand command)
{
var order = new Order
{
Product = command.Product,
Quantity = command.Quantity
};

_db.Orders.Add(order);
await _db.SaveChangesAsync();

return new OrderResult(order.Id);
}
}

This logic:

  • Runs identically in SSR and WASM scenarios
  • Is easy to test
  • Contains no HTTP or UI concerns

Auto Mode can move execution freely because the behavior never moves.

Endpoints Become Simple Adapters

Endpoints exist only to translate transport concerns into commands.

app.MapPost("/api/orders", async (
CreateOrderCommand command,
CreateOrderHandler handler) =>
{
var result = await handler.Handle(command);
return Results.Ok(result);
});

No business logic.
No validation rules.
No orchestration.

Just adaptation.

Why This Model Scales

Command-based slices:

  • Support UIAPIbackground jobs, and SignalR
  • Are easy to reason about
  • Encourage clear boundaries
  • Eliminate duplicated logic

As Blazor adds new capabilities, this structure remains stable.

Auto Mode’s Secret Weapon

Auto Mode doesn’t need smarter UI.

It needs smarter boundaries.

Commands and handlers provide those boundaries, allowing the UI to remain simple and declarative while the slice absorbs execution complexity.

Streaming Rendering + Partial Hydration

One of the most powerful aspects of Blazor Auto Mode in .NET 10 is its ability to stream UI immediately and hydrate components incrementally. This dramatically improves perceived performance — but only if your architecture can support it.

Vertical slices make this possible without added complexity.

What Streaming Rendering Actually Means

With streaming rendering:

  • HTML is sent to the browser as soon as it’s available
  • The page becomes visible before all data is loaded
  • Components don’t block rendering while waiting on async work

The user sees something immediately, not after everything completes.

This is especially important for:

  • Data-heavy pages
  • Forms
  • Dashboards
  • Mobile and low-bandwidth users

Partial Hydration Explained

Hydration is the process where Blazor:

  • Attaches interactivity to rendered HTML
  • Wires up event handlers
  • Transitions execution to WASM

With partial hydration, this happens per component, not all at once.

Some components may already be interactive while others are still loading.

Why Vertical Slices Enable This

Streaming and hydration only work well when components:

  • Are declarative
  • Have minimal side effects
  • Do not assume synchronous execution

Vertical slices encourage exactly this.

Because:

  • Business logic lives in handlers
  • UI expresses intent
  • Data flows through DTOs

Components can render safely without triggering hidden dependencies.

A Streaming-Friendly UI Pattern

@if (order is null)
{
<p>Loading order...</p>
}
else
{
<OrderSummary Order="order" />
}

This works because:

  • The component can render immediately
  • Data arrives later
  • Hydration doesn’t rerun logic
  • No hosting checks are required

The slice absorbs complexity. The UI stays simple.

No Special Code for Streaming

The most important thing to notice:

There is no streaming-specific code here.

No flags.
No modes.
No branching logic.

If streaming requires special handling in your UI, your architecture is fighting the framework.

Handlers Stay Predictable

Handlers don’t care about streaming or hydration.

They:

  • Execute when invoked
  • Return results
  • Remain stateless and testable

This predictability allows Blazor to:

  • Render early
  • Resume later
  • Switch execution models safely

Why This Matters for Auto Mode

Auto Mode relies on:

  • Early rendering
  • Deferred execution
  • Seamless handoff

Vertical slices make those transitions invisible.

The result:

  • Faster first paint
  • Better UX
  • Less architectural debt
  • Fewer bugs tied to execution timing

End-to-End Feature Flow with Real-Time Updates

At this point, all the pieces are in place. Now let’s see how Blazor Auto Mode + Vertical Slices work together in a real feature — from first render to real-time UI updates — without changing architecture or duplicating logic.

We’ll walk through a single slice:

End-to-End Example: Create Order

One feature.
One slice.
One mental model.

Page → Form → Command → Handler → EF Core

SignalR Event

UI Updates (SSR → WASM)

Step 1: The Page Renders (SSR)

The page renders immediately using SSR. Because the UI is declarative and slice-owned, it streams without waiting for backend work.

@page "/orders/create"

<EditForm Model="model" OnValidSubmit="Submit">
<InputText @bind-Value="model.Product" />
<InputNumber @bind-Value="model.Quantity" />
<button type="submit">Create Order</button>
</EditForm>

@if (created)
{
<p>Order created.</p>
}

No SSR logic. No WASM logic. Just UI.

Step 2: The User Submits the Form

The user action produces intent, not behavior.

private async Task Submit()
{
await orderClient.Create(model);
created = true;
}

The UI does not:

  • Talk to EF
  • Know about SignalR
  • Care where it’s running

Step 3: A Command Is Created

public record CreateOrderCommand(
string Product,
int Quantity
);

This command:

  • Is shared across execution models
  • Represents a single business action
  • Can be triggered by UIAPI, or background jobs

Step 4: The Handler Executes

This is where business logic and real-time behavior live together — inside the slice.

public class CreateOrderHandler
{
private readonly AppDbContext _db;
private readonly IHubContext<OrderHub> _hub;

public CreateOrderHandler(
AppDbContext db,
IHubContext<OrderHub> hub)
{
_db = db;
_hub = hub;
}

public async Task Handle(CreateOrderCommand command)
{
var order = new Order
{
Product = command.Product,
Quantity = command.Quantity
};

_db.Orders.Add(order);
await _db.SaveChangesAsync();

await _hub.Clients.All
.SendAsync("OrderCreated", order.Id);
}
}

Step 5: EF Core Persists the Data

Persistence is a detail of the slice:

  • No repository abstraction required
  • No shared service layer
  • EF Core is injected and used directly

The handler remains:

  • Testable
  • Predictable
  • Hosting-agnostic

Step 6: SignalR Pushes a Real-Time Update

The handler publishes a real-time event once the order is created.

Why this works cleanly:

  • SignalR is infrastructure
  • The slice owns when events fire
  • The UI doesn’t orchestrate anything

Auto Mode doesn’t interfere here — it simply keeps the UI alive.

Step 7: The UI Updates Seamlessly

Whether the page is still:

  • SSR-rendered
  • Hydrated
  • Fully running in WASM

The SignalR update arrives the same way.

No special cases.
No alternate code paths.
No duplicated logic.

Why This Is the Big Win

This entire flow:

  • Works in Auto Mode
  • Uses one UI
  • Uses one handler
  • Uses one command
  • Supports real-time updates
  • Scales across execution models

This is the new full-stack baseline in .NET 10.

The Takeaway

When vertical slices own behavior, execution becomes an implementation detailAuto Mode can streamhydrate, and transition freely — because the architecture is solid.

This is what modern Blazor applications should look like.

End-to-End Vertical Slice Flow (Auto Mode)

Conceptual Diagram

  • One UI shared across SSR and WASM
  • One vertical slice owning behavior end to end
  • No duplicated logic for execution mode
  • Real-time updates flowing naturally through the slice
  • Auto Mode becomes invisible — not architectural
┌──────────────┐
│ Blazor Page │
│ (Auto Mode) │
└──────┬───────┘
│ User Intent

┌──────────────┐
│ UI Form │
│ (Shared UI) │
└──────┬───────┘
│ Command

┌────────────────────┐
│ Vertical Slice │
│ ───────────────── │
│ CreateOrderCommand│
│ CreateOrderHandler│
│ OrderDto │
└──────┬─────────────┘
│ Business Logic

┌──────────────┐
│ EF Core │
│ DbContext │
└──────┬───────┘
│ Domain Event

┌──────────────┐
│ SignalR Hub │
└──────┬───────┘
│ Real-time Update

┌────────────────────────┐
│ Blazor UI (SSR → WASM) │
│ Partial Hydration │
└────────────────────────┘

This visual reinforces that execution is a runtime concern, not a design concern.

Common Pitfalls to Avoid

Even with vertical slices and Auto Mode, there are traps that developers frequently fall into:

  • Duplicating UI logic for SSR and WASM: Don’t branch or copy code for different hosting models. Let the slice handle execution-agnostic behavior.
  • Mixing business logic into components: Components should only capture intent and render results. Handlers own behavior.
  • Overloading endpoints with logic: Endpoints are adapters, not the feature core. Keep commands and handlers central.
  • Injecting EF Core or services directly into multiple pages: Let the handler manage persistence. Pages should only call the slice’s abstraction.
  • Skipping DTOs for shared contracts: Avoid coupling UI directly to entities. Shared DTOs keep the slice portable between SSR and WASM.
  • Assuming synchronous rendering: Auto Mode streams and hydrates. Components and handlers must be async-friendly.
  • Ignoring real-time integration: SignalR events should be part of the slice, not scattered in the UI or services.

Pro Tip

If you find yourself adding if (OperatingSystem.IsBrowser()) checks or duplicating service calls, your slice boundaries are probably too weak.

Conclusion: The New Blazor Standard

Blazor Auto Mode + Vertical Slice Architecture in .NET 10 lets you build one UI, one feature flow, and one source of truth that works seamlessly across SSR, WASM, streaming rendering, and real-time updates.

By keeping commandshandlersDTOs, and endpoints self-contained, you eliminate duplicated logicreduce coupling, and make your application predictable, testable, and future-proof. Write your slices once, let Auto Mode handle execution, and deliver full-stack features confidently.

This is what modern Blazor applications should look like.

Happy coding!