Share via


Mehrere ContentPlaceHolder-Steuerelemente und Standardinhalt (C#)

von Scott Mitchell

PDF herunterladen

Untersucht, wie einer master Seite mehrere Inhaltsplatzhalter hinzugefügt werden und wie Standardinhalte in den Inhaltsplatzhaltern angegeben werden.

Einführung

Im vorherigen Tutorial haben wir untersucht, wie master Seiten es ASP.NET Entwicklern ermöglichen, ein konsistentes websiteweites Layout zu erstellen. Gestaltungsvorlagen definieren sowohl Markup, das allen Inhaltsseiten gemeinsam ist, als auch Regionen, die seitenweise angepasst werden können. Im vorherigen Tutorial haben wir eine einfache master Seite (Site.master) und zwei Inhaltsseiten (Default.aspx und About.aspx) erstellt. Unsere master Seite bestand aus zwei ContentPlaceHolders namens head und MainContent, die <head> sich im -Element bzw. im Webformular befanden. Während die Inhaltsseiten jeweils über zwei Inhaltssteuerelemente verfügten, haben wir nur Markup für das -Steuerelement angegeben, das entspricht MainContent.

Wie die beiden ContentPlaceHolder-Steuerelemente in Site.masterbelegen, kann eine master Seite mehrere ContentPlaceHolders enthalten. Darüber hinaus kann die Seite master Standardmarkup für die ContentPlaceHolder-Steuerelemente angeben. Eine Inhaltsseite kann dann optional ein eigenes Markup angeben oder das Standardmarkup verwenden. In diesem Tutorial untersuchen wir die Verwendung mehrerer Inhaltssteuerelemente auf der Seite master und das Definieren von Standardmarkup in den ContentPlaceHolder-Steuerelementen.

Schritt 1: Hinzufügen zusätzlicher ContentPlaceHolder-Steuerelemente zur Gestaltungsvorlage

Viele Websitedesigns enthalten mehrere Bereiche auf dem Bildschirm, die seiteweise angepasst werden. Site.master, die master Seite, die wir im vorherigen Tutorial erstellt haben, enthält einen einzelnen ContentPlaceHolder im Webformular mit dem Namen MainContent. Insbesondere befindet sich dieser ContentPlaceHolder innerhalb des mainContent<div> -Elements.

Abbildung 1 zeigt Default.aspx , wenn sie über einen Browser angezeigt wird. Der rot eingekreiste Bereich ist das seitenspezifische Markup, das entspricht MainContent.

Der eingekreiste Bereich zeigt den Bereich, der derzeit auf Seitenbasis anpassbar ist.

Abbildung 01: Der eingekreiste Bereich zeigt den Bereich, der derzeit auf Seitenbasis anpassbar ist (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Stellen Sie sich vor, dass neben dem in Abbildung 1 dargestellten Bereich auch seitenspezifische Elemente zur linken Spalte unter den Abschnitten Lektionen und Nachrichten hinzugefügt werden müssen. Um dies zu erreichen, fügen wir der Seite master ein weiteres ContentPlaceHolder-Steuerelement hinzu. Öffnen Sie als Nächstes die Site.master Seite master in Visual Web Developer, und ziehen Sie dann ein ContentPlaceHolder-Steuerelement aus der Toolbox auf den Designer nach dem Abschnitt Nachrichten. Legen Sie den ContentPlaceHolder ID auf fest LeftColumnContent.

Hinzufügen eines ContentPlaceHolder-Steuerelements zur linken Spalte der Gestaltungsvorlage

Abbildung 02: Hinzufügen eines ContentPlaceHolder-Steuerelements zur linken Spalte der Gestaltungsvorlage (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Mit dem Hinzufügen von LeftColumnContent ContentPlaceHolder zur master Seite können wir Inhalte für diesen Bereich seitenweise definieren, indem wir ein Content-Steuerelement in die Seite einfügen, deren ContentPlaceHolderID Auf LeftColumnContentfestgelegt ist. Wir untersuchen diesen Prozess in Schritt 2.

Schritt 2: Definieren von Inhalten für den neuen ContentPlaceHolder auf den Inhaltsseiten

Beim Hinzufügen einer neuen Inhaltsseite zur Website erstellt Visual Web Developer automatisch ein Content-Steuerelement auf der Seite für jeden ContentPlaceHolder in der ausgewählten master Seite. Nachdem Sie der Seite "master" in Schritt 1 einen LeftColumnContent ContentPlaceHolder hinzugefügt haben, verfügen neue ASP.NET-Seiten jetzt über drei Inhaltssteuerelemente.

Um dies zu veranschaulichen, fügen Sie dem Stammverzeichnis mit dem Namen MultipleContentPlaceHolders.aspx eine neue Inhaltsseite hinzu, die an die Site.master seite master gebunden ist. Visual Web Developer erstellt diese Seite mit dem folgenden deklarativen Markup:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="MultipleContentPlaceHolders.aspx.cs" Inherits="MultipleContentPlaceHolders" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="LeftColumnContent" Runat="Server">
</asp:Content>

Geben Sie inhalte in das Content-Steuerelement ein, das auf contentPlaceHolders MainContent (Content2) verweist. Fügen Sie als Nächstes das folgende Markup zum Content3 Content-Steuerelement hinzu (das auf den LeftColumnContent ContentPlaceHolder verweist):

<h3>Page-Specific Content</h3>
<ul>
 <li>This content is defined in the content page.</li>
 <li>The master page has two regions in the Web Form that are editable on a
 page-by-page basis.</li>
</ul>

Nachdem Sie dieses Markup hinzugefügt haben, besuchen Sie die Seite über einen Browser. Wie abbildung 3 zeigt, wird das im Content3 Inhaltssteuerelement platzierte Markup in der linken Spalte unter dem Abschnitt Nachrichten (rot eingekreist) angezeigt. Das in Content2 platzierte Markup wird im rechten Teil der Seite angezeigt (blau eingekreist).

Die linke Spalte enthält jetzt Page-Specific Inhalt unterhalb des Abschnitts

Abbildung 03: Die linke Spalte enthält jetzt Page-Specific Inhalt unterhalb des Abschnitts "News" (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Definieren von Inhalten auf vorhandenen Inhaltsseiten

Beim Erstellen einer neuen Inhaltsseite wird automatisch das ContentPlaceHolder-Steuerelement integriert, das wir in Schritt 1 hinzugefügt haben. Unsere beiden vorhandenen Inhaltsseiten – About.aspx und Default.aspx – verfügen jedoch nicht über ein Inhaltssteuerelement für den LeftColumnContent ContentPlaceHolder. Um Inhalte für diesen ContentPlaceHolder auf diesen beiden vorhandenen Seiten anzugeben, müssen wir selbst ein Content-Steuerelement hinzufügen.

Im Gegensatz zu den meisten ASP.NET Websteuerelementen enthält die Visual Web Developer Toolbox kein Inhaltssteuerelementelement. Wir können das deklarative Markup des Inhaltssteuerelements manuell in die Quellansicht eingeben, aber ein einfacherer und schnellerer Ansatz ist die Verwendung der Entwurfsansicht. Öffnen Sie die About.aspx Seite, und wechseln Sie zur Entwurfsansicht. Wie Abbildung 4 veranschaulicht, wird der LeftColumnContent ContentPlaceHolder in der Entwurfsansicht angezeigt. Wenn Sie den Mauszeigen darauf zeigen, lautet der angezeigte Titel: "LeftColumnContent (Master)." Die Aufnahme von "Master" in den Titel gibt an, dass auf der Seite kein Content-Steuerelement für diesen ContentPlaceHolder definiert ist. Wenn ein Content-Steuerelement für den ContentPlaceHolder vorhanden ist, wie im Fall von MainContent, lautet der Titel: "ContentPlaceHolderID (Custom)."

Erweitern Sie das LeftColumnContent Smarttag von ContentPlaceHolder, und klicken Sie auf den Link Benutzerdefinierten Inhalt erstellen, um About.aspxein ContentPlaceHolder-Steuerelement für den ContentPlaceHolder hinzuzufügen.

Die Entwurfsansicht für About.aspx zeigt den LeftColumnContent ContentPlaceHolder an.

Abbildung 04: Die Entwurfsansicht für About.aspx Zeigt den LeftColumnContent ContentPlaceHolder (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wenn Sie auf den Link Benutzerdefinierten Inhalt erstellen klicken, wird das erforderliche Content-Steuerelement auf der Seite generiert und dessen ContentPlaceHolderID Eigenschaft auf den ContentPlaceHolder festgelegt ID. Wenn Sie beispielsweise auf den Link Benutzerdefinierten Inhalt erstellen für LeftColumnContent region in About.aspx klicken, wird der Seite das folgende deklarative Markup hinzugefügt:

<asp:Content ID="Content3" runat="server" contentplaceholderid="LeftColumnContent">
 
</asp:Content>

Weglassen von Inhaltssteuerelementen

ASP.NET erfordert nicht, dass alle Inhaltsseiten Inhaltssteuerelemente für jeden ContentPlaceHolder enthalten, der auf der master-Seite definiert ist. Wenn ein Content-Steuerelement weggelassen wird, verwendet die ASP.NET-Engine das Markup, das im ContentPlaceHolder auf der Seite master definiert ist. Dieses Markup wird als Standardinhalt von ContentPlaceHolder bezeichnet und ist nützlich in Szenarien, in denen der Inhalt für eine Region bei der Mehrheit der Seiten üblich ist, aber für eine kleine Anzahl von Seiten angepasst werden muss. Schritt 3 befasst sich mit der Angabe von Standardinhalten auf der Seite master.

Default.aspx Enthält derzeit zwei Content-Steuerelemente für und headMainContent ContentPlaceHolders. Es verfügt nicht über ein Content-Steuerelement für LeftColumnContent. Wenn daher gerendert wird, Default.aspx wird der LeftColumnContent Standardinhalt des ContentPlaceHolder verwendet. Da wir noch keinen Standardinhalt für diesen ContentPlaceHolder definiert haben, ist der Nettoeffekt, dass für diesen Bereich kein Markup ausgegeben wird. Um dieses Verhalten zu überprüfen, besuchen Sie Default.aspx einen Browser. Wie Abbildung 5 zeigt, wird in der linken Spalte unter dem Abschnitt Nachrichten kein Markup ausgegeben.

Für leftColumnContent ContentPlaceHolder wird kein Inhalt gerendert.

Abbildung 05: Kein Inhalt wird für den LeftColumnContent ContentPlaceHolder gerendert (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Schritt 3: Angeben des Standardinhalts auf der Gestaltungsvorlage

Einige Websitedesigns enthalten eine Region, deren Inhalt für alle Seiten auf der Website mit Ausnahme von einer oder zwei Ausnahmen identisch ist. Stellen Sie sich eine Website vor, die Benutzerkonten unterstützt. Eine solche Website erfordert eine Anmeldeseite, auf der Besucher ihre Anmeldeinformationen eingeben können, um sich bei der Website anzumelden. Um den Anmeldevorgang zu beschleunigen, können die Website-Designer in der oberen linken Ecke jeder Seite Textfelder für Benutzername und Kennwort einfügen, damit sich Benutzer anmelden können, ohne explizit die Anmeldeseite besuchen zu müssen. Obwohl diese Textfelder für Benutzername und Kennwort auf den meisten Seiten hilfreich sind, sind sie auf der Anmeldeseite redundant, die bereits Textfelder für die Anmeldeinformationen des Benutzers enthält.

Um diesen Entwurf zu implementieren, können Sie ein ContentPlaceHolder-Steuerelement in der oberen linken Ecke der seite master erstellen. Jede Seite, die die Textfelder für Benutzername und Kennwort in der linken oberen Ecke anzeigen musste, würde ein Content-Steuerelement für diesen ContentPlaceHolder erstellen und die erforderliche Schnittstelle hinzufügen. Die Anmeldeseite hingegen würde das Hinzufügen eines Content-Steuerelements für diesen ContentPlaceHolder auslassen oder ein Content-Steuerelement ohne Markup-Definition erstellen. Der Nachteil dieses Ansatzes ist, dass wir daran denken müssen, die Textfelder für Benutzername und Kennwort jeder Seite hinzuzufügen, die wir der Website hinzufügen (mit Ausnahme der Anmeldeseite). Dies ist ein Problem. Wir werden wahrscheinlich vergessen, diese Textfelder zu einer oder zwei Seiten hinzuzufügen, oder, schlimmer noch, wir implementieren die Schnittstelle möglicherweise nicht ordnungsgemäß (vielleicht fügen Sie nur ein Textfeld anstelle von zwei hinzu).

Eine bessere Lösung besteht darin, die Textfelder für Benutzername und Kennwort als Standardinhalt von ContentPlaceHolder zu definieren. Auf diese Weise müssen wir diesen Standardinhalt nur auf den wenigen Seiten außer Kraft setzen, auf denen die Textfelder für Benutzername und Kennwort nicht angezeigt werden (die Anmeldeseite für instance). Um die Angabe von Standardinhalten für ein ContentPlaceHolder-Steuerelement zu veranschaulichen, implementieren wir das soeben erläuterte Szenario.

Hinweis

Im weiteren Verlauf dieses Tutorials wird unsere Website aktualisiert, um eine Anmeldeschnittstelle in der linken Spalte für alle Seiten außer der Anmeldeseite einzuschließen. In diesem Tutorial wird jedoch nicht untersucht, wie die Website für die Unterstützung von Benutzerkonten konfiguriert wird. Weitere Informationen zu diesem Thema finden Sie in den Tutorials zu Formularauthentifizierung, Autorisierung, Benutzerkonten und Rollen .

Hinzufügen eines ContentPlaceHolder und Angeben des Standardinhalts

Öffnen Sie die Site.master Seite master, und fügen Sie der linken Spalte zwischen dem Abschnitt Bezeichnung und Lektionen das DateDisplay folgende Markup hinzu:

<asp:ContentPlaceHolder ID="QuickLoginUI" runat="server">
 <asp:Login ID="QuickLogin" runat="server" 
    TitleText="<h3>Sign In</h3>"
    FailureAction="RedirectToLoginPage">
 </asp:Login>
</asp:ContentPlaceHolder>

Nach dem Hinzufügen dieses Markups sollte die Entwurfsansicht Ihrer master Seite ähnlich wie Abbildung 6 aussehen.

Die Gestaltungsvorlage enthält ein Anmeldesteuerelement.

Abbildung 06: Die Gestaltungsvorlage enthält ein Anmeldesteuerelement (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Dieser ContentPlaceHolder, , QuickLoginUIverfügt über ein Anmeldewebsteuerelement als Standardinhalt. Das Login-Steuerelement zeigt eine Benutzeroberfläche an, die den Benutzer zur Eingabe seines Benutzernamens und Kennworts sowie einer Schaltfläche Anmelden auffordert. Wenn Sie auf die Schaltfläche Anmelden klicken, überprüft das Anmeldesteuerelement intern die Anmeldeinformationen des Benutzers anhand der Mitgliedschafts-API. Um dieses Anmeldesteuerelement in der Praxis zu verwenden, müssen Sie Dann Ihre Website für die Verwendung der Mitgliedschaft konfigurieren. Dieses Thema geht über den Rahmen dieses Tutorials hinaus. Weitere Informationen zum Erstellen einer Webanwendung, die Benutzerkonten unterstützt, finden Sie in den Tutorials zur Formularauthentifizierung, Autorisierung, Benutzerkonten und Rollen .

Sie können das Verhalten oder aussehen des Anmeldesteuerelements anpassen. Ich habe zwei seiner Eigenschaften festgelegt: TitleText und FailureAction. Der TitleText Eigenschaftswert, der standardmäßig "Anmelden" ist, wird oben auf der Benutzeroberfläche des Steuerelements angezeigt. Ich habe diese Eigenschaft so festgelegt, dass der Text "Anmelden" als <h3> Element angezeigt wird. Die FailureAction -Eigenschaft gibt an, was zu tun ist, wenn die Anmeldeinformationen des Benutzers ungültig sind. Standardmäßig wird der Wert verwendet Refresh, wodurch der Benutzer auf derselben Seite bleibt und eine Fehlermeldung innerhalb des Anmeldesteuerelements angezeigt wird. Ich habe sie in RedirectToLoginPagegeändert, wodurch der Benutzer bei ungültigen Anmeldeinformationen zur Anmeldeseite gesendet wird. Ich bevorzuge es, den Benutzer auf die Anmeldeseite zu senden, wenn ein Benutzer versucht, sich von einer anderen Seite anzumelden, schlägt jedoch fehl, da die Anmeldeseite zusätzliche Anweisungen und Optionen enthalten kann, die nicht einfach in die linke Spalte passen würden. Die Anmeldeseite kann beispielsweise Optionen zum Abrufen eines vergessenen Kennworts oder zum Erstellen eines neuen Kontos enthalten.

Erstellen der Anmeldeseite und Überschreiben des Standardinhalts

Nachdem die master Seite abgeschlossen ist, besteht unser nächster Schritt darin, die Anmeldeseite zu erstellen. Fügen Sie dem Stammverzeichnis Ihrer Website eine ASP.NET Seite mit dem Namen Login.aspxhinzu, und binden Sie sie an die Site.master seite master. Auf diese Weise wird eine Seite mit vier Content-Steuerelementen erstellt, eines für jedes der in Site.masterdefinierten ContentPlaceHolders.

Fügen Sie dem MainContent Inhaltssteuerelement ein Anmeldesteuerelement hinzu. Ebenso können Sie der LeftColumnContent Region beliebige Inhalte hinzufügen. Achten Sie jedoch darauf, das Inhaltssteuerelement für den QuickLoginUI ContentPlaceHolder leer zu lassen. Dadurch wird sichergestellt, dass das Login-Steuerelement nicht in der linken Spalte der Anmeldeseite angezeigt wird.

Nachdem Sie den Inhalt für die MainContent Regionen und LeftColumnContent definiert haben, sollte das deklarative Markup Ihrer Anmeldeseite in etwa wie folgt aussehen:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
 <h2>
 Sign In</h2>
 <p>
 <asp:Login ID="Login1" runat="server" TitleText="">
 </asp:Login>
 </p>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="QuickLoginUI" Runat="Server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="LeftColumnContent" Runat="Server">
 <h3>Sign In Tasks</h3>
 <ul>
 <li>Create a New Account</li>
 <li>Recover Forgotten Password</li>
 </ul>
 <p>TODO: Turn the above text into links...</p>
</asp:Content>

Abbildung 7 zeigt diese Seite, wenn sie über einen Browser angezeigt wird. Da diese Seite ein Content-Steuerelement für den QuickLoginUI ContentPlaceHolder angibt, überschreibt sie den Standardinhalt, der auf der seite master angegeben ist. Der Nettoeffekt ist, dass das login-Steuerelement, das in der Entwurfsansicht der master Seite (siehe Abbildung 6) angezeigt wird, auf dieser Seite nicht gerendert wird.

Die Anmeldeseite unterdrückt den Standardinhalt von QuickLoginUI ContentPlaceHolder erneut.

Abbildung 07: Die Anmeldeseite unterdrückt den QuickLoginUI Standardinhalt von ContentPlaceHolder erneut (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Verwenden des Standardinhalts in neuen Seiten

Wir möchten das Login-Steuerelement in der linken Spalte für alle Seiten mit Ausnahme der Anmeldeseite anzeigen. Um dies zu erreichen, sollten alle Inhaltsseiten mit Ausnahme der Anmeldeseite ein Content-Steuerelement für den QuickLoginUI ContentPlaceHolder weglassen. Wenn Sie ein Content-Steuerelement weglassen, wird stattdessen der Standardinhalt des ContentPlaceHolder verwendet.

Unsere vorhandenen Inhaltsseiten - Default.aspx, About.aspxund MultipleContentPlaceHolders.aspx - enthalten kein Inhaltssteuerelement fürQuickLoginUI, da sie erstellt wurden, bevor wir das ContentPlaceHolder-Steuerelement der master Seite hinzugefügt haben. Daher müssen diese vorhandenen Seiten nicht aktualisiert werden. Neue Seiten, die der Website hinzugefügt werden, enthalten jedoch standardmäßig ein Content-Steuerelement für den QuickLoginUI ContentPlaceHolder. Daher müssen wir daran denken, diese Inhaltssteuerelemente jedes Mal zu entfernen, wenn wir eine neue Inhaltsseite hinzufügen (es sei denn, wir möchten den Standardinhalt des ContentPlaceHolder überschreiben, wie im Fall der Anmeldeseite).

Um das Inhaltssteuerelement zu entfernen, können Sie das deklarative Markup entweder manuell aus der Quellansicht löschen oder in der Entwurfsansicht den Link Standard zu Masterinhalt aus dem Smarttag auswählen. Bei beiden Ansätzen wird das Inhaltssteuerelement von der Seite entfernt und derselbe Nettoeffekt erzeugt.

Abbildung 8 zeigt Default.aspx , wenn es über einen Browser angezeigt wird. Denken Sie daran, dass Default.aspx nur zwei Content-Steuerelemente im deklarativen Markup angegeben sind – eines für head und eines für MainContent. Daher werden der Standardinhalt für die LeftColumnContent ContentPlaceHolders und QuickLoginUI angezeigt.

Die Standardinhalte für leftColumnContent und QuickLoginUI ContentPlaceHolder werden angezeigt.

Abbildung 08: Der Standardinhalt für die LeftColumnContent ContentPlaceHolder und QuickLoginUI die ContentPlaceHolder werden angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Zusammenfassung

Das ASP.NET master Seitenmodell ermöglicht eine beliebige Anzahl von ContentPlaceHolders auf der seite master. Darüber hinaus enthalten ContentPlaceHolders Standardinhalte, die ausgegeben werden, falls auf der Inhaltsseite kein entsprechendes Inhaltssteuerelement vorhanden ist. In diesem Tutorial haben wir erfahren, wie Sie zusätzliche ContentPlaceHolder-Steuerelemente in die Seite master einfügen und Inhaltssteuerelemente für diese neuen ContentPlaceHolders sowohl auf neuen als auch auf vorhandenen ASP.NET-Seiten definieren. Wir haben uns auch mit der Angabe von Standardinhalten in einem ContentPlaceHolder befasst, was in Szenarien nützlich ist, in denen nur eine Minderheit von Seiten den ansonsten standardisierten Inhalt innerhalb einer bestimmten Region anpassen muss.

Im nächsten Tutorial untersuchen wir den head ContentPlaceHolder ausführlicher und erfahren, wie Sie den Titel, Metatags und andere HTML-Header seitenweise deklarativ und programmgesteuert definieren.

Viel Spaß beim Programmieren!

Zum Autor

Scott Mitchell, Autor mehrerer ASP/ASP.NET-Bücher und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 3.5 in 24 Stunden. Scott kann unter mitchell@4GuysFromRolla.com oder über seinen Blog unter http://ScottOnWriting.NETerreicht werden.

Besonderer Dank an

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Leitender Prüfer für dieses Tutorial war Suchi Banerjee. Möchten Sie meine bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter ab mitchell@4GuysFromRolla.com.