Creating a modern multi-page web application that combines the power of ASP.NET for backend logic and Vite.js for frontend development offers a fast, modular, and scalable solution. This guide walks you through the setup, starting with the essential dependencies.
Step 1: Dependencies
To get started, make sure you have the following installed:
Required Tools
- .NET SDK (7.0 or later)
- Node.js (v18 or later)
- Vite.js (installed via npm)
- A code editor like Visual Studio Code
- Project Structure
Your project will be structured like this:
/MyApp /ClientApp ← Vite.js frontend /Controllers ← ASP.NET MVC controllers /Models ← ASP.NET Model /Properties ← ASP.NET launch setting /Views ← Razor views (optional) /wwwroot ← Final build path Program.cs Startup.cs or minimal hosting
1: Set Up ASP.NET Core Backend
Create a new ASP.NET Core Web App (MVC or Empty):
dotnet new web -n MyApp
cd MyApp
code .
2. Configure Program.cs to serve static files and fallback to index.html in production:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseStaticFiles();
app.MapFallbackToFile("index.html");
}
app.UseRouting();
app.MapControllers();
app.Run();
3. Setup Routing Controller for Client App
Modify Controllers/HomeController.cs as follows:
using Microsoft.AspNetCore.Mvc;
public class HomeController : Controller
{
[HttpGet("{*url}", Order = int.MaxValue)]
public IActionResult Index(string url)
{
return View();
}
}
You can remove the default Privacy() action and its view since this will be handled by your SPA.
Step 2: Add WeatherForecast API
- Create WeatherForecastController.cs Controller
Should create controller inside
/Controller/Api/WeatherForecastController.cs
using Microsoft.AspNetCore.Mvc;
namespace MyApp.Controllers.Api; // change the namespace
[ApiController]
[Route("api/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
});
}
}
- Create a Model for the Controller
Should create model inside /Models/WeatherForecast.cs
namespace MyApp.Models // change the namespace
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
- Update Razor Views
Clear all inside the /Views/Home/Index.cshtml and add:
@{
Layout = "_Layout";
}
Modify the _Layout file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MyApp</title>
<!-- Only for the React Refresh, for other templates remove this -->
<script type="module">
import { injectIntoGlobalHook } from "http://localhost:5173/@react-refresh";
injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => (type) => type;
</script>
<!-- End Refresh -->
<script type="module" src="http://localhost:5173/@vite/client"></script>
</head>
<body>
@RenderBody()
<script type="module" src="http://localhost:5173/src/main.tsx"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Here I use React template in Vite so we need to add the React refresh lines. For other templates we can remove them.
Step 3: Set Up React Frontend with Vite
- Create your Vite app:
npm create vite@latest ClientApp
Package name: clientapp
Template: react, react-ts, or vue (your choice)
- Navigate and install dependencies:
cd ClientApp
npm i
npm i react-router axios
- Recommended Folder Structure
/src
/components ← Header, Footer
/pages ← Home, WeatherList
main.tsx
App.tsx
- Setup Axios API: /src/api/weather.tsx
import axios from "axios"; //can use JavaScript Fetch
export const getWeatherForecast = () =>
axios.get("/api/weatherforecast").then((res) => res.data);
// fetch()
- Create Home Page and Weather Page
import { useEffect, useState } from "react";
import { getWeatherForecast } from "../api/weather";
function WeatherList() {
const [forecasts, setForecasts] = useState([]);
useEffect(() => {
getWeatherForecast().then(setForecasts);
}, []);
return (
<div>
<h2>Weather Forecast</h2>
<ul>
{forecasts.map((f, i) => (
<li key={i}>
{f.date}: {f.summary} ({f.temperatureC}°C)
</li>
))}
</ul>
</div>
);
}
export default WeatherList;
function Home() {
return (
<div className="container mt-5">
<div className="row justify-content-center">
<div className="col-md-8 text-center">
<h1 className="mb-4">Welcome to the Movie Application!</h1>
<p className="lead">Discover, explore, and enjoy our collection of movies.</p>
<p>Use the navigation bar to browse through different sections.</p>
</div>
</div>
</div>
);
}
export default Home;
- Configure Routing in /src/App.tsx
import { BrowserRouter, Routes, Route } from "react-router";
import { WeatherList } from "./pages/WeatherList";
import Home from "./pages/Home";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/weather" element={<WeatherList />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Final Step: Run the App
Open two terminals:
Terminal 1: ASP.NET Core Backend
dotnet dev-certs https --trust
dotnet watch run
# for https
dotnet watch -lp https
Terminal 2: React Frontend with Vite
cd ClientApp
npm run dev
In single Powershell based run both at a time
Start-Process -WorkingDirectory ".\ClientApp" -NoNewWindow -FilePath "powershell" -ArgumentList "npm run dev"
dotnet watch run
Summary
You now have a scalable, modern full-stack application using:
ASP.NET Core for APIs and static file hosting
React (or other template) + Vite for fast frontend development
Axios + React Router for API calls and navigation
This setup is easily extendable to include authentication, advanced state management, and deployment pipelines.
Top comments (1)
Great walkthrough—ASP.NET and Vite together make a super modern stack! On Windows, I often lean on ServBay to quickly spin up .NET, Node, HTTPS, and database services with a single click. Makes testing frontend-backend combos like this effortless.