views:

558

answers:

2

We're using ASP.Net membership providers (the SQL Server provider), and I want to be able to set up an Admin user account as part of our installer. To do this, I need the ASP.Net membership provider configured so that my installer can use it - but I don't want to have to set up a config file for the installer.

So is there a way of configuring an ASP.Net membership through code without writing a custom provider?

A: 

Membership.ApplicationName = "yourfbaApplicationame"; MembershipUser user = Membership.CreateUser("admin,"password","[email protected]");

and Make sure that you have the following entries in the config file.

 <connectionStrings>
<add connectionString="server=sqd01-1-cll;database=FBA;Integrated Security=SSPI;"  name="FBASqlConnString" providerName="System.Data.SqlClient"/>

If you still wanted to use the complete code and dont need to use the config file. Use the below

SqlMembershipProvider ObjSqlMembershipProvider = new SqlMembershipProvider();
            SqlRoleProvider ObjSqlRoleProvider = new SqlRoleProvider();
            NameValueCollection ObjNameValueCollRole = new NameValueCollection();
            NameValueCollection ObjNameValueCollMembership = new NameValueCollection();
            MembershipCreateStatus enMembershipCreateStatus;

                ObjNameValueCollMembership.Add("connectionStringName", "Connection String Name");
                ObjNameValueCollMembership.Add("applicationName", "ApplicatioNAme");

                //these items are assumed to be Default and dont care..Should be given a look later stage.
                ObjNameValueCollMembership.Add("enablePasswordRetrieval", "false");
                ObjNameValueCollMembership.Add("enablePasswordReset", "false");
                ObjNameValueCollMembership.Add("requiresQuestionAndAnswer", "false");
                ObjNameValueCollMembership.Add("requiresUniqueEmail", "false");
                ObjNameValueCollMembership.Add("passwordFormat", "Hashed");
                ObjNameValueCollMembership.Add("maxInvalidPasswordAttempts", "5");
                ObjNameValueCollMembership.Add("minRequiredPasswordLength", "1");
                ObjNameValueCollMembership.Add("minRequiredNonalphanumericCharacters", "0");
                ObjNameValueCollMembership.Add("passwordAttemptWindow", "10");
                ObjNameValueCollMembership.Add("passwordStrengthRegularExpression", "");

                //hard coded the Provider Name,This fuction just need one that is present. I tried other names and it throws error. I found this using Reflector ..all the rest are take care by the above
                //name value pairs
                ObjSqlMembershipProvider.Initialize("AspNetSqlMembershipProvider", ObjNameValueCollMembership);MembershipUser user = ObjSqlMembershipProvider.CreateUser("admin,"password","[email protected]");

One this You need to give the connection string in the Config file no other go. If you want that too to be from the code you need to inherit the class

Kusek
He was looking for a way to specify the connection string via code..
cbeuker
+1  A: 

Ok, following the solution they conjured up here: http://forums.asp.net/p/997608/2209437.aspx

I created a class which, in the parameterless constructor (which you need) just gets the server and port from the command line arguments. Such that I can go "MembershipInitializer.exe "SomeSqlServer\Instance" 51000.

public class CustomSQLMembershipProvider : SqlMembershipProvider {
  private readonly string _server;
  private readonly string _port;

  /// <summary>
  /// Initializes a new instance of the <see cref="T:System.Web.Security.SqlMembershipProvider"/> class.
  /// </summary>
  public CustomSQLMembershipProvider() {
    string[] args = System.Environment.GetCommandLineArgs();
    // args[0] is the exe name
    _server = args[1];
    _port = args[2];
  }

  public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
  {
    base.Initialize(name, config);

    // Update the private connection string field in the base class.
    string connectionString = string.Format(@"Data Source={0},{1};Initial Catalog=aspnetdb;UID=NICCAMembership;PWD=_Password1;Application Name=NICCA;Connect Timeout=120;", _server, _port);

    // Set private property of Membership provider.
    FieldInfo connectionStringField = GetType().BaseType.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic);
    connectionStringField.SetValue(this, connectionString);
  }
}

In the app.config of your console app (or windows app)

<configuration>
 <connectionStrings>
  <clear/>
  <add name="MembershipDB"
    connectionString="Some Bogus String here that gets overrided in the custom class" 
    providerName="System.Data.SqlClient"/>
 </connectionStrings>
 <system.web>
  <authentication mode="Forms"/>
  <authorization>
   <deny users="?"/>
  </authorization>
  <membership>
   <providers>
    <remove name="AspNetSqlMembershipProvider"/>
    <add name="AspNetSqlMembershipProvider" 
      connectionStringName="MembershipDB" 
      applicationName="NICCA" 
      type="MyInitializeMembershipDB.CustomSQLMembershipProvider, MyInitializeMembershipDB" 
      requiresUniqueEmail="false" 
      requiresQuestionAndAnswer="false"/>
   </providers>
  </membership>
 </system.web>
</configuration>

If you are in need of the role provider bit as well, you probably have to override SqlRoleProvider in much the same way.

If you are creating a program to automatically initialize your membership database to a specific state based but the sql server address and port name aren't known until someone enters them into a install wizard, this will do the trick..

Does this help?

cbeuker
That's pretty much what I arrived at in the end. It's a shame that we're forced to use reflection to set private members in order to get this to work :-(.
Samuel Jack