Choosing a Front-End for .NET Development
Here’s a practical guide to pairing .NET with front-end options, including code examples to help you decide: 1. Traditional HTML/JavaScript + Lightweight Libraries Example 1: HTMX + .NET API Goal: Fetch data from a .NET API and update the page without writing JavaScript. Backend (C#) Return HTML instead of JSON using Razor views: // WeatherController.cs [HttpGet("html")] public IActionResult GetWeatherHtml() { var forecasts = new[] { "Sunny", "Cloudy", "Rainy" }; return PartialView("_WeatherPartial", forecasts); } Create a Razor partial view (_WeatherPartial.cshtml): @model string[] @foreach (var forecast in Model) { @forecast } Frontend (HTML with HTMX) Load Weather Loading... .hidden { display: none; } [hx-indicator="#loading"]:not([hx-disabled-elt]) + #loading { display: block; } Example 2: Alpine.js + Razor Pages Goal: Create a reactive counter without complex setup. Frontend (Razor Page): + - 2. Modern Frameworks (React/Vue/Angular) Example 1: React + .NET Web API Goal: Build a dynamic list of items fetched from a .NET API. React Component: // App.jsx import { useEffect, useState } from 'react'; function App() { const [items, setItems] = useState([]); useEffect(() => { fetch('/api/items') // Calls your .NET API .then(res => res.json()) .then(data => setItems(data)); }, []); return ( {items.map(item => {item.name})} ); } Setup: Use the dotnet new react template for a preconfigured React + .NET project. Example 2: Vue + .NET Goal: Display a form that submits data to a .NET API. Vue Component: Save export default { data() { return { name: '' }; }, methods: { submitForm() { fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: this.name }) }); } } }; 3. Blazor (C# on the Front-End) Example: Blazor Component Goal: Create an interactive list using C# instead of JavaScript. Component: @page "/weather" @inject HttpClient Http Weather Forecast @if (forecasts == null) { Loading... } else { @foreach (var forecast in forecasts) { @forecast } } @code { private string[] forecasts; protected override async Task OnInitializedAsync() { // Calls your .NET API directly forecasts = await Http.GetFromJsonAsync("api/weather"); } } When to Use What? Scenario Recommended Approach Simple CRUD app HTML + HTMX/Alpine.js + Razor Team knows JavaScript well React/Vue + .NET Web API Avoid JavaScript entirely Blazor Legacy app maintenance jQuery + MVC Key Takeaways: For quick results, stick to Razor Pages with Alpine.js or HTMX. For complex UIs (e.g., dashboards), use React/Vue with a .NET Web API. If you hate JavaScript, Blazor is your friend.

Here’s a practical guide to pairing .NET with front-end options, including code examples to help you decide:
1. Traditional HTML/JavaScript + Lightweight Libraries
Example 1: HTMX + .NET API
- Goal: Fetch data from a .NET API and update the page without writing JavaScript.
- Backend (C#) Return HTML instead of JSON using Razor views:
// WeatherController.cs
[HttpGet("html")]
public IActionResult GetWeatherHtml()
{
var forecasts = new[] { "Sunny", "Cloudy", "Rainy" };
return PartialView("_WeatherPartial", forecasts);
}
Create a Razor partial view (_WeatherPartial.cshtml
):
@model string[]
class="weather-list">
@foreach (var forecast in Model)
{
@forecast
}
- Frontend (HTML with HTMX)
id="loading" class="hidden">Loading...
id="weather-container">
.hidden { display: none; }
[hx-indicator="#loading"]:not([hx-disabled-elt]) + #loading {
display: block;
}
Example 2: Alpine.js + Razor Pages
- Goal: Create a reactive counter without complex setup.
- Frontend (Razor Page):
x-data="{ count: 0 }">
x-text="count">
2. Modern Frameworks (React/Vue/Angular)
Example 1: React + .NET Web API
- Goal: Build a dynamic list of items fetched from a .NET API.
- React Component:
// App.jsx
import { useEffect, useState } from 'react';
function App() {
const [items, setItems] = useState([]);
useEffect(() => {
fetch('/api/items') // Calls your .NET API
.then(res => res.json())
.then(data => setItems(data));
}, []);
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
-
Setup: Use the
dotnet new react
template for a preconfigured React + .NET project.
Example 2: Vue + .NET
- Goal: Display a form that submits data to a .NET API.
- Vue Component:
<template>
template>
<script>
export default {
data() {
return { name: '' };
},
methods: {
submitForm() {
fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: this.name })
});
}
}
};
script>
3. Blazor (C# on the Front-End)
Example: Blazor Component
- Goal: Create an interactive list using C# instead of JavaScript.
- Component:
@page "/weather"
@inject HttpClient Http
Weather Forecast
@if (forecasts == null) {
Loading...
} else {
@foreach (var forecast in forecasts)
{
- @forecast
}
}
@code {
private string[] forecasts;
protected override async Task OnInitializedAsync()
{
// Calls your .NET API directly
forecasts = await Http.GetFromJsonAsync("api/weather");
}
}
When to Use What?
Scenario | Recommended Approach |
---|---|
Simple CRUD app | HTML + HTMX/Alpine.js + Razor |
Team knows JavaScript well | React/Vue + .NET Web API |
Avoid JavaScript entirely | Blazor |
Legacy app maintenance | jQuery + MVC |
Key Takeaways:
- For quick results, stick to Razor Pages with Alpine.js or HTMX.
- For complex UIs (e.g., dashboards), use React/Vue with a .NET Web API.
- If you hate JavaScript, Blazor is your friend.