I have read through all the related questions, but I still unable to get the right solution for some reason, something is not right on my side, but not sure what's causing it.
I have created a Custom Membership Provider, also changed my web.config to :
<membership defaultProvider="MyMemberShipProvider">
<providers>
<clear />
<add name="MyMemberShipProvider"
type="MyNameSpace.MyMemberShipProvider"
connectionStringName="ApplicationServices"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
applicationName="MyApplication" />
</providers>
</membership>
Here is the code for my Initialize method:
public override void Initialize(string name, NameValueCollection config)
{
if (config == null)
{ throw new ArgumentNullException("config"); }
if (string.IsNullOrEmpty(name))
{ name = "MyMemberShipProvider"; }
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "My Membership Provider");
}
base.Initialize(name, config);
_applicationName = GetConfigValue(config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
_maxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"));
_passwordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10"));
_minRequiredNonAlphaNumericCharacters = Convert.ToInt32(GetConfigValue(config["minRequiredAlphaNumericCharacters"], "1"));
_minRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7"));
_passwordStregthRegularExpression = Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], String.Empty));
_enablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "true"));
_enablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config["enablePasswordRetrieval"], "true"));
_requiredQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "false"));
_requiredUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "true"));
string temp_format = config["passwordFormat"];
if (temp_format == null)
{
temp_format = "Hashed";
}
switch (temp_format)
{
case "Hashed":
_passwordFormat = MembershipPasswordFormat.Hashed;
break;
case "Encrypted":
_passwordFormat = MembershipPasswordFormat.Encrypted;
break;
case "Clear":
_passwordFormat = MembershipPasswordFormat.Clear;
break;
default:
throw new ProviderException("Password format not supported.");
}
ConnectionStringSettings _connectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (_connectionStringSettings == null || _connectionStringSettings.ConnectionString.Length == 0)
{
throw new ProviderException("Connection String Cannot Be Blank.");
}
_connectionString = _connectionStringSettings.ConnectionString;
//Get Encryption and Decryption Key Information From the Information.
System.Configuration.Configuration cfg = WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
_machinekey = cfg.GetSection("system.web/machineKey") as MachineKeySection;
if (_machinekey.ValidationKey.Contains("AutoGenerate"))
{
if (PasswordFormat != MembershipPasswordFormat.Clear)
{
throw new ProviderException("Hashed or Encrypted passwords are not supported with auto-generated keys.");
}
}
}
And I have noticed that the Initialize method was not called, I read through the questions here and the people were saying I do not have to call that manually, if I have wired up my web.config correctly, I don't have to do anything, but I do tried to call that manually, but it gave me an InvalidCastException when I was trying to cast NameValueCollection.
Can anyone help me? Thanks
I am trying to work out what you have done.... I think you have proceeded as follows:
Within this event, you have tried to do something like this and wondering why Initialize() isn't called while stepping through your code:
MyNameSpace.MyMemberShipProvider msp = new MyNameSpace.MyMemberShipProvider();
bool IsAuthorised = msp.ValidateUser(txtLogin, txtPass);
Solution: - Use this instead:
I had a problem some time ago with this Initialize() method, I will post it here it may be helpful for someone.
Let's imagine you have the implementation of your custom provider on:
And what you want is use the method GetUserNameByEmail which is inside the provider implementation. There are two ways to call this method, through:
Which will not fire the Initialize method as you are calling it by yourself, on the other hand if your call is:
The Initialize method will be called if necessary, I assume this is on the base constructor or something (didn't dig more).
Hope this helps. - E.
For Initialize() to be called, you will need to instantiate your custom membership provider a certain way. Like so:
Now when you use myProvider, Initialize() from your custom provider will be called.
Custom Membership provider is initialized automatically and it is not intended to do so manually.
In my implementation, there is the Initialize metod like below:
Keep in mind, that the base.Initialize method is in ProviderBase class which has the following exceptions defined:
Exceptions:
System.ArgumentException: The name of the provider has a length of zero.
System.InvalidOperationException: An attempt is made to call System.Configuration.Provider.ProviderBase.Initialize(System.String,System.Collections.Specialized.NameValueCollection) on a provider after the provider has already been initialized.
Isn't the last exception the one you get?
Basically the flow goes like this,
Membership class (a static class) calls and uses MembershipProvider (an abstract class derived from ProviderBase) which SqlMembershipProvider implements (in your case MyMemberShipProvider), thus you gave the your implementation of the data accessing code to your data source in MyMemberShipProvider but you don't call the initialize yourself.
The Initialize() is virtual method on ProviderBase, when you create your MyMemberShipProvider you override it like below
Without see your code, when you say have an exception that has to do with NameValueCollection, it reminds me of this method above.
Hope this helps, Ray.
Here is the code to initialize a provider: