<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>ASP.NET - Membership API</title>
        <link>http://blogs.ugidotnet.org/matteomigliore/category/2636.aspx</link>
        <description>ASP.NET - Membership API</description>
        <language>it-IT</language>
        <copyright>Matteo Migliore</copyright>
        <managingEditor>matteo.migliore@gmail.com</managingEditor>
        <generator>Subtext Version 2.0.0.43</generator>
        <item>
            <title>Implementare un custom Membership provider con ASP.NET</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2007/10/26/implementare-un-custom-membership-provider-con-asp.net.aspx</link>
            <description>Un esempio su come scrivere un custom Membership provider per ASP.NET che consenta di validare correttamente la password nei vari metodi. &lt;br /&gt;
In particolare se la password non rispetta i vincoli imposti dal provider, la cosa da fare è lanciare un eccezione, che viene poi intercettata dai Login control e viene comunicato all'utente il problema. Bisogna inoltre invocare il metodo OnValidatingPassword, nel caso in cui la password sia corretta, per scatenare l'evento ValidatingPassword del provider. &lt;br /&gt;
Qui il codice:
&lt;pre class="csharpcode2"&gt;&lt;span class="kwrd2"&gt;public&lt;/span&gt; &lt;span class="kwrd2"&gt;override&lt;/span&gt; &lt;span class="kwrd2"&gt;bool&lt;/span&gt; ChangePassword(&lt;span class="kwrd2"&gt;string&lt;/span&gt; username, &lt;span class="kwrd2"&gt;string&lt;/span&gt; oldPassword, &lt;span class="kwrd2"&gt;string&lt;/span&gt; newPassword)
{
    PasswordCheck passwordCheck = IsValidPassword(newPassword);
    &lt;span class="kwrd2"&gt;if&lt;/span&gt; (passwordCheck == PasswordCheck.MinRequiredPasswordLength)
        &lt;span class="kwrd2"&gt;throw&lt;/span&gt; &lt;span class="kwrd2"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Password does not respects min required lenght."&lt;/span&gt;);

    &lt;span class="kwrd2"&gt;if&lt;/span&gt; (passwordCheck == PasswordCheck.NonAlphanumericCharacters)
        &lt;span class="kwrd2"&gt;throw&lt;/span&gt; &lt;span class="kwrd2"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Password does not respects alphanumeric lenght."&lt;/span&gt;);

    ValidatePasswordEventArgs e = &lt;span class="kwrd2"&gt;new&lt;/span&gt; ValidatePasswordEventArgs(username, newPassword, &lt;span class="kwrd2"&gt;false&lt;/span&gt;);
    OnValidatingPassword(e);
    &lt;span class="kwrd2"&gt;return&lt;/span&gt; &lt;span class="kwrd2"&gt;true&lt;/span&gt;;
}

&lt;span class="kwrd2"&gt;public&lt;/span&gt; &lt;span class="kwrd2"&gt;override&lt;/span&gt; MembershipUser CreateUser
    (&lt;span class="kwrd2"&gt;string&lt;/span&gt; username, &lt;span class="kwrd2"&gt;string&lt;/span&gt; password, 
     &lt;span class="kwrd2"&gt;string&lt;/span&gt; email, &lt;span class="kwrd2"&gt;string&lt;/span&gt; passwordQuestion, 
     &lt;span class="kwrd2"&gt;string&lt;/span&gt; passwordAnswer, &lt;span class="kwrd2"&gt;bool&lt;/span&gt; isApproved, 
     &lt;span class="kwrd2"&gt;object&lt;/span&gt; providerUserKey, &lt;span class="kwrd2"&gt;out&lt;/span&gt; MembershipCreateStatus status)
{
    &lt;span class="kwrd2"&gt;if&lt;/span&gt; (IsValidPassword(password) != PasswordCheck.Valid) {
        status = MembershipCreateStatus.InvalidPassword;
        &lt;span class="kwrd2"&gt;return&lt;/span&gt; &lt;span class="kwrd2"&gt;null&lt;/span&gt;;
    }

    ValidatePasswordEventArgs e = &lt;span class="kwrd2"&gt;new&lt;/span&gt; ValidatePasswordEventArgs(username, password, &lt;span class="kwrd2"&gt;true&lt;/span&gt;);
    OnValidatingPassword(e);

    DateTime now = DateTime.Now;
    status = MembershipCreateStatus.Success;
    MembershipUser user = &lt;span class="kwrd2"&gt;new&lt;/span&gt; MembershipUser
        (&lt;span class="kwrd2"&gt;this&lt;/span&gt;.GetType().Name, username, Guid.NewGuid(), 
         email, passwordQuestion, &lt;span class="kwrd2"&gt;string&lt;/span&gt;.Empty, &lt;span class="kwrd2"&gt;true&lt;/span&gt;, &lt;span class="kwrd2"&gt;false&lt;/span&gt;, 
         now, now, now, now, now);
    HttpContext.Current.Cache[user.UserName] = user;
    &lt;span class="kwrd2"&gt;return&lt;/span&gt; user;
}

&lt;span class="kwrd2"&gt;private&lt;/span&gt; &lt;span class="kwrd2"&gt;enum&lt;/span&gt; PasswordCheck { 
    Valid = 0,
    NonAlphanumericCharacters = 2,
    MinRequiredPasswordLength = 4
}

&lt;span class="kwrd2"&gt;private&lt;/span&gt; PasswordCheck IsValidPassword(&lt;span class="kwrd2"&gt;string&lt;/span&gt; password) {
    &lt;span class="kwrd2"&gt;if&lt;/span&gt; (password.Length &amp;lt; &lt;span class="kwrd2"&gt;this&lt;/span&gt;.MinRequiredPasswordLength)
        &lt;span class="kwrd2"&gt;return&lt;/span&gt; PasswordCheck.MinRequiredPasswordLength;

    &lt;span class="kwrd2"&gt;int&lt;/span&gt; nonAlphanumericCharacters = 0;
    &lt;span class="kwrd2"&gt;for&lt;/span&gt; (&lt;span class="kwrd2"&gt;int&lt;/span&gt; i = 0; i &amp;lt; password.Length; i++)
    {
        &lt;span class="kwrd2"&gt;if&lt;/span&gt; (!&lt;span class="kwrd2"&gt;char&lt;/span&gt;.IsLetterOrDigit(password, i))
            nonAlphanumericCharacters++;
    }

    &lt;span class="kwrd2"&gt;if&lt;/span&gt; (nonAlphanumericCharacters &amp;lt; &lt;span class="kwrd2"&gt;this&lt;/span&gt;.MinRequiredNonAlphanumericCharacters)
        &lt;span class="kwrd2"&gt;return&lt;/span&gt; PasswordCheck.NonAlphanumericCharacters;

    &lt;span class="kwrd2"&gt;return&lt;/span&gt; PasswordCheck.Valid;
}

&lt;span class="kwrd2"&gt;public&lt;/span&gt; &lt;span class="kwrd2"&gt;override&lt;/span&gt; MembershipUser GetUser(&lt;span class="kwrd2"&gt;string&lt;/span&gt; username, &lt;span class="kwrd2"&gt;bool&lt;/span&gt; userIsOnline)
{
    MembershipUser user = HttpContext.Current.Cache[username] &lt;span class="kwrd2"&gt;as&lt;/span&gt; MembershipUser;
    &lt;span class="kwrd2"&gt;return&lt;/span&gt; user;
}

&lt;span class="kwrd2"&gt;public&lt;/span&gt; &lt;span class="kwrd2"&gt;override&lt;/span&gt; &lt;span class="kwrd2"&gt;bool&lt;/span&gt; ValidateUser(&lt;span class="kwrd2"&gt;string&lt;/span&gt; username, &lt;span class="kwrd2"&gt;string&lt;/span&gt; password)
{
    MembershipUser user = HttpContext.Current.Cache[username] &lt;span class="kwrd2"&gt;as&lt;/span&gt; MembershipUser;
    &lt;span class="kwrd2"&gt;return&lt;/span&gt; ((user != &lt;span class="kwrd2"&gt;null&lt;/span&gt;) &amp;amp;&amp;amp; user.GetPassword().Equals(password));
}&lt;/pre&gt;
&lt;br /&gt;
Matteo Migliore.&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/89215.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2007/10/26/implementare-un-custom-membership-provider-con-asp.net.aspx</guid>
            <pubDate>Thu, 25 Oct 2007 22:07:46 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/89215.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2007/10/26/implementare-un-custom-membership-provider-con-asp.net.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/89215.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/matteomigliore/services/trackbacks/89215.aspx</trackback:ping>
        </item>
        <item>
            <title>Profile API ASP.NET: disabilitare LastActivityDate, quando non serve</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2007/06/28/83923.aspx</link>
            <description>&lt;p&gt;Le Profile API sono una feature di ASP.NET che conosco in quanto è uno degli argomenti che tratto durante i corsi che tengo, ma in realtà non la uso mai perchè preferisco creare domain model ad-hoc.
&lt;br /&gt;
In un progetto che sto seguendo ho voluto affidarmi temporaneamente all'utilizzo di questa funzionalità, che ci ha fatto risparmiare un po' di tempo.
&lt;br /&gt;
Il fatto è che ha creato un problema di riflesso, era ovvio :-); interrogando le proprietà del profilo viene anche aggiornata la proprietà LastActivityDate dell'utente a cui è associato, usando l'SqlMembershipProvider.
&lt;br /&gt;
In questo modo, ciclando sugli utenti per visualizzarli in un GridView ad esempio, appaiono tutti online :-D.&lt;br /&gt;
&lt;br /&gt;
La proprietà MembershipUser.IsOnline infatti viene calcolata facendo la differenza tra la Membership.UserIsOnlineTimeWindow e LastActivityDate appunto.
&lt;br /&gt;
La soluzione a questo problema la trovate qui:&lt;br /&gt;
&lt;a href="http://www.dotnet-friends.com/fastcode/sql/fastcodeinsqld7f4ebfa-dcc1-4f18-a073-3f3d10885207.aspx"&gt;http://www.dotnet-friends.com/fastcode/sql/fastcodeinsqld7f4ebfa-dcc1-4f18-a073-3f3d10885207.aspx&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Attenzione anche al metodo Membership.GetUser(username) o Membership.GetUser(providerUserKey), entrambi hanno un overload che consente di specificare se aggiornare LastActivityDate passando un bool userIsOnline.&lt;br /&gt;
&lt;br /&gt;
Matteo Migliore.&lt;/p&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/83923.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2007/06/28/83923.aspx</guid>
            <pubDate>Thu, 28 Jun 2007 10:08:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/83923.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2007/06/28/83923.aspx#feedback</comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/83923.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/matteomigliore/services/trackbacks/83923.aspx</trackback:ping>
        </item>
        <item>
            <title>Una mini-applicazione... in espansione :-)!</title>
            <link>http://blogs.ugidotnet.org/matteomigliore/archive/2007/04/18/75799.aspx</link>
            <description>&lt;P&gt;Ho creato una piccola solution, grazie ad una domanda su NG (microsoft.public.it.dotnet.asp), che pu&amp;#242; essere uno startup per capire come gestire l'autenticazione in ASP.NET sfruttando le MemberShip API.&lt;BR&gt;&lt;BR&gt;La solution contiene una classe chiamata SimpleMembershipProvider che implementa solo un metodo della classe abstract MembershipProvider, il metodo ValidateUser che data username e password restituisce true se le credenziali fornite sono valide, false altrimenti.&lt;BR&gt;&lt;BR&gt;La classe fa il minimo indispensabile, pu&amp;#242; servire per utilizzare i Login controls di ASP.NET e al tempo stesso non dover scomodare uno storage.&lt;/P&gt;
&lt;P&gt;L'intento sarebbe quello di creare una delle tante WebApplication, completa di tutte le funzionalit&amp;#224; che rende disponibili ASP.NET 2.0.&lt;/P&gt;
&lt;P&gt;Ma adesso, dove posso pubblicarla sul Blog?&lt;/P&gt;&lt;img src="http://blogs.ugidotnet.org/matteomigliore/aggbug/75799.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Matteo Migliore</dc:creator>
            <guid>http://blogs.ugidotnet.org/matteomigliore/archive/2007/04/18/75799.aspx</guid>
            <pubDate>Wed, 18 Apr 2007 13:04:00 GMT</pubDate>
            <wfw:comment>http://blogs.ugidotnet.org/matteomigliore/comments/75799.aspx</wfw:comment>
            <comments>http://blogs.ugidotnet.org/matteomigliore/archive/2007/04/18/75799.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blogs.ugidotnet.org/matteomigliore/comments/commentRss/75799.aspx</wfw:commentRss>
            <trackback:ping>http://blogs.ugidotnet.org/matteomigliore/services/trackbacks/75799.aspx</trackback:ping>
        </item>
    </channel>
</rss>