Visualizzazioni in ASP.NET Core MVC

Di Steve Smith e Dave Brock

Questo documento illustra le visualizzazioni usate nelle applicazioni ASP.NET Core MVC. Per informazioni sulle Razor pagine, vedere Introduzione alle Razor pagine in ASP.NET Core.

Nello schema MVC la visualizzazione gestisce la presentazione dei dati dell'app e l'interazione dell'utente. Una visualizzazione è un modello HTML con markup incorporato.Razor Razor markup è codice che interagisce con il markup HTML per produrre una pagina Web inviata al client.

In ASP.NET Core MVC, le visualizzazioni sono .cshtml file che usano il linguaggio di programmazione C# nel Razor markup. I file di visualizzazione sono in genere raggruppati in cartelle denominate per ognuno dei controller dell'app. Le cartelle vengono archiviate in una Views cartella nella radice dell'app:

Views folder in Solution Explorer of Visual Studio is open with the Home folder open to show About.cshtml, Contact.cshtml, and Index.cshtml files

Il Home controller è rappresentato da una Home cartella all'interno della Views cartella . La Home cartella contiene le visualizzazioni per le Aboutpagine Web , Contacte Index (home page). Quando un utente richiede una di queste tre pagine Web, le azioni del controller nel Home controller determinano quale delle tre visualizzazioni viene usata per compilare e restituire una pagina Web all'utente.

Usare i layout per offrire sezioni di pagine Web coerenti e ridurre la ripetizione del codice. I layout spesso includono l'intestazione, elementi di navigazione e menu, nonché il piè di pagina. L'intestazione e il piè di pagina in genere contengono il markup boilerplate per molti elementi di metadati e i collegamenti alle risorse di script e stile. I layout consentono di evitare questo markup boilerplate nelle visualizzazioni.

Le visualizzazioni parziali riducono la duplicazione del codice grazie alla gestione delle parti riutilizzabili delle visualizzazioni. Una visualizzazione parziale è ad esempio utile per la biografia di un autore nel sito Web di un blog che viene mostrata in diverse visualizzazioni. Nel caso della biografia di un autore, il contenuto di visualizzazione è ordinario e non richiede l'esecuzione di codice per produrre il contenuto per la pagina Web. Il contenuto della biografia di un autore è disponibile per la visualizzazione tramite la sola associazione di modelli, quindi l'uso di una visualizzazione parziale per questo tipo di contenuto è ideale.

I componenti di visualizzazione sono simili alle visualizzazioni parziali nel senso che consentono di ridurre il codice ripetitivo, ma sono adatti per visualizzare contenuto che richiede l'esecuzione di codice nel server al fine di eseguire il rendering della pagina Web. I componenti di visualizzazione sono utili quando il contenuto sottoposto a rendering richiede l'interazione con il database, ad esempio nel caso del carrello acquisti di un sito Web. I componenti di visualizzazione non si limitano all'associazione di modelli per produrre l'output della pagina Web.

Vantaggi dell'uso delle visualizzazioni

Le visualizzazioni consentono di stabilire una separazione dei concetti all'interno di un'app MVC separando il markup dell'interfaccia utente da altre parti dell'app. La progettazione SoC rende l'app modulare offrendo diversi vantaggi:

  • L'app risulta più facile da gestire perché è organizzata meglio. Le visualizzazioni sono in genere raggruppate per funzionalità dell'app. Individuare le visualizzazioni correlate quando si lavora su una funzionalità risulterà quindi più semplice.
  • Le parti dell'app sono a regime di controllo libero. È possibile compilare e aggiornare le visualizzazioni dell'app separatamente dai componenti di logica di business e accesso ai dati. È possibile modificare le visualizzazioni dell'app senza dover necessariamente aggiornare altre parti dell'app.
  • Poiché le visualizzazioni sono unità distinte, testare le parti dell'interfaccia utente dell'app risulta più semplice.
  • Grazie alla migliore organizzazione, le probabilità che le sezioni dell'interfaccia utente vengano ripetute accidentalmente sono minori.

Creazione di una visualizzazione

Le visualizzazioni specifiche di un controller vengono create nella Views/[ControllerName] cartella . Le visualizzazioni condivise tra i controller vengono inserite nella Views/Shared cartella . Per creare una visualizzazione, aggiungere un nuovo file e assegnargli lo stesso nome dell'azione del controller associata con l'estensione di .cshtml file. Per creare una visualizzazione corrispondente all'azione About nel Home controller, creare un About.cshtml file nella Views/Home cartella :

@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>

<p>Use this area to provide additional information.</p>

Razor il markup inizia con il @ simbolo. Eseguire istruzioni C# inserendo il codice C# all'interno Razor di blocchi di codice impostati da parentesi graffe ({ ... }). Vedere ad esempio l'assegnazione di "About" a ViewData["Title"] illustrato sopra. È possibile visualizzare i valori in HTML facendo semplicemente riferimento al valore con il simbolo @. Vedere il contenuto degli elementi <h2> e <h3> riportati sopra.

Il contenuto della visualizzazione illustrato sopra è solo una parte dell'intera pagina Web di cui viene eseguito il rendering per l'utente. Il resto del layout della pagina e altri aspetti comuni della visualizzazione sono specificati in altri file. Per altre informazioni, vedere l'argomento Layout.

Modalità di scelta delle visualizzazioni da parte dei controller

Le viste vengono in genere restituite dalle azioni come ViewResult, che è un tipo di ActionResult. Il metodo dell'azione può creare e restituire direttamente un elemento ViewResult, ma questa procedura non è molto comune. Poiché la maggior parte dei controller eredita da Controller, è sufficiente usare il View metodo helper per restituire :ViewResult

HomeController.cs:

public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";

    return View();
}

Quando viene restituita questa azione, viene eseguito il rendering della About.cshtml visualizzazione illustrata nell'ultima sezione come pagina Web seguente:

About page rendered in the Edge browser

Il metodo helper View ha diversi overload. È possibile specificare:

  • Una visualizzazione esplicita da restituire:

    return View("Orders");
    
  • Un modello da passare alla visualizzazione:

    return View(Orders);
    
  • Una visualizzazione e un modello:

    return View("Orders", Orders);
    

Individuazione delle visualizzazioni

Quando un'azione restituisce una visualizzazione viene eseguito un processo denominato individuazione delle visualizzazioni. Questo processo determina il file di visualizzazione che verrà usato in base al nome della visualizzazione.

In base al comportamento predefinito, il metodo View (return View();) restituisce una visualizzazione con lo stesso nome del metodo dell'azione dal quale viene chiamato. Ad esempio, il AboutActionResult nome del metodo del controller viene usato per cercare un file di visualizzazione denominato About.cshtml. Prima di tutto, il runtime cerca nella Views/[ControllerName] cartella la visualizzazione. Se non trova una visualizzazione corrispondente, cerca nella Shared cartella la vista.

La restituzione implicita di ViewResult con return View(); o il passaggio esplicito del nome della visualizzazione al metodo View con return View("<ViewName>"); non sono rilevanti. In entrambi i casi, l'individuazione delle visualizzazioni cercherà un file di visualizzazione corrispondente in quest'ordine:

  1. Views/\[ControllerName]/\[ViewName].cshtml
  2. Views/Shared/\[ViewName].cshtml

È possibile fornire il percorso di un file di visualizzazione anziché il nome di una visualizzazione. Se si usa un percorso assoluto a partire dalla radice dell'app (facoltativamente a partire da "/" o "~/"), è necessario specificare l'estensione .cshtml :

return View("Views/Home/About.cshtml");

È anche possibile usare un percorso relativo per specificare le visualizzazioni in directory diverse senza l'estensione .cshtml . All'interno di HomeControllerè possibile restituire la Index visualizzazione delle visualizzazioni Manage con un percorso relativo:

return View("../Manage/Index");

In modo analogo, è possibile indicare la directory corrente specifica dei controller con il prefisso "./":

return View("./About");

Le visualizzazioni parziali e i componenti di visualizzazione usano meccanismi di individuazione simili, ma non identici.

È possibile personalizzare la convenzione predefinita per il modo in cui le visualizzazioni si trovano all'interno dell'app usando un oggetto personalizzato IViewLocationExpander.

L'individuazione delle visualizzazioni si basa sull'individuazione dei file di visualizzazione in base al nome del file. Se il file system sottostante prevede la distinzione tra maiuscole e minuscole, per i nomi delle visualizzazioni verrà probabilmente applicata questa distinzione. Per la compatibilità tra sistemi operativi, rispettare la distinzione maiuscole/minuscole tra i nomi di controller e azioni e i nomi di cartelle e file di visualizzazione associati. In caso di errore relativo a un file di visualizzazione non trovato durante l'uso di un file system con distinzione tra maiuscole e minuscole, verificare che tra il nome del file di visualizzazione richiesto e il nome effettivo del file di visualizzazione l'uso delle maiuscole e minuscole corrisponda.

Per manutenibilità e chiarezza, seguire le procedure consigliate relative all'organizzazione della struttura di file per le visualizzazioni in modo da riflettere le relazioni tra controller, azioni e visualizzazioni.

Passare i dati alle visualizzazioni

Passare i dati alle visualizzazioni usando diversi approcci:

  • Dati fortemente tipizzati: viewmodel
  • Dati tipizzato in modo debole
    • ViewData (ViewDataAttribute)
    • ViewBag

Dati fortemente tipizzati: (viewmodel)

L'approccio più efficace consiste nello specificare un tipo di modello nella visualizzazione. Questo modello è comunemente noto come viewmodel. Un'istanza del tipo viewmodel viene passato alla visualizzazione dall'azione.

L'uso di un viewmodel per passare i dati a una visualizzazione consente a quest'ultima di trarre vantaggio dal controllo con tipizzazione forte. L'espressione tipizzazione forte o fortemente tipizzato indica che ogni variabile e costante ha un tipo definito in modo esplicito, ad esempio string, int o DateTime. La validità dei tipi usati in una visualizzazione viene verificata in fase di compilazione.

In Visual Studio e Visual Studio Code i membri delle classi fortemente tipizzati vengono elencati usando una funzionalità denominata IntelliSense. Per visualizzare le proprietà di un elemento viewmodel, digitare il nome della variabile per l'elemento viewmodel seguito da un punto (.). Ciò consente di scrivere il codice più velocemente con un minor numero di errori.

Specificare un modello usando la direttiva @model. Usare il modello con @Model:

@model WebApplication1.ViewModels.Address

<h2>Contact</h2>
<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

Per fornire il modello alla visualizzazione, il controller lo passa come parametro:

public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    var viewModel = new Address()
    {
        Name = "Microsoft",
        Street = "One Microsoft Way",
        City = "Redmond",
        State = "WA",
        PostalCode = "98052-6399"
    };

    return View(viewModel);
}

Non ci sono limitazioni ai tipi di modello che è possibile fornire a una visualizzazione. È consigliabile usare viewmodel Plain Old CLR Object (POCO) per i quali non siano stati definiti comportamenti (metodi) o ne siano stati definiti solo alcuni. In genere, le classi viewmodel vengono archiviate nella Models cartella o in una cartella separata ViewModels nella radice dell'app. Il Address modello di visualizzazione usato nell'esempio precedente è un modello di visualizzazione POCO archiviato in un file denominato Address.cs:

namespace WebApplication1.ViewModels
{
    public class Address
    {
        public string Name { get; set; }
        public string Street { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string PostalCode { get; set; }
    }
}

Nulla impedisce di usare le stesse classi per i tipi viewmodel e i tipi del modello aziendale. L'uso di modelli separati consente tuttavia la variazione delle visualizzazioni indipendentemente dalle parti relative alla logica di business e all'accesso ai dati dell'app. La separazione di modelli e viewmodel offre anche vantaggi in termini di sicurezza quando i modelli usano l'associazione di modelli e la convalida per i dati inviati all'app dall'utente.

Dati tipizzato in modo debole (ViewData, [ViewData] attributo e ViewBag)

ViewBagnon è disponibile per impostazione predefinita per l'uso nelle Razor classi PagesPageModel.

Oltre alle visualizzazioni fortemente tipizzate, le visualizzazioni hanno accesso a una raccolta di dati con tipizzazione debole o debolmente tipizzati. A differenza della tipizzazione forte, la tipizzazione debole, o l'espressione debolmente tipizzato, indica che il tipo di dati in uso non viene dichiarato in modo esplicito. È possibile usare la raccolta di dati con tipizzazione debole per passare piccole quantità di dati da e verso i controller e le visualizzazioni.

Passaggio dei dati tra... Esempio
Un controller e una visualizzazione Popolamento di dati in un elenco a discesa.
Una visualizzazione e una visualizzazione Layout Impostazione del contenuto dell'elemento <title> nella visualizzazione layout da un file di visualizzazione.
Una visualizzazione parziale e una visualizzazione Widget che visualizza i dati in base alla pagina Web richiesta dall'utente.

È possibile fare riferimento a questa raccolta tramite le proprietà ViewData o ViewBag nei controller e nelle visualizzazioni. La proprietà ViewData è un dizionario di oggetti con tipizzazione debole. La proprietà ViewBag è un wrapper di ViewData che offre proprietà dinamiche per la raccolta ViewData sottostante. Nota: le ricerche chiave non fanno distinzione tra maiuscole e minuscole per ViewData e ViewBag.

ViewData e ViewBag vengono risolte in modo dinamico in fase di esecuzione. Poiché non offrono il controllo del tipo in fase di compilazione, entrambe sono in genere più soggette a errori rispetto all'uso di un elemento viewmodel. Per questo motivo, alcuni sviluppatori preferiscono non usare mai ViewData e ViewBag o usarle il meno possibile.

ViewData

ViewData è un ViewDataDictionary oggetto a cui si accede tramite string chiavi. I dati di tipo stringa possono essere archiviati e usati direttamente, senza la necessità di un cast, ma è necessario eseguire il cast di altri valori dell'oggetto ViewData in tipi specifici quando vengono estratti. È possibile usare ViewData per passare i dati dai controller alle visualizzazioni e al loro interno, inclusi visualizzazioni parziali e layout.

Nell'esempio seguente vengono impostati i valori per una formula di saluto e un indirizzo usando ViewData in un'azione:

public IActionResult SomeAction()
{
    ViewData["Greeting"] = "Hello";
    ViewData["Address"]  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}

Lavorare con i dati in una visualizzazione:

@{
    // Since Address isn't a string, it requires a cast.
    var address = ViewData["Address"] as Address;
}

@ViewData["Greeting"] World!

<address>
    @address.Name<br>
    @address.Street<br>
    @address.City, @address.State @address.PostalCode
</address>

Attributo [ViewData]

Un altro approccio che usa è ViewDataDictionaryViewDataAttribute. Le proprietà nei controller o Razor nei modelli di pagina contrassegnati con l'attributo [ViewData] hanno i relativi valori archiviati e caricati dal dizionario.

Nell'esempio seguente il Home controller contiene una Title proprietà contrassegnata con [ViewData]. Il metodo About imposta il titolo per la visualizzazione About (Informazioni):

public class HomeController : Controller
{
    [ViewData]
    public string Title { get; set; }

    public IActionResult About()
    {
        Title = "About Us";
        ViewData["Message"] = "Your application description page.";

        return View();
    }
}

Nel layout il titolo viene letto dal dizionario ViewData:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

ViewBag

ViewBagnon è disponibile per impostazione predefinita per l'uso nelle Razor classi PagesPageModel.

ViewBag è un Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData oggetto che fornisce l'accesso dinamico agli oggetti archiviati in ViewData. ViewBag può risultare più comodo da usare poiché non richiede l'esecuzione del cast. Nell'esempio seguente viene illustrato come usare ViewBag con lo stesso risultato che si ottiene con l'uso di ViewData descritto in precedenza:

public IActionResult SomeAction()
{
    ViewBag.Greeting = "Hello";
    ViewBag.Address  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}
@ViewBag.Greeting World!

<address>
    @ViewBag.Address.Name<br>
    @ViewBag.Address.Street<br>
    @ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>

Uso ViewData e ViewBag simultaneo

ViewBagnon è disponibile per impostazione predefinita per l'uso nelle Razor classi PagesPageModel.

Dal momento che ViewData e ViewBag fanno riferimento alla stessa raccolta ViewData sottostante, è possibile usare ViewData e ViewBag e combinarle durante la lettura e la scrittura dei valori.

Impostare il titolo usando ViewBag e la descrizione usando ViewData nella parte superiore di una About.cshtml visualizzazione:

@{
    Layout = "/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About Contoso";
    ViewData["Description"] = "Let us tell you about Contoso's philosophy and mission.";
}

Leggere le proprietà ma invertire l'uso di ViewData e ViewBag. _Layout.cshtml Nel file ottenere il titolo usando ViewData e ottenere la descrizione usando ViewBag:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"]</title>
    <meta name="description" content="@ViewBag.Description">
    ...

Tenere presente che per ViewData non è necessario eseguire il cast delle stringhe. È possibile usare @ViewData["Title"] senza eseguire il cast.

L'uso simultaneo di ViewData e ViewBag funziona, così come funziona la combinazione di entrambe durante la lettura e la scrittura delle proprietà. Viene eseguito il rendering del markup seguente:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>About Contoso</title>
    <meta name="description" content="Let us tell you about Contoso's philosophy and mission.">
    ...

Riepilogo delle differenze tra ViewData e ViewBag

ViewBagnon è disponibile per impostazione predefinita per l'uso nelle Razor classi PagesPageModel.

  • ViewData
    • Deriva da ViewDataDictionary, quindi dispone di proprietà del dizionario che possono essere utili, ad esempio ContainsKey, AddRemove, e Clear.
    • Le chiavi nel dizionario sono stringhe, pertanto lo spazio vuoto è consentito. Esempio: ViewData["Some Key With Whitespace"]
    • Per usare ViewData è necessario eseguire il cast di tutti i tipi diversi da string nella visualizzazione.
  • ViewBag
    • Deriva da Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.DynamicViewData, in modo da consentire la creazione di proprietà dinamiche usando la notazione punto (@ViewBag.SomeKey = <value or object>) e non è necessario eseguire il cast. La sintassi di ViewBag velocizza l'aggiunta in controller e visualizzazioni.
    • Verificare la presenza di valori Null è più facile. Esempio: @ViewBag.Person?.Name

Quando usare ViewData o ViewBag

ViewData e ViewBag sono entrambi approcci ugualmente validi per passare piccole quantità di dati tra controller e visualizzazioni. La scelta di quello da usare è basata sulla preferenza. È possibile combinare oggetti ViewData e ViewBag. La lettura e la gestione del codice risulteranno tuttavia più semplici con un unico approccio usato in modo coerente. Entrambi gli approcci vengono risolti in modo dinamico in fase di esecuzione e possono quindi determinare errori di runtime. Alcuni team di sviluppo li evitano.

Visualizzazioni dinamiche

Le visualizzazioni che non dichiarano un tipo di modello usando @model ma a cui è stata passata l'istanza di un modello, ad esempio return View(Address);, possono fare riferimento alle proprietà dell'istanza in modo dinamico:

<address>
    @Model.Street<br>
    @Model.City, @Model.State @Model.PostalCode<br>
    <abbr title="Phone">P:</abbr> 425.555.0100
</address>

Questa funzionalità offre flessibilità ma non offre la protezione della compilazione o IntelliSense. Se la proprietà non esiste, in fase di esecuzione la generazione della pagina Web non riesce.

Altre funzionalità delle visualizzazioni

Gli helper tag semplificano l'aggiunta del comportamento sul lato server ai tag HTML esistenti. Grazie all'uso degli helper tag, è possibile evitare di scrivere codice personalizzato o helper all'interno delle visualizzazioni. Gli helper tag vengono applicati come attributi agli elementi HTML e vengono ignorati dagli editor che non sono in grado di elaborarli. Ciò consente di modificare ed eseguire il rendering del markup delle visualizzazioni in un'ampia gamma di strumenti.

La generazione di markup HTML personalizzato può essere ottenuta con molti helper HTML predefiniti. Una logica dell'interfaccia utente più complessa può essere gestita dai componenti di visualizzazione. I componenti di visualizzazione offrono lo stesso tipo di progettazione SoC offerta dai controller e dalle visualizzazioni. Possono eliminare la necessità di azioni e visualizzazioni che gestiscono i dati usati da elementi comuni dell'interfaccia utente.

Come molti altri aspetti di ASP.NET Core, le visualizzazioni supportano l'inserimento di dipendenze, consentendo che i servizi siano inseriti nelle visualizzazioni.

Isolamento CSS

Isolare gli stili CSS in singole pagine, visualizzazioni e componenti per ridurre o evitare:

  • Dipendenze da stili globali che possono risultare difficili da gestire.
  • Conflitti di stile nel contenuto annidato.

Per aggiungere un file CSS con ambito per una pagina o una visualizzazione, inserire gli stili CSS in un file .cshtml.css complementare corrispondente al nome del file .cshtml. Nell'esempio seguente un file Index.cshtml.css fornisce stili CSS applicati solo alla pagina o alla visualizzazione Index.cshtml.

Pages/Index.cshtml.css (Razor Pages) o Views/Index.cshtml.css (MVC):

h1 {
    color: red;
}

L'isolamento CSS si verifica in fase di compilazione. Il framework riscrive i selettori CSS in modo che corrispondano al markup sottoposto a rendering dalle pagine o dalle visualizzazioni dell'app. Gli stili CSS riscritti vengono raggruppati in bundle e prodotti come asset statici, {APP ASSEMBLY}.styles.css. Il segnaposto {APP ASSEMBLY} è il nome dell'assembly del progetto. Nel layout dell'app viene inserito un collegamento agli stili CSS in bundle.

Nel contenuto <head> del file Pages/Shared/_Layout.cshtml (RazorPages) o Views/Shared/_Layout.cshtml (MVC) dell'app aggiungere o confermare la presenza del collegamento agli stili CSS in bundle:

<link rel="stylesheet" href="~/{APP ASSEMBLY}.styles.css" />

Nell'esempio seguente il nome dell'assembly dell'app è WebApp:

<link rel="stylesheet" href="WebApp.styles.css" />

Gli stili definiti in un file CSS con ambito vengono applicati solo all'output sottoposto a rendering del file corrispondente. Nell'esempio precedente tutte le dichiarazioni CSS h1 definite altrove nell'app non sono in conflitto con lo stile dell'intestazione di Index. Le regole di cascata o ereditarietà degli stili CSS rimangono effettive per i file CSS con ambito. Ad esempio, gli stili applicati direttamente a un elemento <h1> nel file Index.cshtml sostituiscono gli stili del file CSS con ambito in Index.cshtml.css.

Nota

Per garantire l'isolamento degli stili CSS quando si verifica il raggruppamento in bundle, l'importazione di CSS nei blocchi di codiceRazor non è supportata.

L'isolamento CSS si applica solo agli elementi HTML. L'isolamento CSS non è supportato per gli helper tag.

All'interno del file CSS in bundle, ogni pagina, visualizzazione o componente Razor è associato a un identificatore di ambito nel formato b-{STRING}, dove il segnaposto {STRING} è una stringa di dieci caratteri generata dal framework. L'esempio seguente mostra lo stile dell'elemento <h1> precedente nella pagina Index di un'app Razor Pages:

/* /Pages/Index.cshtml.rz.scp.css */
h1[b-3xxtam6d07] {
    color: red;
}

Nella pagina Index in cui viene applicato lo stile CSS dal file in bundle l'identificatore di ambito viene aggiunto come attributo HTML:

<h1 b-3xxtam6d07>

L'identificatore è univoco per un'app. In fase di compilazione viene creato un bundle di progetto con la convenzione {STATIC WEB ASSETS BASE PATH}/Project.lib.scp.css, dove il segnaposto {STATIC WEB ASSETS BASE PATH} è il percorso di base degli asset Web statici.

Se vengono utilizzati altri progetti, ad esempio pacchetti NuGet o librerie di classi Razor, il file in bundle:

  • Fa riferimento agli stili usando le importazioni CSS.
  • Non viene pubblicato come asset Web statico dell'app che utilizza gli stili.

Supporto dei preprocessori CSS

I preprocessori CSS sono utili per migliorare lo sviluppo di CSS tramite l'utilizzo di funzionalità come variabili, annidamenti, moduli, mixin ed ereditarietà. Anche se l'isolamento CSS non supporta in modo nativo i preprocessori CSS, ad esempio Sass o Less, l'integrazione dei preprocessori CSS è facile purché la relativa compilazione si verifichi prima che il framework riscriva i selettori CSS durante il processo di compilazione. Usando Visual Studio, ad esempio, configurare la compilazione del preprocessore esistente come attività Prima di compilare in Esplora esecuzione attività.

Molti pacchetti NuGet di terze parti, ad esempio AspNetCore.SassCompiler, possono compilare file SASS/SCSS all'inizio del processo di compilazione prima che si verifichi l'isolamento CSS, quindi non è necessaria alcuna configurazione aggiuntiva.

Configurazione dell'isolamento CSS

L'isolamento CSS consente di configurare alcuni scenari avanzati, ad esempio quando sono presenti dipendenze da strumenti o flussi di lavoro esistenti.

Personalizzare il formato dell'identificatore di ambito

In questa sezione il segnaposto {Pages|Views} corrisponde a Pages per le app Razor Pages o a Views per le app MVC.

Per impostazione predefinita, gli identificatori di ambito usano il formato b-{STRING}, dove il segnaposto {STRING} è una stringa di dieci caratteri generata dal framework. Per personalizzare il formato dell'identificatore di ambito, aggiornare il file di progetto a un modello desiderato:

<ItemGroup>
  <None Update="{Pages|Views}/Index.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Nell'esempio precedente il file CSS generato per Index.cshtml.css cambia il relativo identificatore di ambito da b-{STRING} a custom-scope-identifier.

Usare gli identificatori di ambito per ottenere l'ereditarietà con i file CSS con ambito. Nell'esempio di file di progetto seguente un file BaseView.cshtml.css contiene stili comuni tra visualizzazioni. Un file DerivedView.cshtml.css eredita questi stili.

<ItemGroup>
  <None Update="{Pages|Views}/BaseView.cshtml.css" CssScope="custom-scope-identifier" />
  <None Update="{Pages|Views}/DerivedView.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Usare l'operatore carattere jolly (*) per condividere gli identificatori di ambito tra più file:

<ItemGroup>
  <None Update="{Pages|Views}/*.cshtml.css" CssScope="custom-scope-identifier" />
</ItemGroup>

Cambiare il percorso di base per gli asset Web statici

Il file CSS con ambito viene generato alla radice dell'app. Nel file di progetto usare la proprietà StaticWebAssetBasePath per cambiare il percorso predefinito. L'esempio seguente inserisce il file CSS con ambito e il resto degli asset dell'app nel percorso _content:

<PropertyGroup>
  <StaticWebAssetBasePath>_content/$(PackageId)</StaticWebAssetBasePath>
</PropertyGroup>

Disabilitare il raggruppamento automatico in bundle

Per rifiutare esplicitamente il modo in cui il framework pubblica e carica i file con ambito in fase di esecuzione, usare la proprietà DisableScopedCssBundling. Quando si usa questa proprietà, altri strumenti o processi sono responsabili dell'acquisizione dei file CSS isolati dalla directory obj, oltre che delle relative operazioni di pubblicazione e caricamento in fase di esecuzione:

<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

Supporto della libreria di classi Razor (RCL)

Quando una libreria di classi Razor (RCL) fornisce stili isolati, l'attributo href del tag <link> punta a {STATIC WEB ASSET BASE PATH}/{PACKAGE ID}.bundle.scp.css, dove i segnaposto sono:

  • {STATIC WEB ASSET BASE PATH}: il percorso di base degli asset Web statici.
  • {PACKAGE ID}: l'identificatore del pacchetto della libreria. L'identificatore del pacchetto viene impostato per impostazione predefinita sul nome dell'assembly del progetto se non viene specificato nel file di progetto.

Nell'esempio seguente:

  • Il percorso di base degli asset Web statici è _content/ClassLib.
  • Il nome dell'assembly della libreria di classi è ClassLib.

Pages/Shared/_Layout.cshtml (Razor Pages) o Views/Shared/_Layout.cshtml (MVC):

<link href="_content/ClassLib/ClassLib.bundle.scp.css" rel="stylesheet">

Per altre informazioni sulle librerie di classi Razor (RCL), vedere gli articoli seguenti:

Per informazioni sull'isolamento CSS Blazor, vedere Isolamento CSS di Blazor in ASP.NET Core.