Archives

Archives / 2009 / August
  • Using ASP.NET Providers in Non-ASP.NET Applications

    ASP.NET developers are most likely familiar with the rich provider-based modules supplied with ASP.NET. These are the Role Provider, the Membership Provider, the Profile Provider, the Personalization Provider, the Web Events Provider, the Site Map Provider, the Session State Provider and the Protected Configuration Provider. For detailed information on all of these modules, you should read this. The providers that I will talk about are the Role, Membership and Profile, which are the ones that may be used in non-ASP.NET applications.

    These post is targeted at Windows Forms users, since ASP.NET ones are probably familiar with all these concepts. 

    What's the purpose of using these providers in your applications? Well, they implement some typical requirements of enterprise-level applications, so you don't have to develop your own:

    • User creation, management, authentication and monitoring (Membership Provider)
    • Role creation and assignment to users (Role Provider)
    • Per-user configuration (Profile Provider)

    The concepts involved are:

    1. A user has certain well-known settable properties, such as a password, a question and an answer, an approval flag, an e-mail and some comments and some implicit properties, like the creation date, last login date, last activity date, logged-in flag, online flag, last lockout date and last password changing date
    2. A user may belong to none or some roles, a role may be associated with many users
    3. A user may have particular values for system-wide defined properties

    I will not get into details on all of these providers, and I won't also talk about rolling out your own providers, which is actually quite simple. The default providers are registed in the global Machine.config file, located in %WINDIR%\Microsoft.NET\Framework\v2.0.50727\Config with their default settings. All providers inherit indirectly from System.Configuration.Provider.ProviderBase.

    The default implementations, which are the ones I will talk about, require an SQL Server database, so we need to create it. We do so with the aspnet_regsql command, which you can find on %WINDIR%\Microsoft.NET\Framework\v2.0.50727. After you run it, you are prompted for the location of the SQL Server to use, and after that a number of tables and stored procedures are created. Don't forget to set it's connection string in App.config:

    <connectionStrings>

      <

    add name="SomeConnectionStringName" connectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=SomeDatabaseName" providerName="System.Data.SqlClient"/>  <add name="AuthorizationStoreConnectionName" connectionString="msxml://~/SomeAutorizationStore.xml" />

    </

    connectionStrings>

    Oracle has an identical set of providers, with the sole difference that they work with Oracle databases, which may come in handy if you really need to have Oracle instead of SQL Server. They are part of Oracle Data Access Components, and you can get it from the Oracle site, here.

    Now, let's move on to the providers. 

    Membership Provider 

    For the Membership Provider, the class that actually implements it is System.Web.Security.SqlMembershipProvider. The methods for the Membership Provider are defined in the abstract base class System.Web.Security.MembershipProvider. These are:

    • ChangePassword
    • ChangePasswordQuestionAndAnswer
    • CreateUser
    • DeleteUser
    • FindUsersByEmail
    • FindUsersByName
    • GetAllUsers
    • GetNumberOfUsersOnline
    • GetPassword
    • GetUser (overloaded)
    • GetUserNameByEmail
    • ResetPassword
    • UnlockUser
    • UpdateUser
    • ValidateUser

    The configuration properties are:

    • ApplicationName
    • EnablePasswordReset
    • EnablePasswordRetrieval
    • MaxInvalidPasswordAttempts
    • MinRequiredNonAlphanumericCharacters
    • MinRequiredPasswordLength
    • PasswordAttemptWindow
    • PasswordFormat
    • PasswordStrengthRegularExpression
    • RequiresQuestionAndAnswer
    • RequiresUniqueEmail

    And the single fired event is:

    • ValidatingPassword

    The Membership Provider is configured through the <system.web><membership> section of the App.config file (because we are developing a Windows Forms applications, otherwise it would be, of course, Web.config). In order to use it, you must configure a default provider on the configuration file, like this:

    <membership defaultProvider="SqlMembershipProvider">

      <providers>

        <

    add name="SqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="SomeConnectionStringName" enablePasswordRetrieval="false" enablePasswordReset="true  requiresQuestionAndAnswer="false" applicationName="SomeApplicationName" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"   passwordStrengthRegularExpression="" />  </providers>

    </

    membership>

    Then you can access it in code:

    MembershipUser user = null;

     

    try

    {

      user = System.Web.Security.Membership.CreateUser("ricardoperes", "somepassword");

    }

    catch

    {

      //user already exists  user = System.Web.Security.Membership.GetUser("ricardoperes");

    }

    //perform operations on user and don't forget to call UpdateUser when finished:

    System.Web.Security.

    Membership.UpdateUser(user);

    Role Provider

    The Role Provider implementation class is System.Web.Security.SqlRoleProvider, and the abstract base class that defines its operations is System.Web.Security.RoleProvider. These operations are:

    • AddUsersToRoles
    • CreateRole
    • DeleteRole
    • FindUsersInRole
    • GetAllRoles
    • GetRolesForUser
    • GetUsersInRole
    • IsUserInRole
    • RemoveUsersFromRoles
    • RoleExists

    And the sole property is:

    • ApplicationName

    You configure the Role Provider through section <system.web><roleManager>:

    <roleManager enabled="true" defaultProvider="SqlRoleProvider">

      <

    providers>    <add name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="SomeConnectionStringName" />

        <

    add name="AuthorizationStoreRoleProvider" type="System.Web.Security.AuthorizationStoreRoleProvider" connectionStringName="AuthorizationStoreConnectionName" applicationName="SomeApplicationName" cacheRefreshInterval="60" scopeName="" />  </providers>

    </

    roleManager>

    You may notice that I configured two Role providers. The second one, AuthorizationStoreRoleProvider, allows us to use AzMan for the definition of the roles, instead of Windows NT groups, and may be usefull if you want to have roles that differ from you machine's or Active Directory's groups.

    This is how you would use the Role Provider:

    if (System.Web.Security.Roles.RoleExists("Bloggers") == false)

    {

      System.Web.Security.Roles.CreateRole("Bloggers");

    }

    String [] roles = System.Web.Security.Roles.GetRolesForUser("ricardoperes");if (roles.Length == 0)

    {

      System.Web.Security.Roles.AddUsersToRole(new String [] { "ricardoperes" }, "Bloggers");

    }

    Profile Provider

    The Profile Provider is implemented in System.Web.Profile.SqlProfileProvider; the base class is System.Web.Profile.ProfileProvider. It's methods are:

    • DeleteInactiveProfiles
    • DeleteProfiles (overloaded)
    • FindInactiveProfilesByUserName
    • FindProfilesByUserName
    • GetAllInactiveProfiles
    • GetAllProfiles
    • GetNumberOfInactiveProfiles

    Both the Profile Provider and the system-wide properties must be configured on App.config. Note that you cannot use property groups, they don't work in non-ASP.NET applications:

    <profile enabled="true" automaticSaveEnabled="true" defaultProvider="SqlProfileProvider">

      <

    providers>    <add name="SqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="SomeConnectionStringName" />

      </

    providers>  <properties>     <add name="Birthday" type="System.DateTime" />

        <

    add name="Url" type="System.String" />

        <add name="Married" type="System.Boolean" defaultValue="false" />

        <add name="Collection" type="SomeNamespace.SomeCollection, SomeAssembly" />   </properties>

    </

    profile>

    And to use it:

    ProfileBase profile = System.Web.Profile.DefaultProfile.Create("ricardoperes", true);

     

    DateTime birthday = (DateTime) profile.GetPropertyValue("Birthday");profile.SetPropertyValue("Birthday", new DateTime(1975, 8, 19));

    profile.Save();

    Bookmark and Share

    Read more...

  • Blog Post Hijack

    Some guy at http : // www . ilovenet . com . ar has published some of my blog posts without quoting me, without a link to my blog and without even mentioning my name. I don't know about the other blog posts, but at least two of them were written by me. I can find no contact on the blog and the comments require approval.

    They say plagiarism is the sincerest form of flattery but I can only think of other words to describe this.

    Bookmark and Share

    Read more...

  • NHibernate Performance Optimization

    Today Fabio Maulo (of NHibernate fame) posted on NHibernate performance optimization. Unfortunately, he didn't include the source code or the DB creation scripts, but I hope he will do it. The post is, however, very interesting, and it certainly shows that NHibernate performance can dramatically change if one knows what to do. 

    Bookmark and Share

    Read more...

  • Using NHibernate Validator 1.0 with NHibernate 2.1

    If you want to use NHibernate Validator with the latest version of NHibernate and you are tired of waiting for the new version of NHibernate Validator which works with NHibernate 2.1 and you also don't want to recompile the whole thing, here's what to do: you must tell the CLR to redirect requests for the old version of NHibernate and Iesi.Collections to the new versions. Add these lines to your App.config or Web.config, inside the <configuration> section:

    <runtime>

      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

        <dependentAssembly>

          <assemblyIdentity name="Iesi.Collections" publicKeyToken="aa95f207798dfdb4"/>

          <bindingRedirect oldVersion="1.0.0.3" newVersion="1.0.1.0"/>

        </dependentAssembly>

        <dependentAssembly>

          <assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4"/>

          <bindingRedirect oldVersion="2.0.1.4000" newVersion="2.1.0.4000"/>

        </dependentAssembly>

      </assemblyBinding>

    </runtime>

    Bookmark and Share

    Read more...

  • .NET O/RM Performance Comparison

    With the launch of the ORMBattle.NET site, a new discussion started on the blogosphere; later on, this post by Gergely Orosz added more ashes to the fire. The subject seems to be, is it possible to blindly compare O/RM tools, disregarding all differences between them, in simple yet not plausible scenarios, such as loading/saving/updating N entities in a loop?

    Oren Eini wrote about it, and so did Davy Brion, both dismissing the way tests were conducted and the general usefulness of these kinds of (well, useless) tests. I tend to agree with both, but I don't know why the performance of these OR/M tools (which all implement the Unit of Work pattern), properly configured of course, can't be configured in simple but common scenarios, such as loading entities by id, loading an amount of entities at the same time, entity materialization, entity saving and updating, SQL generation quality, and so on. Of course, a more interesting test would be implementing a simple application with well known requirements with each technology, something like the PetShop application. Or, why don't we just forget about LINQ (NHibernate's implementation, at least, is not very mature), which seems to me just a trendy subject, and focus instead on things like:

    • Cache support
    • Available mapping types
    • Support for multiple tiers
    • Query language quality (or existence)
    • Possibility to pre-compile queries
    • Support for stored procedures
    • Memory and CPU consumption
    • Existence and quality of supporting tools (automatic entity generation, for example)
    • ...
    Bookmark and Share

    Read more...