Jamie Kiefner
November 20, 2014

Managing ASP.Net Authentication From a Console Application

Jamie Kiefner

Many developers are familiar with the ASP.Net Web Configuration Manager in Visual Studio to maintain or create users in their SQL databases. The application allows the creation of users, as well as role creation and assignment. However, to my surprise, this functionality is no longer available in Visual Studio 2013. This was due to the removal of the Cassini web server in place of IIS Express. There is a workaround if you still like using the tool (as I do). The information can be found in this MSDN blog post.

Recently, I needed to move a small number of users from an older application to a new MVC 4 application using forms authentication. With the previously mentioned issues concerning the web configuration tool, I decided to build a console application to import the users automatically. This would also allow me to repeat the process for any interim users that would be created prior to launch.

Another small caveat to the import was that I was also going to be utilizing profiles for extended information. As I discovered, information is a bit sparse concerning profile usage outside of an ASP.Net application. After a fair amount of trial and error along with the odd exception here and there, I got it to work as expected with a very small amount of code.

The Code

As with an ASP.Net application, you need several elements in the app.config file. Basically the same as would be in your web.config for an ASP.Net application. In my case, I added the SQL membership, rolemanager, and profile providers in order to create the profile and attach additional user related fields.

<connectionStrings> <add name="MyConnectionString" connectionString="Data Source=MySqlServer;Initial Catalog=MyDB
   &lt;/connectionStrings>
 

Then in a “system.web” section add the following:

<membership defaultProvider="AspNetSqlMembershipProviderEncrypted"> <providers> <clear /> <add name="AspNetSqlMembershipProviderEncrypted" type="System.Web.Security.SqlMembershipProvider" connectionStringName=" MyConnectionString " enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Encrypted" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="3" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" /> </providers> </membership> <profile defaultProvider="AspNetSqlProfileProvider"> <providers> <clear /> <add name="AspNetSqlProfileProvider" connectionStringName=" MyConnectionString " applicationName="/" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> </providers> <properties> <add name="userHomePhone" type="string" /> </properties> </profile> <roleManager enabled="true"> <providers> <clear /> <add connectionStringName=" MyConnectionString " applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> </providers> </roleManager>
 

In order to use the role provider and profile provider, we need to instantiate them. In a standard ASP.Net application, these objects are instantiated behind the scenes so we need to bring them up ourselves. I did this with simple static methods and a couple of properties outlined in my app.config.

Roleprovider:

public static SqlRoleProvider GetRoleProvider()
        {
            var prov = new SqlRoleProvider();
            var coll = new NameValueCollection
            {
                {"connectionStringName", "PEFAppsConnectionString"},
                {"applicationName", "/"}
            };
            prov.Initialize("AspNetSqlRoleProvider", coll);
            return prov;
        }

Profileprovider:

public static SqlProfileProvider GetProfileProvider()
        {
            var prov = new SqlProfileProvider();
            var coll = new NameValueCollection
            {
                {"connectionStringName", "PEFAppsConnectionString"},
                {"applicationName", "/"}
            };
            prov.Initialize("AspNetSqlProfileProvider", coll);
            return prov;
        }

The Membership object is instantiated normally utilizing the fields from the app.config without any static methods. You will need to add references to System.Web and System.Security.

To access the member data from SQL, you use the normal routines. For example, to get user information:

var user = Membership.GetUser("userName");

In order to get role information, we use one of our static methods to retrieve a role provider:

var rp = GetRoleProvider();
var rpRole = rp.IsUserInRole(“userName, "roleName");

To retrieve profile information, we use ProfileBase.Create(“username”). This does seem a bit odd, since we aren’t actually, creating a new profile. The method name (“Create”) is a bit misleading since you are not actually creating a profile, but a connection to it. You can then set your property values:

pr.SetPropertyValue("userPhoneNumber", “username”);
pr.Save();

I utilized standard EF 6 functionality to import users from the old database. I then simply looped through them and created members, roles and profiles using the above methods. One other small piece I added that was helpful was a simple static method to create a role if it wasn’t already present. I then passed the role provider and role name to my CreateNewRole method:

public static void CreateNewRole(SqlRoleProvider roleProvider, string roleName)
        {
            var newRole =
           roleProvider.GetAllRoles().FirstOrDefault(x => x.Contains(roleName));
            if (newRole == null)
            {
                roleProvider.CreateRole(roleName);
            }
        }

In summation, it is very easy to move large numbers of users from an existing, non-ASP. Net authentication database to a new ASP. Net Forms Authentication database with a console application. This method takes a fraction of the time when compared with a simple MVC web site or the ASP.Net configuration manager to perform the operation.

8 Comments

  1. 8 brainStorm 25 Nov
    Yea, I guess it is easy to move large numbers of users from an existing non-ASP.NET authentication database with a console application. However, in terms of speed, how does this method compare with a simple MVC website to perform the operation?
  2. 7 AJ 28 Nov
    Great Post, Dad! I look forward to implementing role providers in mvc applications later down the road.
  3. 6 Donald Bickel 03 Dec
    I remember Jamie putting this together in a VERY short time frame - like between conversations on the topic at his desk.  I'd say it probably took a little less time than a simple MVC app would have, especially when you include deployment time but I'll admit it's probably a little less accessible to other devs.
  4. 5 Rockie 25 Sep
    What is PEFAppsConnectionString in Your case?
  5. 4 Jamie Kiefner 28 Sep
    "PEFAppsConnectionString" happens to be the name I gave to the real connection string in this project. In the example i replaced it with "MyConnectionString" I just missed renaming it in the example.
  6. 3 Rockie 01 Oct
    Thank You Jamie! Imho You found great workaround! :)
  7. 2 R.L. Parker 08 Dec
    I'm implementing a similar task (migrating some user attributes that were stored in asp.net membership profile in a legacy app into a custom sql table in a new app). It was the fact that I had to manually initialize the Profile provider that I was missing. Thanks for the tip!
  8. 1 Jamie Kiefner 08 Dec
    You are very welcome, glad you found the post helpful!

Comment

  1. RadEditor - HTML WYSIWYG Editor. MS Word-like content editing experience thanks to a rich set of formatting tools, dropdowns, dialogs, system modules and built-in spell-check.
    RadEditor's components - toolbar, content area, modes and modules
       
    Toolbar's wrapper 
     
    Content area wrapper
    RadEditor's bottom area: Design, Html and Preview modes, Statistics module and resize handle.
    It contains RadEditor's Modes/views (HTML, Design and Preview), Statistics and Resizer
    Editor Mode buttonsStatistics moduleEditor resizer
      
    RadEditor's Modules - special tools used to provide extra information such as Tag Inspector, Real Time HTML Viewer, Tag Properties and other.
       

Subscribe to Our Blog

Get the latest blog posts sent right to your inbox so you never miss an informative post from Mercury.

 

Get Your Share On!

 

Tags