Print
Mittwoch, 6. Juni 2007 |

User Controls mit ASP.NET

Zusätzlich zu den vorgegebenen "server controls" wie <asp:button> kannst du dir auch eigene controls basteln - sogenannte "user controls".

Im Prinzip ähnelt eine "user control" einer ganz gewöhnlichen aspx seite bis auf wenige Details. So hat eine User Control die Fileendung "ascx" und da die Seite in deine aspx Seite eingebettet ist brauchst du keine <html>, <head> und <body> tags mehr.

Wir werden hier als Beispiel eine Loginseite schreiben. Ich rate davon ab dieses Skript auf echten Seiten zu verwenden - das hier ist nur ein Beispiel und kein vollwertiges Loginskript!

Zwar kann ein potenzieller Angreifer das Passwort nicht aus der Seite "rauslesen", da der Servercode beim client nicht dargestellt wird (klick einfach in der entgültigen Version im Browser mit der rechten Maustaste drauf und geh auf "View Source" oder "Quelltext anzeigen").
Dafür sieht jeder das Passwort der Zugriff auf den Server hat!

Öffnen wir zuerst wieder unsere default.aspx aus dem Tutorial ASP.NET - Erste Seite in notepad.
Im selben Ordner wie default.aspx legen wir außerdem noch eine Datei "uc_login.ascx" an (das wird unsere Usercontrol) und öffnen das leere File ebenfalls in Notepad.
Lösche aus der default.aspx alles dynamische erst mal raus.

Fügen wir nun als erstes die Usercontrol in unsere website ein. Damit die Seite weiß, wo sie die Usercontrol findet verwenden wir eine "Register" Anweisung ganz oben auf der Seite. Diese Register Anweisung sieht folgendermaßen aus:

    <%@Register TagPrefix="MyLogin" TagName="Login" src="uc_login.ascx" %>


Das Attribut "TagPrefix" bezeichnet einen eindeutigen namespace für die UserControl (dadurch wird gewährleistet, dass mehrere User Controls mit demselben Namen von einander unterschieden werden können), der "TagName" ist ein endeutiger Name für das Control.
Das Attribut "Src" bezeichnet den virtuellen Pfad zu der User Control, also zum Beispiel "uc_login.ascx" wenn die Control im selben Ordner liegt oder "/includes/uc_login.ascx" wenn die Control in einem Unterordner liegt.

Wenn eine User Control auf diese Art registriert ist kannst du sie - gleich wie die Server Controls an einer beliebigen Stelle auf der Stelle einfügen. In unserem Fall sieht das dann so aus:

    <MyLogin:Login id="MyLogin" runat="server"/>

Deine default.aspx sollte jetzt in etwa so aussehen:


    <%@ Register TagPrefix="MyLogin" TagName="Login" src="uc_login.ascx" %>

    <html>
        <head>
            <title>Meine erste ASP.NET Seite</title>
        </head>

        <body>
            <MyLogin:Login id="MyLogin" runat="server"/>
        </body>
    </html>

Widmen wir uns nun unserer user control.

Wie bereits aus den vorigen Tutorials bekannt bauen wir uns ein User Interface mit folgenden Elementen:
Einer Textbox für Benutzernamen mit der id="User", eine für das Passwort (Anmerkung: mit dem Attribut TextMode="Password" kann man eine Textbox als Passwortbox definieren) mit der id="Pass", einen Button zum Einloggen mit der id="Btn_Login" und einen Label um den Status anzuzeigen mit der id="lblErr".
"User" und "Pass" sollen außerdem das Attribut OnTextChanged="AuthUser" haben, Button soll auf klick ebenfalls "AuthUser" als Wert haben.
Das Ganze könnte in etwa so aussehen:


    <table style="background-color:gray; border: 1px solid black;" cellspacing="15">
        <tr>
            <td>
                <b>Login: </b>
            </td>
            <td>
                <asp:TextBox id="User" runat="server" OnTextChanged="AuthUser" />
            </td>
        </tr>
        <tr>
            <td>
                <b>Password: </b>
            </td>
            <td>
                <asp:TextBox id="Pass" TextMode="Password" OnTextChanged="AuthUser"
                    runat="server"/>
            </td>
        </tr>
        <tr>
            <td> </td>
            <td>
                <asp:Button id="Btn_Login" Text="Login" onClick="AuthUser" runat="server"/>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:Label id="lblErr" runat="server"/>
            </td>
        </tr>
    </table>

Ebenso wie auch bei aspx Seiten können wir hier den Code über einen Script Block einfügen.
Um den Status der Authentifizierung an die aspx Seite zu übergeben werden wir zwei Sachen verwenden die du noch nicht kennst.

Das eine sind "Properties", spezielle Methoden in c# die einer Variablen ähneln, denen man allerdings eine funktionalität mitgeben kann - um so zum Beispiel null values zu vermeiden. Es reicht vorerst wenn du die Syntax kennst:

 
     string property { 
         // gibt was zurück 
         get { 
             return (smthg != null) ? smth : String.Empty; 
         } 
         // setzt den Wert 
         set { 
             smthg = value; 
         } 
     } 
  
     void test( ) { 
         // Setze den Wert 
         property = "bla"; 
         // hole den Wert 
         Console.Write( property ); 
     } 
  
  

Properties können auch dazu verwendet werden um Werte an die Control zu übergeben. Genauer werden wir das im Kapitel über Custom Controls behandeln. Bei User Controls funktioniert die Übergabe von Werten dann genau gleich.

Das andere ist der ViewState - ein Container, den dir ASP.NET zur verfügung stellt um Variablen über längere Zeit zu behalten ohne sie explizit immer wieder übergeben zu müssen.
Syntax:

    ViewState["Name"]

Setzen und auslesen kann man sie wie eine ganz gewöhnliche Variabel, allerdings hat sie den Wert "null" bevor sie das erstemal gesetzt wurde.

Nutzen wir jetzt unser Wissen um einen Skriptblock in unsere Seite einzubauen. In dem Skriptblock erzeugen wir zwei Methoden, eine public property mit Namen "isAuthenticated", die fehlerfrei testet ob der Benutzer eingeloggt ist und einen boolwert zurückgibt der true ist falls der Benutzer eingeloggt ist, und eine private Event-Funktion "AuthUser", die testet ob Benutzernamen und Passowrt stimmen (in dem Beispiel einfach über statische Variablen) und die "isAuthenticated" auf den Wert true setzt falls alles stimmt.

Die gesamte Usercontrol uc_login.ascx könnte dann am Ende etwa folgendermaßen ausschauen:

 
     <script language="c#" runat="server"> 
     public bool isAuthenticated { 
         get { 
             // Teste ob ViewState auch nicht "null" ist und gib einen Wert zurück 
             //     der beschreibt ob der Benutzer eingeloggt ist 
             return (ViewState["isAuth"]  == null) ? false : (bool) ViewState["isAuth"] ; 
         } 
     } 
  
     private void AuthUser( object sender, EventArgs e ) { 
         if ( "default" != User.Text ) 
             lblErr.Text = "<font color=\"red\">Der Benutzername ist falsch!</font>"; 
         else if ( "00000" != Pass.Text ) 
             lblErr.Text = "<font color=\"red\">Das Passwort ist falsch!</font>"; 
         else 
             ViewState["isAuth"]  = true; 
     } 
     </script> 
  

    <table style="background-color:gray; border: 1px solid black;" cellspacing="15">
        <tr>
            <td>
                <b>Login: </b>
            </td>
            <td>
                <asp:TextBox id="User" runat="server" OnTextChanged="AuthUser" />
            </td>
        </tr>
        <tr>
            <td>
                <b>Password: </b>
            </td>
            <td>
                <asp:TextBox id="Pass" TextMode="Password" OnTextChanged="AuthUser"
                    runat="server"/>
            </td>
        </tr>
        <tr>
            <td> </td>
            <td>
                <asp:Button id="Btn_Login" Text="Login" onClick="AuthUser" runat="server"/>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:Label id="lblErr" runat="server" />
            </td>
        </tr>
    </table>


Wenn du jetzt wieder die Seite default.aspx in einem Browser öffnest siehst du die Loginfläche. Wenn du einen falschen Benutzenamen oder ein falsches Passwort eingibst wird dir das gesagt, aber noch passiert nix wenn alles stimmt.

Dafür öffnen wir wieder default.aspx in notepad und fügen folgenden Skriptblock hinzu (der rote Teil):


    <%@ Register TagPrefix="MyLogin" TagName="Login" src="uc_login.ascx" %>

    <html>
        <head>
            <title>Meine erste ASP.NET Seite</title>
        </head>
 
     <script language="c#" runat="server"> 
     // Page_Load wird immer geöffnet wenn die Seite geöffnet wird 
     void Page_Load( object sender, EventArgs e ) { 
         Label_Message.Text = ""; 
         // Page.IsPostBack beschreibt ob die Seite zum ersten Mal geöffnet wurde  
         //     (dann ist es false) oder ob ein Event auf dieser Seite  
         //     stattfunden hat (dann ist es true) 
         if ( Page.IsPostBack && MyLogin.isAuthenticated ) { 
             Label_Message.Text += "<font color=\"green\">Du wurdest erfolgreich" + 
                  "authetifiziert!</font>"; 
              MyLogin_1.Visible = false; 
         }  
     }
  
     </script> 
  

        <body>
            <MyLogin:Login id="MyLogin" runat="server"/>
        </body>
    </html>

Nun verschwindet die Loginfläche - vorausgesetzt der Benutzer hat die korrekten daten eingegeben - und wird ersetzt durch die Meldung "Du wurdest erfolgreich authetifiziert!".
Anstelle der Meldung könnte natürlich jetzt auch eine andere User Control geladen werden.