HowToCode "ReadYou": Neue Gedanken zum Usersystem mit OpenID, Windows Live und co.

Mein letzter direkter “ReadYou” Post ist schon etwas länger her – meine Membership-Idee habe ich in einem HowTo mal verwirklicht, allerdings hatte ich bisher keine Gelegenheit mehr zu coden.

Authentication, Authorization & Personalization
Für mich persönlich war der Kommentar von Andre Loker ein Anstoß darüber nachzudenken, das Membership System komplett zu entfernen bzw. einfach meinen eigenen Provider zu schreiben. Die verschiedenen Tabellen vom Membership-System find ich recht “groß” und unübersichtlich.
Insbesondere passt aber das Membership-System nicht ganz in meine Architektur rein.

Gut, dass nicht nur ich so denke, sondern inzwischen auch Rob Conery zu diesem Ergebnis gekommen ist. Den Anstoß gab Ayende Rahien in dem 15 Teil vom MVC Storefront Screencast.
Inzwischen hat Rob den 16 Teil fertig gestellt – in diesem verwirft er das Membership-System und implementiert prototypisch OpenID.

Hinweis: Meine Anwendung wird stark an die Architektur von Rob angelehnt sein – ich hab dies bereits produktiv in einem Projekt eingesetzt und bin positiv überrascht wie gut dies geklappt hat :)
Die gesamte MVC Storefront Serie ist sehr sehenswert!

Robs Screencast endet bei dem Login mit OpenID – er erwähnt noch, dass er sich nun auch Gedanken macht, wie er die OpenID tatsächlich an einen User knüpfen kann. Selbe Gedanken beschäftigen mich ebenfalls schon eine Weile (und insbesondere habe ich ja noch den mutigen Vorschlag gehabt Windows Live ID mit zu unterstützen ;) ).

Was es nicht heute alles gibt
Ich muss zugeben, dass ich früher mir nicht so einen großen Kopf um das Usersystem an sich gemacht hatte – da wird das Passwort und ein Loginname vergeben und gut ist.
Allerdings bin ich der Meinung, dass hier einige große Veränderungen kommen – warum sich bei X-Diensten registrieren, wenn man doch z.B. eine OpenID hat.
Auch CardSpace ist eine Sache – Produktiv hab ich das (bis auf den Blog Kim Cameron) nicht gesehen.

Jetzt eine Frage an meine werte Leserschaft: Wer von euch weiß was OAuth ist und was man damit machen kann? So richtig schlau werde ich aus der Seite nicht.

Wo stehen wir momentan?
Momentan beschäftigt mich das Grundkonzept von diesen verschiedenen Diensten etwas – da mir leider da auch TDD nicht weiterhelfen kann, versuche ich mich erstmal zu informieren.
Ein paar interessante Links (neben den MVC Storefront) :

Das wäre es (leider) für heute erst mal.
Ein Hinweis noch: Mir ist bewusst, dass ich mich doch recht lange an einem doch trivial klingenden Thema aufhalte – allerdings genau wegen solchen Sachen mach ich das ja auch. Wer würde das denn sonst auch bezahlen? ;)

HowTo: Membership in Klassenbibliotheken / DLLs

In diesem HowTo habe ich das ASP.NET Membership System mal kurz vorstellt. Ich hab in einem Projekt nun das Membership System eingesetzt und auch seine großen Schattenseiten kennengelernt.

Der erste große Kritikpunkt:
Da entwirft man eine 3-Tier Architektur und am Ende hängt einer der wichtigsten Teile (das Usersystem) mit in der WebApp – das ist mehr als unschön.

Mein Wunsch: Das Usersystem soll mit im Backend verschwinden.
Eine grobe Skizze (wobei man den “Service” noch in andere Schichten unterteilen kann):

image
Die “App.Config” sollte den ConnectionString speichern und auch die Membership-Konfiguration übernehmen.
Ich sage hier bewusst “sollte”, da ich es leider nicht ganz so perfekt hinbekommen hab.

Allerdings erst mal Schritt für Schritt: Das Membership-System muss in eine DLL rein.

Grundsätzlicher Aufbau:

image

  • DllMembership.Lib” ist unser Service in dem wir unseren “MembershipService” haben.
  • DllMembership.Web” ist eine gewöhnliche ASP.NET Website.
  • DllMembership.Test” ist unser UnitTest-Projekt

Schritt 1: Membership-System in der DLL Konfigurieren

Als erstes müssen wir in der App.Config folgende Konfiguration erstellen:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="ASPNETDBConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename='C:\Users\rmu\Documents\Visual Studio 2008\Projects\Blogposts\DllMembership\DllMembership.Lib\DB\ASPNETDB.MDF';Integrated Security=True;User Instance=True"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
  <system.web>
    <membership>
      <providers>
        <remove name="AspNetSqlMembershipProvider"/>
        <add name="AspNetSqlMembershipProvider"
             type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
             connectionStringName="ASPNETDBConnectionString"
             enablePasswordRetrieval="false"
             enablePasswordReset="true"
             requiresQuestionAndAnswer="false"
             applicationName="/"
             requiresUniqueEmail="true"
             passwordFormat="Hashed"
             maxInvalidPasswordAttempts="12"
             minRequiredPasswordLength="1"
             minRequiredNonalphanumericCharacters="0"
             passwordAttemptWindow="10"
             passwordStrengthRegularExpression="" />
      </providers>
    </membership>
  </system.web>
</configuration>

Die Data Source muss natürlich entsprechend des DB Speicherortes ausgewechselt werden.
Wichtiger Hinweise: Ich verwende dieselbe DB wie aus dem anderen Blogpost.
Ganz wichtig: Damit die App.Config auch angenommen wird, müssen die Properties richtig gesetzt sein:

image

Jetzt fügen wir noch die “System.Web” Referenz hinzu:

image

Schritt 2: Service schreiben

Jetzt implementieren wir unseren sehr einfachen Service:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;

namespace DllMembership.Lib
{
    public class MembershipService
    {
        public IList<User> GetUsers()
        {
            MembershipUserCollection col = Membership.GetAllUsers();
            List<User> returnList = new List<User>();
            foreach (MembershipUser user in col)
            {
                User u = new User();
                u.Name = user.UserName;
                u.Email = user.Email;
                returnList.Add(u);
            }
            return returnList;
        }

        public User Login(string username, string password)
        {
            User returnUser = new User();

            if (Membership.ValidateUser(username, password))
            {
                returnUser.IsLoggedIn = true;
                returnUser.Name = username;
                returnUser.Password = password;
                return returnUser;
            }
            else
            {
                returnUser.IsLoggedIn = false;
                return returnUser;
            }
        }

        public User GetUser(string username)
        {
            MembershipUser user = Membership.GetUser(username);
            User returnUser = new User();
            returnUser.Name = user.UserName;
            returnUser.Email = user.Email;
            return returnUser;
        }
    }
}

Dieser Service gibt ein “User” Objekt zurück (im Prinzip findet ein Mapping zwischen dem MembershipUser und unserem User statt) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DllMembership.Lib
{
    public class User
    {
        public bool IsLoggedIn { get; set; }
        public string Name { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
    }
}

Diese “User” Klasse fungiert ebenfalls als “Result” für unsere Service-Aufrufe. Klappt zum Beispiel die Login-Methode nicht, wird einfach die “IsLoggedIn” Property auf false gesetzt.

Schritt 2.5: Unit Tests

Ich habe 3 Unit-Test Methoden geschrieben, welche die grobe Funktionalität testen. Das klappt soweit.

Schritt 3: Das Web-Projekt
Damit unser Nutzer während einer Session auch eingeloggt bleibt, müssen wir noch die Form-Authentication aktivieren.
Hier müssen wir noch den Cookie “manuell” setzen. Dazu habe ich eine AppHelper mir erstellt:

namespace DllMembership.Web
{
    public static class AppUtil
    {
        public static User GetActiveUser()
        {
        if(HttpContext.Current.User.Identity.IsAuthenticated == false)
            {
                return new User() { IsLoggedIn = false };
            }
            else
            {
                MembershipService service = new MembershipService();
                User returnValue = service.GetUser(HttpContext.Current.User.Identity.Name);
                returnValue.IsLoggedIn = true;
                return returnValue;
            }
        }

        public static User Login(string username, string password)
        {
            MembershipService service = new MembershipService();
            User returnValue = service.Login(username, password);
            if (returnValue.IsLoggedIn)
            {
                FormsAuthentication.SetAuthCookie(returnValue.Name, true);
                returnValue.IsLoggedIn = true;
            }
            else
            {
                returnValue.IsLoggedIn = false;
            }

            return returnValue;
        }
    }
}

Hierbei gibt es zwei Methoden “GetActiveUser” und “Login”.
Zum “Login”:
Diese Methode übergibt die Parameter zum Service und wenn der Login erfolgreich war, wird dieser über ein Cookie über die Session hinweg authentifiziert.
Die “GetActiveUser”:
Diese Methode schaut einfach, ob der User im HttpContext authentifiziert ist, wenn nicht, gibt es keinen angemeldeten Nutzer, ansonsten wird der aktuelle Nutzer geladen.

Schritt 4: Ausgabe des Usernamen auf der Website

            DllMembership.Lib.User returnUser = AppUtil.GetActiveUser();
            if (returnUser.IsLoggedIn == false)
            {
                this.UserName.Text = "unangemeldet";
            }
            else
            {
                this.UserName.Text = returnUser.Name;
            }

Dadurch können wir leicht prüfen, ob jemand angemeldet ist, oder nicht.

Das Problem dabei
Leider geht die Lösung so wie ich sie hier gepostet habe, nicht ganz, denn man muss leider in der Web.Config die Membership Konfiguration und den ConnectionString noch extra angeben.
Das “Witzige” an der Geschichte: Die Unit-Tests laufen. Sobald dies aber auf der Webseite genutzt wird, überschreiben wohl die Web.Config Einstellungen die App.Config Einstellung – ihr könnt es gerne selber ausprobieren.
Ich finde das etwas unschön, aber verschmerzbar (bzw. fällt mir nix anderes ein).
Wenn jemand eine Lösung weiß, dann her damit :)

Fazit
Das ist nur ein “Prototyp”, ich habe längst nicht alles fertig mir ausgedacht und würde vielleicht noch extra Properties einbauen und den Service umbasteln. Allerdings sollte dies der erste Schritt sein um zu zeigen, wie man das Membership dahin packt, wo es hingehört: In eine andere Schicht.

[ Download Source Code ]
* In den *.config muss der ConnectionString angepasst werden
** Anmeldedaten stehen in der ReadMe.txt in WebApp Ordner

ASP.NET MVC – "AddIns" auf Codeplex

Da ich gerade selber an einem MVC "Testprojekt" arbeite, schau ich mir natürlich auch mal andere Ansätze oder "Zusätze" an, welche sicherlich ein Blick wert sind. Achtet allerdings auf die verwendete Lizenz.

Troy Goode´s Implementation von dem ASP.NET Membership System in MVC – schade das ich meine MVC Membership Version nicht besser bekannt gemacht hab (naja, nochmal passiert das nicht ;) )

>> Lizenz

Jedes Eingabefeld benötigt irgendwo eine Validierung – hier ein interessanter Ansatz wie man die geschickt mit Filtern und jQuery lösen könnte.

>> Lizenz

4 neue Viewengines, Code Snippets, Extensions etc.

>> Lizenz

 

Das MVC Demoprojekt überhaupt: Kigg (Lizenz)

ASP.NET MVC Preview 2 + Membership

Ich hab mich in den letzten 3 Tagen (jeweils vielleicht 1,5 Stunden)  mit dem ASP.NET MVC (Preview 2) beschäftigt.

Wer ASP.NET MVC mit dem Visual Web Developer ausprobieren möchte, der schaut sich am besten diesen Blogpost von mir an.

Wenn man das MVC Modell installiert hat, bekommt man eine neue Projektvorlage:

image

Wenn man dies nun das erste mal startet, erblickt man eine doch schon nett ausschauende Seite:

image

Leider kann man nur zwischen "Home" und "About" hin und her schalten.

Ich will ein einfaches Loginsystem haben

Grob hab ich ähnliche Schritte wie hier gemacht – also ASP.NET DB aufgesetzt, User eingetragen & das Menü erstmal erweitert (und die CSS etwas umgestellt) :

Vorher:

image

Nachher:

image

Der "Login" & "Register" Button verweist auf den LoginController (die genaue Implementation findet ihr im Download) :

image 
(das Attribut wird später erklärt)

Im Login Userinterface sieht das so aus
"Index.aspx"

image 

"PasswordRecovery.aspx"

image 
(nicht wundern: hier gibt man den Nutzernamen ein und das generierte Passwort wird hier wieder ausgegeben – in einer richtigen Applikation würde man dies über eine Email an den jeweiligen schicken)

"Register.aspx"

image

In der Dateistruktur ist es recht übersichtlich:

image

Nach einem erfolgreichen Login

Das Menü wird entsprechend (über das ASP.NET LoginView Control) verändert:

image

Das Profil kann man auf dieser Seite ansehen:

image

… und editieren:

image

In der Dateistruktur:

image

… und der Controller:

image

Rechtesystem mit Rollensystem

Ich habe noch eine Adminrolle hinzugefügt, dieser kann User auf einer Übersichtsseite wieder löschen und hat eine anderes Menü:

image

Die Administrationsseite:

image

Der "Delete" link verweisst auf diese URL:

"/Useradmin/Delete/[USERNAME]"

Der Controller ist auch recht einfach:

image

Mit einem Klick auf den Link wird der Nutzer gelöscht.

Wie sieht das ganze Projekt aus?

image

Das ist das gesamte Projekt – sieht auf dem ersten Blick viel aus, allerdings ist es einfach durch das MVC Paradigma eine solche Trennung zwischen den einzelnen Views. Die Views selbst sind meistens sehr schmal gehalten.

Was machen diese Attribute "RequiresRole" & "RequiresAuthentication"?

In ASP.NET WebForms kann man über die Web.config die Sicherheitsregeln einstellen. Das wird auf die entsprechende URL gemappt – da aber die URL im MVC nur noch wenig mit der richtigen Pfadangabe zutun hat, gibt es da natürlich Probleme.

Abhilfe schaffen diese beiden Attribute, welche überprüfen, ob der Nutzer authentifiziert ist oder ob er in der angegebenen Rolle ist. Der Code dafür stammt von Rob Conerys Blog.

Wie schickt man Daten an den Controller und wieder zurück?

Um mal ein Beispiel zu zeigen, wie einfach die Kommunikation zwischen den Controllern und den Viewpages ist, möchte ich die Register Methode im LoginController erklären:

image

Damit ich die Registrierseite unter der URL "Login/Register" erreichen kann, prüfe ich im ersten Schritt, ob ich bereits irgendwelche Daten in dem Request stehen.

Wenn ja:

Verarbeite die Daten – also befülle das Membership System. Wenns ein Fehler gibt (z.B. der Nutzer existiert bereits), dann merke dir in "ViewData", dass ein Fehler aufgetreten ist und render den View.
Die Membership API ist in diesem Fall unser Model – das wir entsprechend befüllen.

Wenn nein:

Render den View

Im View ist sehr einfaches HTML – keine runat="server" etc.

Hinweis: Scott Guthrie hat dieses Thema bereits vor einige Zeit gut erklärt.

Erweitertes Beispiel ist fertig.

Man kann sich bei der Demoapplikation nun Anmelden, Registrieren, ein neues Passwort generieren lassen wenn es vergessen wurde, seine Hauptdaten ändern und der Admin kann Nutzer löschen – ich denke für einen ersten Wurf ist das eigentlich schon ok :)

Unten findet ihr diese Applikation zum Runterladen und selber ausprobieren. Wichtig ist, dass ihr die ASP.NET MVC Preview 2 installiert habt.

An die Kritiker, die meinen, dass man das mit den eingebauten ASP.NET Controls viel schneller hinbekommt: Das mag erstmal hier vielleicht stimmen – allerdings sind die Controls verdammt umständlich, wenn man die etwas verändern möchte oder ganz einfache Funktionalität einbauen möchte.
Im Zusammenhang mit einer Masterpage (und vielleicht wenn man das Logincontrol noch abändert), funktioniert die "Enter" Taste nicht mehr – das muss man erst recht komplex umstellen. Das ganze ist recht fix implementiert gewesen – die Geschwindigkeit (und die nette Logik) mit der man entwickelt empfinge ich als ex-PHP Entwickler wesentlich logischer, als dieses Postback Modell.

Wer auf pures HTML steht (dazu zähle ich mich) und diese Servercontrols für den "falschen" Weg hält, der sollte sich das Beispiel hier mal anschauen. Ich gebe zu, dass der Inlinecode sicherlich auch noch nicht ganz der Weisheit letzter Schluss ist, allerdings ist eine ViewPage auch nichts anderes als eine Klasse, welche ein Konstruktor hat – wenn man dies alles noch mit kleinen Methoden und/oder UserControls auslagert, ist das MVC Model für viele Fälle sicher auch eine ebenso gute Wahl.

Letzter Hinweis:

Das ist eine Demoapplikation – wer sich näher mit dem MVC Modell beschäftigt, wird bestimmt noch viele weitere coole Features finden.

[ Download Democode ]*

* in der ReadMe.txt stehen die Logindaten für das Beispiel

Empfohlene Links:

Die Videos von Scott Hanselman zu ASP.NET MVC sowie die Northwind Sample App sollte man sich auch anschauen.

HowTo: ASP.NET Membership, Roles & Profiles – Einrichten, Rollensystem, Allgemeines & Demoprojekt

Jetzt werde ich sicherlich über ein etwas älteres Thema schreiben. Allerdings hatte ich erst jetzt damit zutun und da ich doch einige Anfangsschwierigkeiten hatte, werde ich hier nach und nach Informationen zum Membership System von ASP.NET niederschreiben. Ziel soll es sein auch CardSpace oder OpenID mit einzubinden – mal sehn wann dies geschehen wird.

Dies ist der “Einstiegsteil” in das Thema, fangen wir daher nun an:

Membership? Was ist das?

Das ASP.NET Membership System wurde mit ASP.NET 2.0 eingeführt und stellt eine einheitliche API zum Benutzer-, Rollen-, Profilmanagement sowie Authentifierung bereit. Zudem gibt es noch einige UI Controls in ASP.NET.

Das ganze Membership System ist zudem erweiterbar – dazu gibt es ein Providermodell.

Wie funktioniert das ganze?

Von Microsoft direkt gibt es ein Provider für Active Directory und für den SQL Server (desweiteren kann man noch in der web.config feste Nutzer einrichten). Der SQL Provider ist für Internetanwendungen geeignet, dabei wird von ASP.NET eine solche DB erzeugt:

image

Es gibt auch bereits Provider für alles mögliche – z.B. auch für MySQL. Natürlich kann man auch seinen eigenen Membership Provider schreiben. Schauen wir uns erstmal Schritt für Schritt an, was man tun muss, um eine solche Datenbank zu bekommen.

Schritt 1: Web Site anlegen & ASP.NET Configuration starten

Ich empfehle eine “Web Site”, weil es in Zusammenhang mit dem Profil System und “Web Projects” zu Problemen kommen kann. Visual Studio sollte zudem möglichst unter dem Admin Konto ausgeführt werden – bei mir hat es ansonsten immer mal geklemmt.

Sobald man solch ein Web Site angelegt hat, gibt es im Menü den Punkt “Website”, dort einfach auf “ASP.NET Configuration” gehen:

image

Danach öffnet sich eine Website mit mehreren Reitern – der interessanteste Teil dürfte sicherlich “Sicherheit” sein:

image

Unter “Authentifierzungstyp auswählen” kann man zwischen den SQL Provider und den AD Provider wechseln. Wenn man das erste mal den Punkt “Aus dem Internet” (also den SQL Provider) gewählt hat, dann wird die obrige Datenbank erstellt.
Hinweis: Das aspnet_regsql Tool erlaubt dies auch auf Basis der Kommandozeile.

Recht komfortabel kann man hier zudem Nutzer und Rollen einrichten und Zugriffsregeln setzen. Die Zugriffsregeln werden dabei jeweils in der web.config abgespeichert.

Wichtig ist, dass die Nutzer nach dem Anlegen aktiviert sind:

image

Rollen lassen sich ebenso managen.

Hinweis: Der Reiter “Anbieter” wird bei einem Custom Membership Provider interessant.

Schritt 2: ASP.NET Login Controls verwenden

Man kann den gesamten Authentifierungsprozess & das restliche Management über die Membership Klassen abbilden, allerdings hat Microsoft eine handvoll nützliche Controls bereits definiert:

image

Wenn man nichts verstellt hat, kann man das Login Control auf eine ASPX Seite ziehen und sich (nachdem Nutzer eingerichtet wurden) auch gleich anmelden. Einen Überblick über die einzelnen Controls gibt es hier.

Die meisten Controls können angepasst werden, z.B. das Login Control, aber auch andere.

Schritt 3: Grundgerüst erstellen

Ich mache mal eine Beispielhafte Implementation, welche ich am Ende auch zum Downloaden anbiete.

Das Grundgerüst sieht so aus

image

Es wurden 3 Nutzer eingerichtet und 3 Rollen – Benutzer, Redakteur und Administrator.

In dem Ordner “Redakteur” kommen nur Redakteure – in den Ordner “Admin” kommen nur Administrator – die Benutzer und anonyme kommen nur auf die “Default.aspx” im Root Verzeichnis – dies wurde über die ASP.NET Configuration vorgenommen.

Schritt 4: MasterPage einrichten

Auf jeder Seite wollen wir bei anonymen Nutzern einen “Anmelden” Button anzeigen oder bei bereits angemeldeten einen “Abmelden” Button – daher kommt dies in die MasterPage.
Zudem wollen wir jeden Nutzer “Willkommen” sagen und spezielle Links je nach Rolle ihm zur Verfügung stellen:

image

Das “LoginStatus” Control übernimmt den Login/Logout Part. Das “LoginView” Control bietet die Möglichkeit je nach Anmeldestatus informationen bereitzustellen:

image

Mithilfe des “LoginName” Control bekommen wir den Usernamen des momentan angemeldeten Nutzers raus.

Schritt 5: Login Page einrichten

Die Login.aspx ist Standardmäßig die Login Seite (ist in der web.config gespeichert) und muss natürlich ebenfalls noch mit einem Control gefüllt werden – das “Login” Control. Wenn man mit den normalen Aussehen leben kann, muss man hier auch nichts mehr machen. Falls man allerdings das design etwas stärker ändern möchte, muss man wie hier beschrieben z.B. ein Template anlegen.

image

Die Codebehinde sieht dann so aus:

image

Das wars eigentlich bereits. Wenn man diese Template Variante wählt, muss man dann natürlich um die ganze Funktionalität abzudecken, auch wie hier beschrieben die Elemente mit implementieren.

Sehr praktisch ist es auch, wenn ein nicht angemeldeter Nutzer z.B. die Adminseite besuchen möchte, wir automatisch auf die Login.aspx verlinkt, allerdings wird als Parameter die Zieladresse mitgegeben, sodass nach einem erfolgreichen Login man automatisch auf der “richtigen” Seite befindet:

image

Dafür ist diese Methode verantwortlich: FormsAuthentication.RedirectFromLoginPage.

Die technische Seite

Der angemeldete Nutzer ist in der Klassenhierarchie z.B. bei jeder Page oder HttpContext unter “User” zu finden:

image

Andere Teile finden sich auch in dem HttpSessionState:

image

Eine Sache zu den Controls

Die Login Controls renden oft nicht das, was man als normaler Webdesigner erwartet – dafür gibt es entweder den CSS Friendly Adapter oder man muss eigene Controls entwickeln, welche auf das Membership System aufsetzen.

Grundsatzfrage: Sollte ich das Membership verwenden oder was selber implementieren?

Das ist so eine nette Frage – wenn man sich in das System eingefunden hat, sieht man viele positive Sachen. Die Controls sind natürlich etwas garstig, aber auch das bekommt man in den Griff.

Wenn man selber eine Art Membership System realisiert, dann kann dies später zu einem Problem werden, da das Membership System ansich wie oben zu sehen ist, einiges im Hintergrund macht. Wozu selber so ein System dann realisieren? Dann lieber ein Custom Provider erstellen – dies wäre mein Rat zu dem Thema.

Weiterführende Links & Informationen

Scott Guthrie hat einige tolle Links zusammengefasst. Ein sehr gutes, 9 teiliges Tutorial gibt es zudem auch hier. Mein persönliches Lieblingsthema ASP.NET MVC kann man zudem ebenfalls mit dem Membership System (und den Controls) verheiraten: ASP.Net MVC Framework – Using Forms Authentication. Hier gibt es auch noch ein HowTo direkt auf der MSDN.

Es gibt auch direkt ein Buch was sich nur mit diesem Thema auseinandersetzt.

Download des Demoprojekts

Um das Demoprojekt auszuführen braucht ihr VS 2008 und in der web.config muss der Connection String noch angepasst werden. In der ReadMe.txt stehen die eingetragenen Nutzer samt Passwörter. Viel Spaß wünsch ich euch.

[ Download Democode ]

HowTo: ASP.NET Profile System mit Web Projects nutzen (Visual Studio 2005/2008)

ASP.NET 2.0 führte ein so genanntes “Membership” System ein – darunter sind allgemeine Benutzerregistrier-, Benutzerprofil- und Benutzerrollensystem gebündelt.

Insbesondere das Profilsystem hat mich heute etwas beschäftigt (auch wenn es etwas älter ist). Mit dem Profilsystem kann man einfach Benutzern bestimmte Attribute zuordnen, z.B. Name, Alter, Wohnort oder andere Verweise zu bestimmten Daten innerhalb der Applikation.

Das kann man natürlich auch selber in seiner DB zusammenbasteln – aber das ASP.NET Profile System bietet eine strenge Typsierung, sodass man in der Web.config folgendes anlegen kann:

<profile>
  <properties>
    <add name="PostalCode" />
  </properties>
</profile>

Und im Code hinter so aufrufen kann “Profile.PostalCode” – man kann auch direkt typen angeben, sodass man direkt festlegen kann, welcher Typ eine Profileigenschaft hat:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <system.web>
    <profile>
      <properties>
        <add name="BirthDate" type="DateTime"/>
        <add name="FavoriteNumber" type="int"/>
        <add name="Comment" type="string"/>
        <add name="FavoriteColor" type="string" defaultValue="Blue"/>
        <add name="FavoriteAlbums"
             type="System.Collections.Specialized.StringCollection"
             serializeAs="Xml"/>
      </properties>
    </profile>
  </system.web>
</configuration>

Das ganze wird zudem mit der Membership Datenbank synchronisiert – dort gibt es direkt eine “Profile” Tabelle in dem diese Werte reingeschrieben werden:

image

Das ganze kann man nun noch beliebig erweitern oder eigene Profil-Provider schreiben – hier ein anderer guter Artikel.

Doch wie ruft man denn nun eigentlich die Profileigenschaften ab? Das was auf den MSDN Seiten immer “Profile.[PROPERTY]” verwendet wird, ist schlecht dokumentiert.

Jedenfalls erstellt VS im Hintergrund automatisch eine “ProfileCommon” Klasse die überall erreichbar ist (* hier kommt noch eine Anmerkung!)

So kommt man an die Profile Eigenschaften (System.Web.Profile Namespace):

ProfileCommon profile = HttpContext.Current.Profile
as ProfileCommon;

Danach kann man über “profile.” seine Properties aufrufen.

* – die Anmerkung

Das ganze funktioniert aber nur mit dem “Web Site” Modell (hier z.B. ein Beispiel von Scott) – in Web Applications wird die ProfileCommon nicht automatisch erstellt.
Scott Guthrie schrieb auf einer sehr alten Seite (ganz unten) seine Lösung: WebProfile Generator (Alternative: Die Klasse manuell erstellen)

Problem hier: Das ganze läuft unter Visual Studio 2008 bisher nicht (daher manuell erstellen :( ) – wird aber hoffentlich bald kommen. Auf der Codeplex Seite habe ich bereits einen Kommentar gefunden, kann daher wohl nicht mehr lange dauern.

Anmerkung gernell

Es gibt sicherlich  noch die ein oder andere Möglichkeit auf die Profildaten zuzugreifen, aber extra wegen dieser streng-typisierten und leichten Variante habe ich das einer Eigenentwicklung vorgezogen – schauen wir mal, wann ich dies bereuen werde ;)