Visualizzazioni parziali in ASP.NET Core

Di Steve Smith, Maher JENDOUBI, Rick Anderson e Scott Sauber

Una visualizzazione parziale è un Razor file di markup (.cshtml) senza una @page direttiva che esegue il rendering dell'output HTML all'interno dell'output di rendering di un altro file di markup.

Il termine visualizzazione parziale viene usato quando si sviluppa un'app MVC, in cui i file di markup vengono chiamati visualizzazioni o un'app Razor Pages, in cui vengono chiamati pagine i file di markup. Questo argomento si riferisce in modo generico alle visualizzazioni MVC e Razor alle pagine Pages come file di markup.

Visualizzare o scaricare il codice di esempio (procedura per il download)

Quando usare le visualizzazioni parziali

Le visualizzazioni parziali sono un modo efficace di:

  • Suddividere file di markup di grandi dimensioni in componenti più piccoli.

    In un file di markup complesso e di grandi dimensioni, composto da diverse parti logiche, gestire ognuna di queste parti isolate in una visualizzazione parziale offre dei vantaggi. Il codice del file di markup è infatti gestibile in quanto il markup contiene solo la struttura della pagina complessiva e riferimenti alle visualizzazioni parziali.

  • Ridurre la duplicazione del contenuto di markup comune nei file di markup.

    Quando nei vari file di markup vengono usati gli stessi elementi di markup, una visualizzazione parziale rimuove la duplicazione del contenuto di markup in un file di visualizzazione parziale. Quando il markup viene modificato nella visualizzazione parziale, aggiorna l'output sottoposto a rendering dei file di markup che usano la visualizzazione parziale.

Le visualizzazioni parziali non devono essere usate per gestire gli elementi di layout comuni. Gli elementi comuni del layout devono essere specificati nei file _Layout.cshtml.

Non usare una visualizzazione parziale in cui per il rendering del markup è necessaria una logica di rendering complessa o l'esecuzione di codice. Invece di una visualizzazione parziale, usare un componente di visualizzazione.

Dichiarare le visualizzazioni parziali

Una visualizzazione parziale è un .cshtml file di markup senza una @page direttiva mantenuta all'interno della cartella Views (MVC) o Pages (Razor Pages).

In ASP.NET Core MVC, l'elemento ViewResult di un controller è in grado di restituire una visualizzazione o una visualizzazione parziale. In Razor Pages un PageModel oggetto può restituire una visualizzazione parziale rappresentata come PartialViewResult oggetto . Il riferimento e il rendering delle visualizzazioni parziali sono descritti nella sezione Riferimento a una visualizzazione parziale.

A differenza del rendering della pagina o della visualizzazione MVC, una visualizzazione parziale non esegue _ViewStart.cshtml. Per altre informazioni su _ViewStart.cshtml, vedere Layout in ASP.NET Core.

I nomi dei file di visualizzazione parziale iniziano spesso con un carattere di sottolineatura (_). Questa convenzione di denominazione non è obbligatoria, ma è utile per differenziare visivamente le visualizzazioni parziali dalle visualizzazioni e dalle pagine.

Una visualizzazione parziale è un .cshtml file di markup gestito all'interno della cartella Views .

L'elemento ViewResult di un controller è in grado di restituire una visualizzazione o una visualizzazione parziale. Il riferimento e il rendering delle visualizzazioni parziali sono descritti nella sezione Riferimento a una visualizzazione parziale.

A differenza del rendering della visualizzazione MVC, una visualizzazione parziale non esegue _ViewStart.cshtml. Per altre informazioni su _ViewStart.cshtml, vedere Layout in ASP.NET Core.

I nomi dei file di visualizzazione parziale iniziano spesso con un carattere di sottolineatura (_). Questa convenzione di denominazione non è obbligatoria, ma è utile per differenziare visivamente le visualizzazioni parziali dalle visualizzazioni.

Riferimento a una visualizzazione parziale

Usare una visualizzazione parziale in un Razor pagemodel pagine

In ASP.NET Core 2.0 o 2.1, il metodo del gestore seguente esegue il rendering della visualizzazione parziale _AuthorPartialRP.cshtml alla risposta:

public IActionResult OnGetPartial() =>
    new PartialViewResult
    {
        ViewName = "_AuthorPartialRP",
        ViewData = ViewData,
    };

In ASP.NET Core 2.2 o versioni successive, un metodo del gestore può chiamare in alternativa il metodo Partial per produrre un oggetto PartialViewResult:

public IActionResult OnGetPartial() =>
    Partial("_AuthorPartialRP");

Usare una visualizzazione parziale in un file di markup

All'interno di un file di markup è possibile fare riferimento a una visualizzazione parziale in diversi modi. È consigliabile usare uno dei metodi asincroni seguenti nelle app:

All'interno di un file di markup è possibile fare riferimento a una visualizzazione parziale in due modi:

È consigliabile usare l'helper HTML asincrono nelle app.

Helper tag Partial

L'helper tag Partial richiede ASP.NET Core 2.1 o versioni successive.

Questo helper esegue il rendering del contenuto in modo asincrono e usa una sintassi HTML:

<partial name="_PartialName" />

Quando è presente un'estensione di file, l'helper tag fa riferimento a una visualizzazione parziale che deve essere contenuta nella stessa cartella in cui si trova il file di markup che chiama la visualizzazione parziale:

<partial name="_PartialName.cshtml" />

L'esempio seguente fa riferimento a una visualizzazione parziale dalla radice dell'app. I percorsi che iniziano con una tilde e una barra (~/) o con una barra (/) fanno riferimento alla radice dell'app:

Razor Pages

<partial name="~/Pages/Folder/_PartialName.cshtml" />
<partial name="/Pages/Folder/_PartialName.cshtml" />

MVC

<partial name="~/Views/Folder/_PartialName.cshtml" />
<partial name="/Views/Folder/_PartialName.cshtml" />

L'esempio seguente fa riferimento a una visualizzazione parziale con un percorso relativo:

<partial name="../Account/_PartialName.cshtml" />

Per altre informazioni, vedere Helper tag parziale in ASP.NET Core.

Helper HTML asincrono

Quando si usa un helper HTML, la procedura consigliata consiste nell'usare PartialAsync. PartialAsync restituisce un tipo IHtmlContent di cui è stato eseguito il wrapping in un Task<TResult>. Il riferimento al metodo avviene facendo precedere la chiamata attesa da un carattere @:

@await Html.PartialAsync("_PartialName")

Quando è presente l'estensione di file, l'helper HTML fa riferimento a una visualizzazione parziale che deve essere contenuta nella stessa cartella in cui si trova il file di markup che chiama la visualizzazione parziale:

@await Html.PartialAsync("_PartialName.cshtml")

L'esempio seguente fa riferimento a una visualizzazione parziale dalla radice dell'app. I percorsi che iniziano con una tilde e una barra (~/) o con una barra (/) fanno riferimento alla radice dell'app:

Razor Pages

@await Html.PartialAsync("~/Pages/Folder/_PartialName.cshtml")
@await Html.PartialAsync("/Pages/Folder/_PartialName.cshtml")

MVC

@await Html.PartialAsync("~/Views/Folder/_PartialName.cshtml")
@await Html.PartialAsync("/Views/Folder/_PartialName.cshtml")

L'esempio seguente fa riferimento a una visualizzazione parziale con un percorso relativo:

@await Html.PartialAsync("../Account/_LoginPartial.cshtml")

In alternativa è possibile eseguire il rendering di una visualizzazione parziale con RenderPartialAsync. Questo metodo non restituisce un IHtmlContent. Trasmette l'output sottoposto a rendering direttamente alla risposta. Poiché il metodo non restituisce un risultato, deve essere chiamato all'interno di un Razor blocco di codice:

@{
    await Html.RenderPartialAsync("_AuthorPartial");
}

Poiché RenderPartialAsync trasmette il contenuto sottoposto a rendering, assicura prestazioni migliori in alcuni scenari. In situazioni in cui le prestazioni sono importanti, eseguire il benchmark della pagina usando entrambi gli approcci e usare quindi l'approccio che genera una risposta più rapidamente.

Helper HTML sincrono

Partial e RenderPartial sono gli equivalenti sincroni rispettivamente di PartialAsync e RenderPartialAsync. L'uso degli equivalenti sincroni non è consigliabile perché in alcuni scenari causano un deadlock. I metodi sincroni verranno rimossi in una versione futura.

Importante

Se è necessario eseguire codice, usare un componente di visualizzazione invece di una visualizzazione parziale.

La chiamata di Partial o RenderPartial genera un avviso di Visual Studio Analyzer. Ad esempio, la presenza di Partial produce il messaggio di avviso seguente:

L'uso di IHtmlHelper.Partial potrebbe determinare deadlock dell'applicazione. È consigliabile usare l'helper tag <Partial> o IHtmlHelper.PartialAsync.

Sostituire le chiamate a @Html.Partial con @await Html.PartialAsync o con l'helper tag Partial. Per altre informazioni sulla migrazione dell'helper tag Partial, vedere Eseguire la migrazione da un helper HTML.

Individuazione delle visualizzazioni parziali

Quando si fa riferimento a una visualizzazione parziale per nome senza un'estensione di file, viene eseguita una ricerca nelle posizioni seguenti, nell'ordine indicato:

Razor Pages

  1. Cartella della pagina attualmente in esecuzione
  2. Grafico delle directory sopra la cartella della pagina
  3. /Shared
  4. /Pages/Shared
  5. /Views/Shared

MVC

  1. /Areas/<Area-Name>/Views/<Controller-Name>
  2. /Areas/<Area-Name>/Views/Shared
  3. /Views/Shared
  4. /Pages/Shared
  1. /Areas/<Area-Name>/Views/<Controller-Name>
  2. /Areas/<Area-Name>/Views/Shared
  3. /Views/Shared

Le convenzioni seguenti si applicano all'individuazione delle visualizzazioni parziali:

  • Sono consentite visualizzazioni parziali diverse con lo stesso nome purché si trovino in cartelle diverse.
  • Quando si fa riferimento a una visualizzazione parziale per nome senza un'estensione di file e la visualizzazione parziale è presente sia nella cartella del chiamante sia nella cartella Shared, viene usata la visualizzazione parziale nella cartella del chiamante. Se la visualizzazione parziale non è presente nella cartella del chiamante, viene usata la visualizzazione parziale nella cartella Shared. Le visualizzazioni parziali nella cartella Shared sono dette visualizzazioni parziali condivise o visualizzazioni parziali predefinite.
  • Le visualizzazioni parziali possono essere concatenati: una visualizzazione parziale può chiamare un'altra visualizzazione parziale se un riferimento circolare non è formato dalle chiamate. I percorsi relativi sono sempre relativi al file corrente, non alla radice o al padre del file.

Nota

Un Razorsection oggetto definito in una visualizzazione parziale è invisibile ai file di markup padre. L'oggetto section è visibile solo per la visualizzazione parziale in cui è definito.

Accesso ai dati da visualizzazioni parziali

Quando viene creata un'istanza di una visualizzazione parziale, riceve una copia del dizionario ViewData del padre. Gli aggiornamenti apportati ai dati all'interno della visualizzazione parziale non vengono mantenuti per la visualizzazione padre. Le modifiche a ViewData in una visualizzazione parziale vengono perse quando viene restituita la visualizzazione parziale.

Nell'esempio seguente viene illustrato come passare un'istanza di ViewDataDictionary a una visualizzazione parziale:

@await Html.PartialAsync("_PartialName", customViewData)

È possibile trasmettere un modello in una visualizzazione parziale. Il modello può essere un oggetto personalizzato. È possibile passare un modello con PartialAsync (esegue il rendering di un blocco di contenuto al chiamante) o con RenderPartialAsync (trasmette il contenuto all'output):

@await Html.PartialAsync("_PartialName", model)

Razor Pages

Il markup seguente nell'app di esempio proviene dalla Pages/ArticlesRP/ReadRP.cshtml pagina. La pagina contiene due visualizzazioni parziali. La seconda visualizzazione parziale viene trasmessa a un modello e ViewData viene trasmesso alla visualizzazione parziale. L'overload del costruttore ViewDataDictionary viene usato per passare un nuovo dizionario ViewData mantenendo il dizionario ViewData esistente.

@model ReadRPModel

<h2>@Model.Article.Title</h2>
@* Pass the author's name to Pages\Shared\_AuthorPartialRP.cshtml *@
@await Html.PartialAsync("../Shared/_AuthorPartialRP", Model.Article.AuthorName)
@Model.Article.PublicationDate

@* Loop over the Sections and pass in a section and additional ViewData to 
   the strongly typed Pages\ArticlesRP\_ArticleSectionRP.cshtml partial view. *@
@{
    var index = 0;

    foreach (var section in Model.Article.Sections)
    {
        await Html.PartialAsync("_ArticleSectionRP", 
                                section,
                                new ViewDataDictionary(ViewData)
                                {
                                    { "index", index }
                                });

        index++;
    }
}

Pages/Shared/_AuthorPartialRP.cshtml è la prima visualizzazione parziale a cui fa riferimento il file di ReadRP.cshtml markup:

@model string
<div>
    <h3>@Model</h3>
    This partial view from /Pages/Shared/_AuthorPartialRP.cshtml.
</div>

Pages/ArticlesRP/_ArticleSectionRP.cshtml è la seconda visualizzazione parziale a cui fa riferimento il file di ReadRP.cshtml markup:

@using PartialViewsSample.ViewModels
@model ArticleSection

<h3>@Model.Title Index: @ViewData["index"]</h3>
<div>
    @Model.Content
</div>

MVC

Il markup seguente nell'app di esempio mostra la Views/Articles/Read.cshtml visualizzazione. La visualizzazione contiene due visualizzazioni parziali. La seconda visualizzazione parziale viene trasmessa a un modello e ViewData viene trasmesso alla visualizzazione parziale. L'overload del costruttore ViewDataDictionary viene usato per passare un nuovo dizionario ViewData mantenendo il dizionario ViewData esistente.

@model PartialViewsSample.ViewModels.Article

<h2>@Model.Title</h2>
@* Pass the author's name to Views\Shared\_AuthorPartial.cshtml *@
@await Html.PartialAsync("_AuthorPartial", Model.AuthorName)
@Model.PublicationDate

@* Loop over the Sections and pass in a section and additional ViewData to 
   the strongly typed Views\Articles\_ArticleSection.cshtml partial view. *@
@{
    var index = 0;

    foreach (var section in Model.Sections)
    {
        @(await Html.PartialAsync("_ArticleSection", 
                                section,
                                new ViewDataDictionary(ViewData)
                                {
                                    { "index", index }
                                }))

        index++;
    }
}

Views/Shared/_AuthorPartial.cshtml è la prima visualizzazione parziale a cui fa riferimento il file di Read.cshtml markup:

@model string
<div>
    <h3>@Model</h3>
    This partial view from /Views/Shared/_AuthorPartial.cshtml.
</div>

Views/Articles/_ArticleSection.cshtml è la seconda visualizzazione parziale a cui fa riferimento il file di Read.cshtml markup:

@using PartialViewsSample.ViewModels
@model ArticleSection

<h3>@Model.Title Index: @ViewData["index"]</h3>
<div>
    @Model.Content
</div>

In fase di esecuzione, il rendering delle parziali viene eseguito nell'output sottoposto a rendering del file di markup padre, di cui viene eseguito il rendering all'interno dell'oggetto condiviso _Layout.cshtml. La prima visualizzazione parziale esegue il rendering del nome dell'autore e della data di pubblicazione dell'articolo:

Abraham Lincoln

Questa visualizzazione parziale dal <percorso del file di visualizzazione parziale condivisa>. 11/19/1863 12:00:00 AM

La seconda visualizzazione parziale esegue il rendering delle sezioni dell'articolo:

Section One Index: 0

Four score and seven years ago ...

Section Two Index: 1

Now we are engaged in a great civil war, testing ...

Section Three Index: 2

But, in a larger sense, we can not dedicate ...

Risorse aggiuntive