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.