Table of Contents
L'architettura Model-View-Controller (MVC) è un modello di design testuale che separa le preoccupazioni all'interno di un'applicazione web, rendendo più facile gestire la complessità, i componenti di prova in isolamento e le caratteristiche di scala nel tempo. In ASP.NET Core, MVC è un cittadino di prima classe, fornendo un quadro robusto per la costruzione di applicazioni web moderne e manutenbili.
Comprendere il modello MVC in profondità
Prima di immergersi in codice, è essenziale capire come i tre componenti fondamentali di MVC collaborano per gestire una richiesta dell'utente.
- Modello[]: Rappresenta la struttura dei dati e le regole aziendali. Non sa dell'interfaccia utente o come vengono visualizzati i dati. I modelli sono in genere semplici classi C# che incapsulano proprietà, logica di validazione e accesso ai dati (spesso tramite Entity Framework Core).
- Visualizza[]: Renders l'interfaccia utente. In ASP.NET Core, le visualizzazioni sono file Razor (`.cshtml`) che combinano il markup HTML con il codice C# lato server.
- Controller]: agisce come intermediario. Riceve richieste HTTP, decide quale modello utilizzare e seleziona la visualizzazione appropriata per tornare. I controller contengono metodi di azione che mappano le rotte specifiche.
La richiesta tipica scorre in ASP.NET Core MVC: un utente naviga in un URL (ad esempio [), il middleware instradante dirige la richiesta all'azione [, l'azione interagisce con il modello (ad esempio, fetches prodotti da un database), imballa i dati in un modello di visualizzazione e lo passa alla vista.
Prerequisiti
- .NET SDK[] (versione 6.0 o successiva). Scarica da dotnet.microsoft.com.
- Visual Studio[], Codice Studio Visuale[], o qualsiasi editor di codice preferito.
- La familiarità di base con C# e i concetti di sviluppo web.
Passo 1: Creazione di un nuovo progetto MVC di ASP.NET Core
Puoi iniziare con il .NET CLI o Visual Studio. Entrambi forniscono un modello di progetto che impalca la struttura standard della cartella MVC.
Usare la linea di comando
Aprire un terminale e eseguire:
dotnet new mvc -n MyMvcApp
Questo crea un progetto chiamato in una nuova cartella. La struttura generata include , , [], e (per file statici).
Utilizzo di Visual Studio
In Visual Studio, scegliere Crea un nuovo progetto[ → selezionare [ASP.NET Core Web App (Model-View-Controller)] → configurare il nome del progetto e la posizione → scegliere la versione .NET (ad esempio, .NET 8). Le stesse cartelle vengono create automaticamente.
Verificare le funzioni del progetto:
cd MyMvcApp
dotnet run
Apri per vedere la home page predefinita.
Fase 2: Comprendere la struttura del progetto
Il progetto impalcabile contiene diversi elementi chiave:
- Controllers[: cartella vuota dove aggiungere le classi di controllo C#.
- Models[]]: Luogo per le classi di dominio e modelli di visualizzazione.
- Visualizza[]]: Ha una cartella e [] per impostazione predefinita, più un layout.
- Program.cs[]: Avvio di applicazioni, dove i servizi (compresi MVC) sono configurati.
Aprire e notare le linee che permettono MVC:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();
...
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Questo imposta la rotta predefinita che mappa URL come ] a .
Passo 3: Creazione di una classe di modello
I modelli rappresentano i dati con cui l'applicazione funziona. Inizia creando un modello [ all'interno della cartella .
// Models/Product.cs
namespace MyMvcApp.Models;
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public string? Description { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
È possibile arricchire i modelli con annotazioni di dati per la validazione:
using System.ComponentModel.DataAnnotations;
public class Product
{
public int Id { get; set; }
[Required(ErrorMessage = "Product name is required.")]
[StringLength(100)]
public string Name { get; set; } = string.Empty;
[Range(0.01, 10000)]
public decimal Price { get; set; }
[MaxLength(500)]
public string? Description { get; set; }
[Display(Name = "Created")]
public DateTime CreatedAt { get; set; }
}
In una vera applicazione, si aggiungerebbe tipicamente un contesto di database (Entity Framework Core) per persistere nei modelli. Per questa guida useremo i dati in memoria per mantenere la concentrazione sul flusso MVC.
Passo 4: Aggiungere un controller
I controller gestiscono le richieste in arrivo e orchestrano la risposta. Creare un all'interno della cartella .
// Controllers/ProductsController.cs
using Microsoft.AspNetCore.Mvc;
using MyMvcApp.Models;
using System.Collections.Generic;
namespace MyMvcApp.Controllers;
public class ProductsController : Controller
{
// Simulate a data source
private static List<Product> _products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Price = 999.99m },
new Product { Id = 2, Name = "Smartphone", Price = 599.99m },
new Product { Id = 3, Name = "Tablet", Price = 399.99m }
};
// GET: /Products
public IActionResult Index()
{
return View(_products); // Pass list to the view
}
// GET: /Products/Details/5
public IActionResult Details(int id)
{
var product = _products.Find(p => p.Id == id);
if (product == null)
return NotFound();
return View(product);
}
// GET: /Products/Create
public IActionResult Create()
{
return View();
}
// POST: /Products/Create
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Product product)
{
if (ModelState.IsValid)
{
product.Id = _products.Max(p => p.Id) + 1;
product.CreatedAt = DateTime.UtcNow;
_products.Add(product);
return RedirectToAction(nameof(Index));
}
return View(product);
}
}
Punti chiave:
- IActionResult[]] è il tipo di ritorno. Può essere un , [, , ecc.
- I nomi di azione mappano a una cartella chiamata dal controller ([).
- L'azione ha due sovraccarichi: uno per GET (vedi il modulo) e uno per POST (presentazione del modulo di manuale).
- protegge contro la richiesta di falsificazione del sito.
Passo 5: Creazione di viste con Razor Syntax
Viste in diretta . Il layout condiviso è in .
Indice Visualizza – Visualizzare un elenco
Crea :
@model IEnumerable<MyMvcApp.Models.Product>
@{
ViewData["Title"] = "Product List";
}
<h2>@ViewData["Title"]</h2>
<table class="table table-striped">
<thead>
<tr>
<th>@Html.DisplayNameFor(model => model.Id)</th>
<th>@Html.DisplayNameFor(model => model.Name)</th>
<th>@Html.DisplayNameFor(model => model.Price)</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.Id</td>
<td>@item.Name</td>
<td>@item.Price.ToString("C")</td>
<td>
<a asp-action="Details" asp-route-id="@item.Id">Details</a>
</td>
</tr>
}
</tbody>
</table>
<p>
<a asp-action="Create" class="btn btn-primary">Create New Product</a>
</p>
Punte di richiamo[]: Usa per passare dall'HTML al C#, e /[] tag helper per generare URL.
Dettagli Vedi
Crea :
@model MyMvcApp.Models.Product
@{
ViewData["Title"] = "Product Details";
}
<h2>@Model.Name</h2>
<dl class="row">
<dt class="col-sm-2">@Html.DisplayNameFor(model => model.Id)</dt>
<dd class="col-sm-10">@Model.Id</dd>
<dt class="col-sm-2">@Html.DisplayNameFor(model => model.Price)</dt>
<dd class="col-sm-10">@Model.Price.ToString("C")</dd>
<dt class="col-sm-2">@Html.DisplayNameFor(model => model.Description)</dt>
<dd class="col-sm-10">@Model.Description</dd>
<dt class="col-sm-2">@Html.DisplayNameFor(model => model.CreatedAt)</dt>
<dd class="col-sm-10">@Model.CreatedAt</dd>
</dl>
<a asp-action="Index">Back to List</a>
Creare Vista con il modulo
Crea :
@model MyMvcApp.Models.Product
@{
ViewData["Title"] = "Create Product";
}
<h2>Create</h2>
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description"></label>
<textarea asp-for="Description" class="form-control"></textarea>
</div>
<button type="submit" class="btn btn-primary">Create</button>
<a asp-action="Index" class="btn btn-secondary">Cancel</a>
</form>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
I supporti per tag razor come generano campi formali con binding e validazione del modello.
Passo 6: Aggiungere Routing e Percorsi personalizzati
MVC utilizza il routing convenzionato per impostazione predefinita. Il percorso in [] mappe []. È inoltre possibile aggiungere l'attributo routing per un maggiore controllo. Ad esempio, nel controller:
[Route("products")]
public class ProductsController : Controller
{
[Route("")] // matches /products
[Route("index")] // matches /products/index
public IActionResult Index() { ... }
[Route("{id:int}")] // matches /products/5
public IActionResult Details(int id) { ... }
}
Questo approccio è utile per le API RESTful quando combinato con .
Passo 7: Utilizzo di ViewModels per dati complessi
Spesso è necessario passare più di un oggetto di dati a una vista, o includere proprietà extra (come liste selezionate, titoli di pagina).
namespace MyMvcApp.Models.ViewModels;
public class ProductIndexViewModel
{
public IEnumerable<Product> Products { get; set; }
public string SearchString { get; set; } = string.Empty;
public decimal MaxPrice { get; set; } = 10000;
}
Quindi regolare l'azione del controller per populare il modello di vista e passarlo alla vista. La vista utilizza e accede alle proprietà di conseguenza.
Passo 8: Convalida di esecuzione
ASP.NET Core MVC fornisce sia la convalida lato server che lato client tramite annotazioni di dati. Aggiungi [], , e attributi personalizzati. Nella visualizzazione , il visualizza messaggi di errore. L'attributo sul modulo di presentazione assicura solo l'azione reale assicura che solo i messaggi di presentazione sono veriti.
Per la logica di validazione personalizzata, implementare sul modello o creare una classe di validazione separata. La documentazione ufficiale ASP.NET Core validation[] copre questi modelli in dettaglio.
Passo 9: iniezione di dipendenza nei regolatori
Invece di dati di codifica dura, è possibile iniettare servizi (come un contesto di repository o database) nel costruttore del controller, che promuove l'accoppiamento e la testabilità allentati.
public class ProductsController : Controller
{
private readonly IProductRepository _repository;
public ProductsController(IProductRepository repository)
{
_repository = repository;
}
public IActionResult Index()
{
var products = _repository.GetAll();
return View(products);
}
}
Registra il repository in :
builder.Services.AddScoped<IProductRepository, ProductRepository>();
Il metodo registra già i controller per DI. Questo modello rende la vostra applicazione più pulita e più manutenbile. Vedi Guida di iniezione di dipendenza di Microsoft[] per altro.
Passo 10: Lavorare con i layout e le viste parziali
Per personalizzare, modificare il in []]]. È possibile definire le sezioni, o utilizzare viste parziali per i componenti UI riutilizzabili come navigazione, piè di pagina o rendering delle schede di prodotto.
Esempio di vista parziale :
@model Product
<div class="card">
<div class="card-body">
<h5 class="card-title">@Model.Name</h5>
<p class="card-text">Price: @Model.Price.ToString("C")</p>
<a asp-action="Details" asp-route-id="@Model.Id" class="btn btn-primary">Details</a>
</div>
</div>
Includilo in qualsiasi vista con .
Passo 11: Gestione degli errori e codici di stato
I controller dovrebbero gestire con grazia gli errori. Utilizzare blocchi o un gestore di eccezioni globale tramite middleware.
- per 404]
- per 400
- per errori del server.
Puoi anche aggiungere una visualizzazione di errore personalizzata: è già inclusa nel modello. Imposta in []] per reindirizzare le eccezioni in produzione.
Passo 12: Testare l'applicazione MVC
Il test è fondamentale. Utilizzare xUnit e il pacchetto per scrivere test di integrazione. Esempio per l'azione :
public class ProductsControllerTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;
public ProductsControllerTests(WebApplicationFactory<Program> factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task Index_ReturnsSuccessAndCorrectContentType()
{
var response = await _client.GetAsync("/products");
response.EnsureSuccessStatusCode();
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
}
Il controllore di unità prova con servizi ingannevoli per isolare la logica. ASP.NET Core documentazione di prova fornisce esempi estensivi.
Migliori Pratiche e Consigli Avanzati
- I controller di guardia sono sottili[: La logica aziendale appartiene ai servizi/repositori, non ai metodi di azione.
- Utilizza modelli di visualizzazione[[[]: Evitare di passare modelli di dominio direttamente alla vista; utilizzare modelli di visualizzazione dedicati per modellare i dati secondo le necessità.
- Aiutenti di tag di leva[: fanno più pulitore HTML e riducono gli errori nel binding di forma.
- Abilita la validazione del lato client[]: Include e bundle (già in ).
- Utilizzare azioni asincroni[[] per operazioni I/O-bound: con .
- Segui la tua applicazione[[]: Usa sempre HTTPS, token anti-forgery su moduli POST, e autorizzazione basata sul ruolo tramite .
Conclusioni
Implementare l'architettura MVC in ASP.NET Core vi dà una solida base per la costruzione di applicazioni web che sono organizzati, testabili e manutenbili. Separando modelli, viste e controller, è possibile lavorare su ogni componente in modo indipendente e scalare la vostra applicazione con fiducia. I passaggi in questa guida forniscono una completa passeggiata dalla creazione di progetto ai modelli di produzione-ready.