如何在自定义MembershipProvider上调用Initialize?

时间:2009-03-08 13:08:09

标签: model-view-controller asp.net-membership web-config

我已经阅读了所有相关的问题,但由于某种原因我仍然无法得到正确的解决方案,有些事情不适合我,但不确定是什么导致了它。

我创建了一个自定义成员资格提供程序,也将我的web.config更改为:

   <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>

以下是我的Initialize方法的代码:

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.");
        }
    }

}

我注意到没有调用Initialize方法,我在这里阅读了问题并且人们说我不必手动调用,如果我正确连接了我的web.config,我没有必须做任何事情,但我确实试图手动调用它,但是当我试图转换NameValueCollection时它给了我一个InvalidCastException。

任何人都可以帮助我吗?感谢

8 个答案:

答案 0 :(得分:46)

要调用Initialize(),您需要以某种方式实例化自定义成员资格提供程序。像这样:

MyCustomMembershipProvider myProvider = (MyCustomMembershipProvider)Membership.Providers["NameOfMembershipProviderInConfig"];

现在,当您使用myProvider时,将调用自定义提供程序中的Initialize()。

答案 1 :(得分:3)

只要您的提供程序配置正确(因为它似乎在您的代码示例中),就应该自动调用Initialize方法。

您需要澄清“手动调用它”的方式,以及尝试转换NameValueCollection的位置。它是在Initialize内发生的吗?

也许您应该向我们展示您的Initialize方法(您没有忘记override关键字,是吗?; - )

编辑:嗯,Initialize方法似乎也很好。

请记住:Membership是一个静态类,它以惰性方式加载和初始化已配置的提供程序。因此,在调用InitializeMembership.Provider属性之前,不会发生提供程序的构造以及对其Membership.Providers方法的调用。大多数其他静态方法(例如GetUser())都会这样做,但结论是在实际使用Membership API之前不会调用Initialize方法。

您是否已明确或使用Login控件等完成此操作?

答案 2 :(得分:2)

我想弄清楚你做了什么......我认为你已经按照以下步骤进行:

  • 通过继承MembershipProvider
  • 创建名为MyMembershipProvider的自定义类
  • 配置web.config(看起来对我来说)
  • 创建了一个Web控件,用于触发事件以执行某些操作(例如,对登录进行身份验证) 然后...
  • 在这个事件中,你试图做这样的事情并想知道为什么在单步执行代码时没有调用Initialize():

    MyNameSpace.MyMemberShipProvider msp = new MyNameSpace.MyMemberShipProvider();
    bool IsAuthorised = msp.ValidateUser(txtLogin,txtPass);

解决方案: - 改用它:

bool IsAuthorised = Membership.ValidateUser(txtLogin, txtPass);
  • 不要自己创建类的实例,而是让.NET通过使用Membership静态类为您执行此操作,这样可确保在应用程序的整个生命周期中只存在一个MyMemberShipProvider实例。如果您实例化自己的类并调用Initialize(),则代码将不是线程安全的。

答案 3 :(得分:1)

基本上流程就是这样,

成员资格类(静态类)调用并使用SqlMembershipProvider实现的MembershipProvider(派生自ProviderBase的抽象类)(在您的情况下为MyMemberShipProvider),因此您将数据访问代码的实现提供给MyMemberShipProvider中的数据源但是你不要自己打电话给初始化。

Initialize()是ProviderBase上的虚方法,当你创建MyMemberShipProvider时,你会覆盖它,如下所示

class MyMemberShipProvider : MembershipProvider
{
    private string _connectionStringName;

    public override void Initialize(string name, NameValueCollection config)
    {
       // see the config parameter passed in is of type NameValueCollection 
       // it gives you the chance to get the properties in your web.config
       // for example, one of the properties is connectionStringName

        if (config["connectionStringName"] == null)
        {
            config["connectionStringName"] = "ApplicationServices";
        }
        _connectionStringName = config["connectionStringName"];
        config.Remove("connectionStringName");          
    }
}

如果没有看到你的代码,当你说有一个与NameValueCollection有关的异常时,它会让我想起上面的这个方法。

希望这有帮助, 射线。

答案 4 :(得分:1)

前一段时间我用这个Initialize()方法遇到了问题,我会在这里发布它可能对某人有帮助。

让我们假设您已经实现了自定义提供程序:

MyEnterprise.MyArea.MyProviders.CustomProvider

您想要的是使用提供程序实现中的方法GetUserNameByEmail。有两种方法可以通过以下方式调用此方法:

MyEnterprise.MyArea.MyProviders.CustomProvider.GetUserNameByEmail(email)

如果您的电话是:

,那么您自己调用的方法不会触发Initialize方法。
Membership.GetUserNameByEmail(email)

如果需要,将调用Initialize方法,我假设这是在基础构造函数或其他东西上(没有挖掘更多)。

希望这会有所帮助。 - E.

答案 5 :(得分:0)

自定义成员资格提供程序会自动初始化,而不是手动初始化。

在我的实现中,有如下的Initialize metod:

public override void Initialize(string name, NameValueCollection config)
{
    if (config == null)
        throw new ArgumentNullException("config");


    // Initialize the abstract base class.
    base.Initialize(name, config);
}

请记住,base.Initialize方法位于ProviderBase类中,该类定义了以下异常:

例外:

  • System.ArgumentNullException:     提供程序的名称为null。
  • System.ArgumentException:     提供者的名称长度为零。

  • System.InvalidOperationException:      尝试调用System.Configuration.Provider.ProviderBase.Initialize(System.String,System.Collections.Specialized.NameValueCollection) 提供商之后的提供商 已经初始化。

你得到的那个不是最后一个例外吗?

答案 6 :(得分:0)

这会强制调用初始化

private readonly Provider _provider;

public AccountMembershipService(Provider provider)
{
   _provider = provider ?? (Provider) Membership.Provider;
}

答案 7 :(得分:0)

以下是初始化提供商的代码:

                System.Collections.Specialized.NameValueCollection adProviderConfig;
                adProviderConfig = membershipSection.Providers[adProviderName].Parameters;
                var _ADProvider = new ActiveDirectoryMembershipProvider();
                _ADProvider.Initialize(adProviderName, adProviderConfig);