Roadmap › ASP.NET Core MVC (and Razor Pages) › Module: MVC Basics
Lessons in this course (15)

1. Project and folder structure — every folder and file explained

Basic★ Must knowLesson 1 of 15

dotnet new mvc -n MyShop.Web (or Visual Studio → "ASP.NET Core Web App (Model-View-Controller)") creates:

text
MyShop.Web/
├── Connected Services/               (VS only) service references
├── Dependencies/                     (VS only) view of NuGet packages, frameworks, analyzers
├── Properties/
│   └── launchSettings.json           local run profiles: URLs/ports, environment (ASPNETCORE_ENVIRONMENT=Development) — NOT used in production
├── wwwroot/                          the web root: the ONLY folder served as static files
│   ├── css/site.css
│   ├── js/site.js
│   ├── lib/                          client libraries (bootstrap, jquery, jquery-validation)
│   └── favicon.ico
├── Controllers/
│   └── HomeController.cs             classes ending in "Controller", deriving from Controller
├── Models/
│   └── ErrorViewModel.cs             view models / DTOs (domain entities usually live in other projects)
├── Views/
│   ├── _ViewImports.cshtml           @using namespaces + @addTagHelper for ALL views in this folder and below
│   ├── _ViewStart.cshtml             code run before every view — normally sets Layout = "_Layout"
│   ├── Home/                         one folder per controller
│   │   ├── Index.cshtml              view for HomeController.Index()
│   │   └── Privacy.cshtml
│   └── Shared/                       views searched by every controller
│       ├── _Layout.cshtml            master layout (<html>, <head>, nav, @RenderBody(), footer)
│       ├── _Layout.cshtml.css        CSS isolation for the layout (scoped CSS)
│       ├── _ValidationScriptsPartial.cshtml   jquery validation scripts partial
│       └── Error.cshtml              error page used by UseExceptionHandler("/Home/Error")
├── appsettings.json                  configuration for all environments (logging, connection strings, options)
├── appsettings.Development.json      overrides for Development (merged on top)
├── Program.cs                        app entry point: builds the host, registers services (DI), defines the middleware pipeline and routes
└── MyShop.Web.csproj                 SDK-style project: <Project Sdk="Microsoft.NET.Sdk.Web">, target framework, package references

Folders that real projects usually add:

text
├── Areas/Admin/Controllers, Views, ...   feature sections with their own controllers/views ([Area("Admin")])
├── ViewComponents/                       reusable widgets with logic (CartSummaryViewComponent.cs)
│   └── (views in Views/Shared/Components/CartSummary/Default.cshtml)
├── TagHelpers/                           custom tag helpers
├── Filters/                              action/exception filters
├── Middleware/                           custom middleware classes
├── Services/                             application services (or a separate class library)
├── Data/                                 DbContext, migrations, seed data (or Infrastructure project)
├── Extensions/                           IServiceCollection extension methods (AddShopServices)
├── Resources/                            .resx files for localisation
└── Properties/PublishProfiles/           publish settings (folder, IIS, Azure)

Program.cs — the whole app setup in one file (.NET 6+ minimal hosting):

csharp
var builder = WebApplication.CreateBuilder(args);       // 1. host: configuration, logging, DI container, Kestrel

// 2. Register services (DI container)
builder.Services.AddControllersWithViews();              // MVC + Razor views
builder.Services.AddDbContext<ShopDbContext>(o => o.UseSqlServer(builder.Configuration.GetConnectionString("Shop")));
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();

var app = builder.Build();                               // 3. build the app (service provider created)

// 4. Middleware pipeline — ORDER MATTERS
if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); }
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapStaticAssets();                                   // .NET 9+ (older: app.UseStaticFiles() before UseRouting)

// 5. Endpoints
app.MapControllerRoute(name: "areas", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}").WithStaticAssets();

app.Run();                                               // 6. start Kestrel and block until shutdown

View lookup convention: for ProductsController.Details() returning View(), the view engine searches Views/Products/Details.cshtml, then Views/Shared/Details.cshtml (and Areas/{area}/Views/... for areas). Partial views starting with _ by convention.

Comparison with MVC 5: Global.asax + App_Start/*Config.cs + web.config → Program.cs + appsettings.json; Content/ + Scripts/ → wwwroot/; Views/web.config → _ViewImports.cshtml; packages.config → <PackageReference> in the .csproj.

Interview tip: Only wwwroot is publicly served. Files like appsettings.json or .cshtml are never downloadable — Razor views are compiled into the app's assembly at build time.