Thomas Bandt

Über mich | Kontakt | Archiv

Einmal Anonymous und zurück, bitte

Man stelle sich folgendes, vereinfachtes aber gängiges Szenario vor:

Seine Website ist lokalisiert, und man erlaubt sowohl anonymen als auch angemeldeten Benutzern, sich ihre Sprache selbst zu wählen. Diese Wahl speichert man im ASP.NET Profil des Benutzers:

web.config:

"true"
>
   
      "PreferredCulture" type="System.String" allowAnonymous="true" defaultValue="en"/>
   

Nun möchte man die Sprache übernehmen, wenn sich ein User einloggt. Das heißt man möchte in das offizielle Benutzerprofil die vorher als Anonymous gewählte Sprache übernehmen und dort speichern. Auch daran hat Microsoft gedacht:

Global.asax:

void
Profile_MigrateAnonymous(Object sender, ProfileMigrateEventArgs pe)
{
   ProfileCommon anonProfile = Profile.GetProfile(pe.AnonymousID);

   if (!string.IsNullOrEmpty(anonProfile.PreferredCulture))
      Profile.PreferredCulture = anonProfile.PreferredCulture;

   //Delete the anonymous data from the database
   ProfileManager.DeleteProfile(pe.AnonymousID);

   //Remove the anonymous identifier from the request so 
   //this event will no longer fire for a logged-in user
   AnonymousIdentificationModule.ClearAnonymousIdentifier();
}

Was hier passiert, ist in den Quickstart Tutorials beschrieben. Wichtig ist, dass man den anonymen User in Form seines Cookies in jedem Fall löschen muss, da sich sonst die Einstellungen für ihn und den nun eingeloggten Benutzer in die Quere kommen. Genauer wird dann z.B. die im eingeloggten Zustand gewählte Sprache einfach von der des Anonymous überschrieben.

So weit, so (immer noch) gut. Nun steht man aber vor einem Problem. Der User ist eingeloggt, der Anonymous gelöscht ... was ist, wenn sich der User nun wieder abmeldet? Was passiert dann mit seinen gewählten Einstellungen?

Richtig - diese werden gelöscht, und da ein neuer Anonymous-User erstellt wird, werden diesem die Default-Einstellungen zugewiesen. Das heißt wenn man - eingeloggt - noch alles auf Deutsch sah, bekommt man nun - ausgeloggt - alles auf Englisch angezeigt, weil im Profil als DefaultValue Englisch als Standardsprache gewählt wurde.

Leider hat Microsoft das passende Logout-Event nach meinen Recherchen vergessen, sodass man selbst Hand anlegen muss.

Was ist also zu tun?

Als erstes legen wir mal ein entsprechendes Event auf unseren Logout-Button, damit wir dort alles regeln können:

"LoginStatus1" runat="server" LogoutText="<%$ Resources:GlobalPageText,MembershipLogoutButton %>" OnLoggingOut="LoginStatus1_LoggingOut" />

protected void LoginStatus1_LoggingOut(object sender, LoginCancelEventArgs e)
{
   string pc = Profile.PreferredCulture;
   FormsAuthentication.SignOut();
   Response.Redirect("~/SelectLanguage.aspx?Language=" + pc, true);
}

Nun kommt sicher die Frage auf - warum ein Redirect? Der Reihe nach: als erstes speichern wir uns mal die gewählte Sprache des angemeldeten Benutzers zwischen. Dann loggen wir ihn manuell aus - ist ja zum Glück nur ein Einzeiler. Und jetzt liegt der Hase im Pfeffer: ich dachte zuerst, dass ich nun einfach dem - jetzt ja theoretisch bestehenden - anonymen User die Sprache wieder zuweise, via

Profile.SetPropertyValue("PreferredCulture", Language.SelectedValue);

Aber das geht natürlich nicht ... warum nicht? Ganz klar: weil ASP.NET bei diesem Request alle Kekse löscht. Das heißt alles was hier angelegt wird, wird nachher beim Schicken der Bytes an den Client wieder zerstört ... man muss sich diese Einstellung also merken und kann sie frühestens im nächsten Aufruf wieder setzen. Dafür habe ich mir in meinem Fall einer Weiche beholfen, die eh schon existiert hat, und sie eben um den Sprachparameter erweitert:

public partial class SelectLanguage : System.Web.UI.Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      string comesFrom = Request.QueryString["ComesFrom"];
      string targetUrl = "Default.aspx";
      string language = Request.QueryString["Language"];

      if (!string.IsNullOrEmpty(language))
      {
         string avaiableLanguages = ConfigurationManager.AppSettings["AvaiableLanguages"];
         if (!string.IsNullOrEmpty(avaiableLanguages))
         {
            string[] languages = avaiableLanguages.Split(';');
            foreach (string lng in languages)
            {
               string[] details = lng.Split(',');
               if (details[1].Trim().ToLower().Equals(language.Trim().ToLower()))
               {
                  Profile.SetPropertyValue("PreferredCulture", details[1].Trim().ToLower());
                  break;
               }
            }
         }
      }

      if (!string.IsNullOrEmpty(comesFrom))
      targetUrl = Path.GetFileName(comesFrom);

      Response.Redirect("~/" + Profile.PreferredCulture + "/" + targetUrl, true);
   }
}

Wie man sieht lässt sich also auch mit ASP.NET 2.0 hin und wieder relativ viel Aufwand, für relativ wenig Ergebnis nicht vermeiden. Nix mit 70% Code-Ersparung ;-)



« Zurück  |  Weiter »