C# 13 and .NET 9: Build Modern Cross‑Platform Websites and Services with ASP.NET Core 9, Blazor, and EF Core 9
What if you could go from “Hello, World” to a production‑ready API and a polished web UI using the same language, the same framework, and the same tooling across Windows, macOS, and Linux? With C# 13 and .NET 9, that promise isn’t hype—it’s the daily reality for modern teams shipping fast and iterating with confidence.
In this guide, I’ll translate the newest features of C# 13 and .NET 9 into practical steps you can use right away: building APIs with Minimal APIs, creating interactive UIs with Blazor, and working with data using EF Core 9. We’ll cover what’s new, why it matters, and how to put it to work—with short code examples you can copy and run. And yes, we’ll talk performance, Native AOT, and the now‑built‑in OpenAPI experience that makes your services a dream to consume.
What’s new in C# 13 and .NET 9 (in plain English)
C# and .NET continue to evolve with a clear theme: reduce ceremony, boost performance, and remove friction so you can ship. Here are highlights—minus the jargon:
- C# 13 adds quality‑of‑life improvements that make everyday code more expressive and less error‑prone.
- More flexible params allow you to pass collections more naturally to methods that accept variable arguments.
- Language refinements build on C# 12 features like primary constructors and collection expressions to make data and configuration code cleaner.
- LINQ in .NET 9 introduces new operators and performance tweaks.
- CountBy groups items and gives you counts in one pass—great for analytics dashboards and quick summaries.
- Index and related helpers make it easier to work with positions without writing your own counters.
- Runtime performance upgrades mean faster startups and lower memory in real apps.
- When exceptions do happen, they’re cheaper, so telemetry and error handling add less overhead.
- Native AOT expands and stabilizes.
- You can publish many types of apps with ahead‑of‑time compilation for faster startup and smaller footprints—ideal for containerized and serverless workloads.
On the web stack side, ASP.NET Core 9 doubles down on developer experience:
- Built‑in OpenAPI document generation creates Swagger docs with minimal setup—no heavy configuration required.
- Optimized static assets make bundling and serving front‑end content simpler and more efficient.
- HybridCache adds a first‑class caching model that blends in‑memory and distributed caches for consistent speed at scale.
And for data access, EF Core 9 brings reliability and modern database features:
- Better JSON column mapping and querying on supported providers.
- Improvements to compiled models, interceptors, and the LINQ translation engine for fewer surprises and more speed.
If you want the long form from Microsoft, check out What’s new in .NET 9 and C# 13 in the official docs and release posts: – C# 13 highlights: What’s new in C# – .NET 9 overview: What’s new in .NET 9 – ASP.NET Core 9 release notes: ASP.NET Core 9.0 – EF Core 9 changes: What’s new in EF Core
Want to try it yourself? Check it on Amazon.
Your development setup: tools, SDKs, and a smooth workflow
Getting set up is the easy part:
- Install the .NET 9 SDK: Use the official installer for your OS. On macOS and Linux, package managers work great. Verify with:
dotnet --info
. - Choose your IDE:
- Windows: Visual Studio 2022 (latest channel) gives you rich debugging, designers, and integrated Docker tooling.
- Cross‑platform: Visual Studio Code with the C# Dev Kit and .NET extensions is light, fast, and perfect for web and service development. Get started with VS Code and .NET.
- Decide how you’ll run: local Kestrel server is fine for development; add Docker for parity with production. The .NET SDK ships with great Docker base images.
A note for Mac users: Visual Studio for Mac is retired, so VS Code or a third‑party IDE like Rider is the current path forward. Here’s why that matters: the C# Dev Kit in VS Code has caught up fast, with dependable debugging and project scaffolding for web, Blazor, and testing.
If you’re picking a learning resource to pair with your environment, choose one that uses .NET 9 project templates and shows both Visual Studio and VS Code workflows so you’re not locked into a tool. Ready to upgrade your learning stack with a hands‑on guide? See price on Amazon.
Recommended project structure for clarity
You’ll onboard faster if you keep projects focused:
- Web API or Blazor project (ASP.NET Core 9)
- Class library for domain + application logic
- EF Core data project for DbContext and migrations
- Test project (xUnit or NUnit)
This separation pays off when you add CI/CD, AOT, and containerization later.
Build a minimal API with built‑in OpenAPI
Minimal APIs let you define endpoints in a few lines while keeping testability and strong typing. Open your terminal and run:
dotnet new web -n TodoApi
cd TodoApi
dotnet add package Microsoft.AspNetCore.OpenApi
Program.cs:
var builder = WebApplication.CreateBuilder(args);
// Built-in OpenAPI in ASP.NET Core 9
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapGet("/api/todos", () =>
{
var todos = new[] {
new { Id = 1, Title = "Learn Minimal APIs", Done = false },
new { Id = 2, Title = "Ship an endpoint", Done = true }
};
return Results.Ok(todos);
})
.WithName("GetTodos")
.WithOpenApi();
app.MapPost("/api/todos", (Todo todo) =>
{
// Persist later with EF Core; return created for now
return Results.Created($"/api/todos/{todo.Id}", todo);
})
.WithOpenApi();
app.MapOpenApi(); // Serve /openapi/v1.json
app.UseSwaggerUI(); // Serve Swagger UI at /swagger
app.Run();
record Todo(int Id, string Title, bool Done);
A few notes: – AddOpenApi and MapOpenApi ship with ASP.NET Core 9, so Swagger setup is now essentially one line. – .WithOpenApi on endpoints enriches your docs with summaries and parameter metadata automatically.
Prefer step‑by‑step labs that mirror the code below? Buy on Amazon.
To learn more about OpenAPI integration, see the ASP.NET docs: OpenAPI support in minimal APIs.
Blazor in .NET 9: one Blazor, many choices
Blazor’s unified hosting model (introduced in .NET 8 and refined in .NET 9) gives you a single component model that can render server‑side or on WebAssembly and fall back to server rendering as needed. Here’s why that matters: your team can share UI code and decide on the hosting mode by scenario, not by framework constraint.
- Blazor Server: Lowest latency, great for intranet and authenticated apps.
- Blazor WebAssembly: Runs in the browser, great for offline and CDN‑friendly deployments.
- Blazor “Auto” or mixed: Start server‑rendered, progressively enhance with client interactivity where it helps UX.
A tiny Blazor component that renders a list and uses CountBy‑style logic in C# is straightforward:
@page "/stats"
<h3>Todo Stats</h3>
@if (todos is null)
{
<p>Loading...</p>
}
else
{
<ul>
@foreach (var (status, count) in todos.GroupBy(t => t.Done)
.Select(g => (status: g.Key ? "Done" : "Open", count: g.Count())))
{
<li>@status: @count</li>
}
</ul>
}
@code {
private List<Todo>? todos;
protected override async Task OnInitializedAsync()
{
// In real code, call your Minimal API endpoint
await Task.Delay(50);
todos = new()
{
new Todo(1, "Create Blazor component", true),
new Todo(2, "Wire up API", false),
new Todo(3, "Deploy", false)
};
}
public record Todo(int Id, string Title, bool Done);
}
Note: When your SDK includes the new CountBy operator, you can replace GroupBy + Count with a cleaner call, improving readability and performance.
For an overview of Blazor’s model and templates, start here: Blazor documentation.
Data access with EF Core 9: clean models, fluent queries
EF Core 9 continues the trend of predictable migrations, faster query translation, and richer mapping.
- JSON columns: On supported relational providers (like SQL Server and PostgreSQL), mapping to JSON shapes is more natural, reducing DTO overhead.
- Interceptors and logging: Hook into query execution, command creation, and save changes for telemetry and diagnostics.
- Compiled models: Improve cold start and query performance for known schemas.
Example DbContext and entity:
public class AppDbContext : DbContext
{
public DbSet<Todo> Todos => Set<Todo>();
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Todo>()
.Property(t => t.MetadataJson)
.HasColumnType("json"); // Provider-appropriate type
}
}
public class Todo
{
public int Id { get; set; }
public string Title { get; set; } = "";
public bool Done { get; set; }
public string? MetadataJson { get; set; } // JSON for tags, notes, etc.
}
Adding EF Core to the Minimal API:
builder.Services.AddDbContext<AppDbContext>(opts =>
opts.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
Endpoint that queries with LINQ:
app.MapGet("/api/todos/open", async (AppDbContext db) =>
{
var open = await db.Todos
.Where(t => !t.Done)
.OrderBy(t => t.Id)
.Select(t => new { t.Id, t.Title })
.ToListAsync();
return Results.Ok(open);
})
.WithOpenApi();
If you like having a reference open while you build your data layer, View on Amazon.
For the official “what’s new,” visit: EF Core 9 highlights.
Performance, Native AOT, and HybridCache
Shipping fast often means starting fast and staying fast under load.
- Native AOT: Publish ahead of time to reduce cold‑start latency and memory footprint. This especially shines in microservices, serverless functions, and CLI tools.
- Try it:
dotnet publish -c Release -r linux-x64 -p:PublishAot=true
- Learn more: Native AOT deployment
- HybridCache: Blend in‑memory speed with distributed cache consistency.
- Cache hot results in memory on each instance.
- Synchronize invalidations via Redis for correctness.
- Use it for read‑heavy endpoints with tolerable staleness windows.
To go deeper into performance tuning and AOT, Shop on Amazon.
For a bird’s‑eye view of .NET performance work, see the latest announcements on the .NET Blog.
Smarter LINQ in .NET 9: CountBy, Index, and less boilerplate
LINQ gets a quiet but useful boost in .NET 9. Two patterns you’ll notice:
- CountBy: Great for quick summaries without the ceremony of GroupBy/Select/Count chains.
- Index helpers: Cleaner enumeration with positions, less custom counters.
Use these to simplify analytics endpoints, quick dashboards, and result transforms between your API and UI.
Here’s a pattern for analytics in a Minimal API:
app.MapGet("/api/todos/stats", async (AppDbContext db) =>
{
var items = await db.Todos.AsNoTracking().ToListAsync();
// Replace with CountBy when available in your SDK
var counts = items
.GroupBy(t => t.Done ? "Done" : "Open")
.Select(g => new { Status = g.Key, Count = g.Count() })
.OrderByDescending(x => x.Count);
return Results.Ok(counts);
})
.WithOpenApi();
This is not only shorter; it’s easier to test and maintain.
Choosing the right hosting model: Kestrel, IIS, Nginx, containers
You have options, and they all play well with .NET 9:
- Kestrel + reverse proxy (Nginx/Apache): Common for Linux deployments; keep TLS at the proxy and forward to Kestrel.
- IIS on Windows: Use the ASP.NET Core Module; good for orgs with existing Windows Server infrastructure.
- Containers: The most portable and repeatable approach. Use the official .NET 9 runtime images and multi‑stage Dockerfiles for small builds.
Tips: – Always enable HTTPS in dev and use environment‑specific configuration with user secrets for connection strings. – Consider AOT for cold‑start sensitive services; measure with and without to justify the tradeoffs.
Cache, compress, and cut the noise
ASP.NET Core 9 makes it straightforward to layer performance best practices:
- Response compression: Add Brotli/Gzip for text assets.
- Output caching or HybridCache: Cache responses for idempotent, read‑heavy endpoints.
- Static web assets: Ship hashed bundles and configure long cache lifetimes.
These changes are often one‑ or two‑line additions, yet they can cut response times in half and reduce server CPU.
Testing and debugging: less friction, more confidence
A few habits go a long way:
- Unit test your endpoints’ handlers and your domain services separately from the web host.
- Use EF Core’s InMemory provider or Testcontainers for integration tests.
- Turn on detailed logging in dev and teach your team to read traces and OpenAPI docs.
With Visual Studio or VS Code, you can attach to a running process, set conditional breakpoints, and step through async code reliably. It’s worth a half‑day to set up launch profiles, Docker integration, and environment variables so “it works on my machine” stops being a blocker.
Common pitfalls—and how to avoid them
- Blocking calls in async code: Always await database and network calls to prevent thread starvation.
- Massive DbContexts: Keep them focused; avoid “god contexts” that slow startup and migration times.
- Overusing exceptions for control flow: Exceptions are faster in .NET 9, but they’re still for exceptional paths.
- Premature AOT: Validate your reflection usage and dependencies; profile first, then AOT.
- Ignoring OpenAPI: Your consumers need reliable contracts—treat your OpenAPI doc as a build artifact.
Quick buying and setup tips for learners
If you’re picking a guide, choose one that: – Uses .NET 9 templates so your experience matches production defaults. – Covers both ASP.NET Core and Blazor with EF Core data access. – Includes exercises for Visual Studio and VS Code. – Explains AOT, caching, and OpenAPI—not just the happy path.
Want a curated, practice‑first walkthrough that includes all of the above? View on Amazon.
Frequently asked questions
Q: Do I need Windows to build with .NET 9 and C# 13? A: No. .NET 9 is fully cross‑platform. You can build and run on Windows, macOS, and Linux using Visual Studio (Windows) or VS Code (all platforms).
Q: Should I choose Blazor Server or WebAssembly? A: It depends on your UX needs. Blazor Server has the lowest latency to data and smaller downloads, while Blazor WebAssembly runs offline and can be served via a CDN. The unified model lets you mix as needed.
Q: Are Minimal APIs “too minimal” for large apps? A: Not if you keep handlers thin and push logic into services. You still get DI, filters, OpenAPI, testing support, and middleware. MVC controllers are great too—pick the style your team can maintain.
Q: How hard is Native AOT in real projects? A: It’s getting easier, but you still need to validate reflection, dynamic code, and some libraries. Start with small services and measure. See the official guide: Native AOT deployment.
Q: What’s the biggest EF Core 9 win? A: Better predictability and performance in queries, plus improved JSON mapping where supported. It reduces boilerplate and surprises.
Q: How do I expose OpenAPI docs in ASP.NET Core 9? A: Add AddOpenApi(), call MapOpenApi(), and optionally UseSwaggerUI(). You can decorate endpoints with .WithOpenApi() for richer docs. See: OpenAPI with minimal APIs.
Q: Can I mix Razor Pages, MVC, Minimal APIs, and Blazor? A: Yes. ASP.NET Core is composable. Many apps use Minimal APIs for services, MVC/Razor for server‑rendered pages, and Blazor for interactive client components.
The takeaway
C# 13 and .NET 9 give you a unified, fast path to building professional websites and services: Minimal APIs with first‑class OpenAPI, a flexible Blazor UI story, and an EF Core 9 data layer you can trust. Start with a small end‑to‑end feature—API, UI, and database—then layer in caching, AOT, and CI/CD. You’ll feel the productivity gains from day one.
If you found this useful, consider exploring more deep dives on .NET 9, Blazor, and EF Core, or subscribe for upcoming hands‑on walkthroughs and sample repos.
Discover more at InnoVirtuoso.com
I would love some feedback on my writing so if you have any, please don’t hesitate to leave a comment around here or in any platforms that is convenient for you.
For more on tech and other topics, explore InnoVirtuoso.com anytime. Subscribe to my newsletter and join our growing community—we’ll create something magical together. I promise, it’ll never be boring!
Stay updated with the latest news—subscribe to our newsletter today!
Thank you all—wishing you an amazing day ahead!
Read more related Articles at InnoVirtuoso
- How to Completely Turn Off Google AI on Your Android Phone
- The Best AI Jokes of the Month: February Edition
- Introducing SpoofDPI: Bypassing Deep Packet Inspection
- Getting Started with shadps4: Your Guide to the PlayStation 4 Emulator
- Sophos Pricing in 2025: A Guide to Intercept X Endpoint Protection
- The Essential Requirements for Augmented Reality: A Comprehensive Guide
- Harvard: A Legacy of Achievements and a Path Towards the Future
- Unlocking the Secrets of Prompt Engineering: 5 Must-Read Books That Will Revolutionize You