Freigeben über


Wiederverwenden der Benutzeroberfläche mit Masterseiten und Teilausführungen

von Microsoft

PDF herunterladen

Dies ist Schritt 7 eines kostenlosen "NerdDinner"-Anwendungstutorial , das das Erstellen einer kleinen, aber vollständigen Webanwendung mit ASP.NET MVC 1 durchläuft.

Schritt 7 untersucht, wie wir das "DRY-Prinzip" in unseren Ansichtsvorlagen anwenden können, um Codeduplizierung zu vermeiden, indem Teilansichtsvorlagen und master Seiten verwendet werden.

Wenn Sie ASP.NET MVC 3 verwenden, empfiehlt es sich, die Tutorials Erste Schritte Mit MVC 3 oder MVC Music Store zu befolgen.

NerdDinner Schritt 7: Teil- und Gestaltungsvorlagen

Eine der Designphilosophien ASP.NET MVC ist das "Do Not Repeat Yourself"-Prinzip (allgemein als "DRY" bezeichnet). Ein DRY-Design hilft dabei, die Duplizierung von Code und Logik zu vermeiden, wodurch Anwendungen letztendlich schneller erstellt und einfacher zu verwalten sind.

Wir haben bereits gesehen, dass das DRY-Prinzip in mehreren unserer NerdDinner-Szenarien angewendet wurde. Einige Beispiele: Unsere Validierungslogik wird innerhalb unserer Modellschicht implementiert, sodass sie sowohl für Bearbeitungs- als auch für Erstellungsszenarien in unserem Controller erzwungen werden kann. Wir verwenden die Ansichtsvorlage "NotFound" für die Aktionsmethoden Bearbeiten, Details und Löschen erneut. wir verwenden ein Konventionsbenennungsmuster mit unseren Ansichtsvorlagen, wodurch es nicht mehr erforderlich ist, den Namen explizit anzugeben, wenn wir die View()-Hilfsmethode aufrufen. und wir verwenden die DinnerFormViewModel-Klasse für Aktionsszenarien bearbeiten und erstellen erneut.

Nun sehen wir uns an, wie wir das "DRY-Prinzip" in unseren Ansichtsvorlagen anwenden können, um auch dort Codeduplizierungen zu vermeiden.

Erneuter Besuch unserer Vorlagen zum Bearbeiten und Erstellen von Ansichtsvorlagen

Derzeit verwenden wir zwei verschiedene Ansichtsvorlagen – "Edit.aspx" und "Create.aspx", um unsere Dinner-Formularbenutzeroberfläche anzuzeigen. Ein schneller visueller Vergleich zeigt, wie ähnlich sie sind. Im Folgenden sehen Sie, wie das Formular zum Erstellen aussieht:

Screenshot der Seite

Und so sieht unser Formular "Bearbeiten" aus:

Screenshot des Paages

Gibt es keinen großen Unterschied? Abgesehen von Titel und Kopfzeilentext sind das Formularlayout und die Eingabesteuerelemente identisch.

Wenn wir die Ansichtsvorlagen "Edit.aspx" und "Create.aspx" öffnen, werden wir feststellen, dass sie identisches Formularlayout und Eingabesteuerungscode enthalten. Diese Duplizierung bedeutet, dass wir am Ende zweimal Änderungen vornehmen müssen, wenn wir eine neue Dinner-Eigenschaft einführen oder ändern - was nicht gut ist.

Verwenden von Teilansichtsvorlagen

ASP.NET MVC unterstützt die Möglichkeit, "partielle Ansicht"-Vorlagen zu definieren, die verwendet werden können, um die Renderinglogik der Ansicht für einen Teil einer Seite zu kapseln. "Partielle Elemente" bieten eine nützliche Möglichkeit, die Renderlogik der Ansicht einmal zu definieren und sie dann an mehreren Stellen in einer Anwendung wiederzuverwenden.

Um die Duplizierung von Edit.aspx- und Create.aspx-Ansichtsvorlagen zu erleichtern, können wir eine Teilansichtsvorlage mit dem Namen "DinnerForm.ascx" erstellen, die das Formularlayout und die für beide gemeinsamen Eingabeelemente kapselt. Dazu klicken Sie mit der rechten Maustaste auf unser Verzeichnis /Views/Dinners und wählen den Menübefehl "Add-View>" aus:

Screenshot der Projektmappen-Explorer Navigationsstruktur Abendessen ist hervorgehoben. Hinzufügen und Anzeigen sind ausgewählt. Die Ansicht ist hervorgehoben.

Daraufhin wird das Dialogfeld "Ansicht hinzufügen" angezeigt. Wir nennen die neue Ansicht, die wir erstellen möchten, "DinnerForm", aktivieren das Kontrollkästchen "Teilansicht erstellen" im Dialogfeld und geben an, dass sie eine DinnerFormViewModel-Klasse übergeben wird:

Screenshot des Dialogfelds

Wenn wir auf die Schaltfläche "Hinzufügen" klicken, erstellt Visual Studio eine neue Ansichtsvorlage "DinnerForm.ascx" für uns im Verzeichnis "\Views\Dinners".

Anschließend können wir das doppelte Formularlayout/den Eingabesteuerungscode aus unseren Ansichtsvorlagen Edit.aspx/ Create.aspx in unsere neue Teilansichtsvorlage "DinnerForm.ascx" kopieren/einfügen:

<%= Html.ValidationSummary("Please correct the errors and try again.") %>

<% using (Html.BeginForm()) { %>

    <fieldset>
        <p>
            <label for="Title">Dinner Title:</label>
            <%= Html.TextBox("Title", Model.Dinner.Title) %>
            <%=Html.ValidationMessage("Title", "*") %>
        </p>
        <p>
            <label for="EventDate">Event Date:</label>
            <%= Html.TextBox("EventDate", Model.Dinner.EventDate) %>
            <%= Html.ValidationMessage("EventDate", "*") %>
        </p>
        <p>
            <label for="Description">Description:</label>
            <%= Html.TextArea("Description", Model.Dinner.Description) %>
            <%= Html.ValidationMessage("Description", "*") %>
        </p>
        <p>
            <label for="Address">Address:</label>
            <%= Html.TextBox("Address", Model.Dinner.Address) %>
            <%= Html.ValidationMessage("Address", "*") %>
        </p>
        <p>
            <label for="Country">Country:</label>
            <%= Html.DropDownList("Country", Model.Countries) %>                
            <%= Html.ValidationMessage("Country", "*") %>
        </p>
        <p>
            <label for="ContactPhone">Contact Phone #:</label>
            <%= Html.TextBox("ContactPhone", Model.Dinner.ContactPhone) %>
            <%= Html.ValidationMessage("ContactPhone", "*") %>
        </p>
            
        <p>
            <input type="submit" value="Save"/>
        </p>
    </fieldset>
    
<% } %>

Anschließend können wir unsere Bearbeitungs- und Create-Ansichtsvorlagen aktualisieren, um die Partielle DinnerForm-Vorlage aufzurufen und die Formularduplizierung zu beseitigen. Dazu rufen Wir html.RenderPartial("DinnerForm") in unseren Ansichtsvorlagen auf:

Create.aspx
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Host a Dinner
</asp:Content>

<asp:Content ID="Create" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Host a Dinner</h2>

    <% Html.RenderPartial("DinnerForm"); %>
    
</asp:Content>
Edit.aspx
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
    Edit: <%=Html.Encode(Model.Dinner.Title) %>
</asp:Content>

<asp:Content ID="Edit" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Edit Dinner</h2>

    <% Html.RenderPartial("DinnerForm"); %>

</asp:Content>

Sie können den Pfad der gewünschten Teilvorlage explizit qualifizieren, wenn Sie Html.RenderPartial aufrufen (z. B. ~Views/DinnerForm.ascx). In unserem obigen Code nutzen wir jedoch das konventionsbasierte Benennungsmuster in ASP.NET MVC und geben einfach "DinnerForm" als Namen des teiligen zu rendernden an. Wenn wir dies tun, ASP.NET MVC zuerst im Verzeichnis der konventionsbasierten Ansichten nachschaut (für DinnersController ist dies /Views/Dinners). Wenn die Teilvorlage dort nicht gefunden wird, sucht sie im Verzeichnis /Views/Shared nach dieser Vorlage.

Wenn Html.RenderPartial() nur mit dem Namen der Teilansicht aufgerufen wird, übergibt ASP.NET MVC die gleichen Model- und ViewData-Wörterbuchobjekte, die von der aufrufenden Ansichtsvorlage verwendet werden, an die Teilansicht. Alternativ gibt es überladene Versionen von Html.RenderPartial(), die es Ihnen ermöglichen, ein alternatives Model-Objekt und/oder ein ViewData-Wörterbuch für die zu verwendende Teilansicht zu übergeben. Dies ist nützlich für Szenarien, in denen Sie nur eine Teilmenge des vollständigen Modells/ViewModel übergeben möchten.

Nebenthema: Warum <% %> statt <%= %>?
Eines der subtilen Dinge, die Sie mit dem obigen Code möglicherweise bemerkt haben, ist, dass wir beim Aufrufen von Html.RenderPartial() einen % %> -Block anstelle eines <%= -> Blocks verwenden<. <%= %> -Blöcke in ASP.NET angeben, dass ein Entwickler einen angegebenen Wert rendern möchte (z. B. <%= "Hello" %> würde "Hello" rendern). <%%> -Blöcke geben stattdessen an, dass der Entwickler Code ausführen möchte und dass jede gerenderte Ausgabe darin explizit erfolgen muss (z. B. <%Response.Write("Hello") %>. Der Grund, warum wir einen <% %> -Block mit unserem obigen Html.RenderPartial-Code verwenden, liegt daran, dass die Html.RenderPartial()-Methode keine Zeichenfolge zurückgibt und stattdessen den Inhalt direkt an den Ausgabestream der aufrufenden Ansichtsvorlage ausgibt. Dies geschieht aus Gründen der Leistungseffizienz und vermeidet dadurch die Notwendigkeit, ein (potenziell sehr großes) temporäres Zeichenfolgenobjekt zu erstellen. Dies reduziert die Arbeitsspeicherauslastung und verbessert den gesamten Anwendungsdurchsatz. Ein häufiger Fehler bei der Verwendung von Html.RenderPartial() besteht darin, zu vergessen, ein Semikolon am Ende des Aufrufs hinzuzufügen, wenn es sich innerhalb eines <% %> -Blocks befindet. Dieser Code verursacht beispielsweise einen Compilerfehler: <% Html.RenderPartial("DinnerForm") %> Sie müssen stattdessen schreiben: <% Html.RenderPartial("DinnerForm"); %> Dies liegt daran, dass <% %> -Blöcke eigenständige Codeanweisungen sind und bei Verwendung von C#-Codeanweisungen mit einem Semikolon beendet werden müssen.

Verwenden von Teilansichtsvorlagen zum Klarstellen von Code

Wir haben die Partielle Ansichtsvorlage "DinnerForm" erstellt, um das Duplizieren der Renderinglogik der Ansicht an mehreren Stellen zu vermeiden. Dies ist der häufigste Grund zum Erstellen von Teilansichtsvorlagen.

Manchmal ist es trotzdem sinnvoll, Teilansichten zu erstellen, auch wenn sie nur an einer einzigen Stelle aufgerufen werden. Sehr komplizierte Ansichtsvorlagen können oft viel einfacher zu lesen sein, wenn ihre Renderinglogik der Ansicht extrahiert und in eine oder mehrere gut benannte Partielle Vorlagen unterteilt wird.

Betrachten Sie beispielsweise den folgenden Codeausschnitt der Website. master Datei in unserem Projekt (die wir uns in Kürze ansehen werden). Der Code ist relativ einfach zu lesen – teilweise, weil die Logik zum Anzeigen eines Anmelde-/Abmeldelinks oben rechts auf dem Bildschirm im Teil "LogOnUserControl" gekapselt ist:

<div id="header">
    <div id="title">
        <h1>My MVC Application</h1>
    </div>
      
    <div id="logindisplay">
        <% Html.RenderPartial("LogOnUserControl"); %>
    </div> 
    
    <div id="menucontainer">
    
        <ul id="menu">              
            <li><%=Html.ActionLink("Home", "Index", "Home")%></li>
            <li><%=Html.ActionLink("About", "About", "Home")%></li>
        </ul>
    </div>
</div>

Wenn Sie beim Versuch, das HTML/Code-Markup innerhalb einer Ansichtsvorlage zu verstehen, verwirrt werden, überlegen Sie, ob es nicht klarer wäre, wenn einige davon extrahiert und in gut benannte Teilansichten umgestaltet wurden.

Masterseiten

Neben der Unterstützung von Teilansichten unterstützt ASP.NET MVC auch die Möglichkeit, "master Seite"-Vorlagen zu erstellen, die verwendet werden können, um das allgemeine Layout und html der obersten Ebene einer Website zu definieren. Inhaltsplatzhaltersteuerelemente können dann der master Seite hinzugefügt werden, um ersetzbare Regionen zu identifizieren, die von Ansichten überschrieben oder "ausgefüllt" werden können. Dies bietet eine sehr effektive (und TROCKENE) Möglichkeit, ein gemeinsames Layout für eine Anwendung anzuwenden.

Standardmäßig wird bei neuen ASP.NET MVC-Projekten automatisch eine master-Seitenvorlage hinzugefügt. Diese master Seite heißt "Site.master" und befindet sich im Ordner \Views\Shared\:

Screenshot der Navigationsstruktur

Die Standardwebsite. master Datei sieht wie unten aus. Es definiert den äußeren HTML-Code der Website zusammen mit einem Menü für die Navigation am oberen Rand. Es enthält zwei ersetzbare Inhaltsplatzhaltersteuerelemente – eines für den Titel und das andere für den Bereich, an dem der primäre Inhalt einer Seite ersetzt werden soll:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">
    <title>
       <asp:ContentPlaceHolder ID="TitleContent" runat="server" />
    </title>
   <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <div class="page">

        <div id="header">
            <div id="title">
                <h1>My MVC Application</h1>
            </div>
              
            <div id="logindisplay">
                <% Html.RenderPartial("LogOnUserControl"); %>
            </div> 
            
            <div id="menucontainer">

                <ul id="menu">              
                    <li><%=Html.ActionLink("Home", "Index", "Home")%></li>
                    <li><%=Html.ActionLink("About", "About", "Home")%></li>
                </ul>
            
            </div>
        </div>

        <div id="main">
            <asp:ContentPlaceHolder ID="MainContent" runat="server" />
        </div>
    </div>
</body>
</html>

Alle Ansichtsvorlagen, die wir für unsere NerdDinner-Anwendung ("List", "Details", "Edit", "Create", "NotFound" usw.) erstellt haben, basieren auf dieser Website. master Vorlage. Dies wird über das Attribut "MasterPageFile" angegeben, das standardmäßig der oberen <Anweisung % @ Page %> hinzugefügt wurde, als wir unsere Ansichten mithilfe des Dialogfelds "Ansicht hinzufügen" erstellt haben:

<%@ Page Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerViewModel>" MasterPageFile="~/Views/Shared/Site.Master" %>

Dies bedeutet, dass wir die Website ändern können. master Inhalt, und lassen Sie die Änderungen automatisch anwenden und verwenden, wenn wir eine unserer Ansichtsvorlagen rendern.

Lassen Sie uns unsere Website aktualisieren. master-Headerabschnitt, sodass der Header unserer Anwendung "NerdDinner" anstelle von "Meine MVC-Anwendung" lautet. Lassen Sie uns auch unser Navigationsmenü aktualisieren, sodass die erste Registerkarte "Dinner suchen" ist (von der Index()-Aktionsmethode des HomeControllers behandelt wird, und fügen wir eine neue Registerkarte mit dem Namen "Host a Dinner" (von der Create()-Aktionsmethode von DinnersController behandelt:

<div id="header">

    <div id="title">
        <h1>NerdDinner</h1>
    </div>

    <div id="logindisplay">
        <% Html.RenderPartial("LoginStatus"); %>
    </div> 
    
    <div id="menucontainer">
        <ul id="menu">      
           <li><%=Html.ActionLink("Find Dinner", "Index", "Home")%></li>
           <li><%=Html.ActionLink("Host Dinner", "Create", "Dinners")%></li>
           <li><%=Html.ActionLink("About", "About", "Home")%></li>   
        </ul>
    </div>
</div>

Wenn wir die Website speichern. master Datei und Aktualisieren des Browsers werden die Headeränderungen in allen Ansichten in unserer Anwendung angezeigt. Zum Beispiel:

Screenshot der Listenseite Nerd Dinner Upcoming Dinners

Und mit der URL /Dinners/Edit/[id]

Screenshot der Formularseite

Nächster Schritt

Partielle und master Seiten bieten sehr flexible Optionen, mit denen Sie Ansichten sauber organisieren können. Sie werden feststellen, dass sie Ihnen helfen, das Duplizieren von Ansichtsinhalten/Code zu vermeiden und Ihre Ansichtsvorlagen einfacher zu lesen und zu verwalten.

Lassen Sie uns nun das zuvor erstellte Listenszenario erneut aufarbeiten und skalierbare Pagingunterstützung aktivieren.