Как мне вызвать Initialize для пользовательского MembershipProvider? - PullRequest
19 голосов
/ 08 марта 2009

Я прочитал все связанные с этим вопросы, но я все еще не могу найти правильное решение по какой-то причине, что-то не в порядке с моей стороны, но не уверен, что его вызывает.

Я создал провайдера нестандартного членства, также изменил свой 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, я не Я должен был что-то сделать, но я пытался вызвать это вручную, но это дало мне InvalidCastException, когда я пытался привести NameValueCollection.

Кто-нибудь может мне помочь? Спасибо

Ответы [ 8 ]

46 голосов
/ 21 октября 2009

Для вызова Initialize () вам нужно будет определенным образом создать своего провайдера пользовательского членства. Вот так:

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

Теперь, когда вы используете myProvider, будет вызываться Initialize () из вашего пользовательского провайдера.

3 голосов
/ 08 марта 2009

Это правда, ваш метод Initialize должен вызываться автоматически, если ваш провайдер настроен правильно (как, кажется, в вашем примере кода).

Вам нужно будет уточнить, как вы «вызывали его вручную» и где вы пытались привести NameValueCollection. Это случилось внутри Initialize?

Возможно, вам следует показать нам ваш метод Initialize (вы не забыли ключевое слово override, не так ли?; -)

Редактировать: Что ж, метод Initialize тоже выглядит хорошо.

Имейте в виду: Membership - это статический класс, который загружает и инициализирует настроенных провайдеров ленивым образом. Поэтому создание вашего провайдера и вызов его метода Initialize не будут происходить, пока не будет выполнен вызов либо свойства Membership.Provider, либо свойства Membership.Providers. Большинство других статических методов (таких как GetUser()) будут делать это, но вывод заключается в том, что ваш метод Initialize не будет вызываться до тех пор, пока API-членство не будет фактически использовано.

Делали ли вы это явно или с помощью элемента управления Login или подобного?

2 голосов
/ 30 мая 2009

Я пытаюсь понять, что вы сделали .... Я думаю, вы поступили следующим образом:

  • Создал пользовательский класс MyMembershipProvider, унаследованный от MembershipProvider
  • Настроил web.config (выглядит мне правильно)
  • Создан веб-элемент управления, который запускает событие, чтобы что-то сделать (например, для аутентификации входа в систему) Тогда ...
  • В рамках этого события вы пытались сделать что-то подобное и удивляетесь, почему Initialize () не вызывается при пошаговом выполнении кода:

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

Решение: - Используйте это вместо:

bool IsAuthorised = Membership.ValidateUser(txtLogin, txtPass);
  • Не создавайте экземпляр своего класса самостоятельно, вместо этого позвольте .NET сделать это за вас, используя статический класс Membership, который гарантирует, что только один экземпляр MyMemberShipProvider существует в течение всего времени жизни приложения. Если вы создадите свой собственный класс и вызовете Initialize (), ваш код не будет потокобезопасным.
1 голос
/ 21 февраля 2014

У меня была проблема с этим методом Initialize (), я опубликую его здесь, это может быть полезно для кого-то.

Представим, что у вас есть реализация вашего собственного провайдера:

MyEnterprise.MyArea.MyProviders.CustomProvider

И вам нужно использовать метод GetUserNameByEmail, который находится внутри реализации провайдера. Есть два способа вызвать этот метод:

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

, который не будет вызывать метод Initialize, поскольку вы вызываете его самостоятельно, с другой стороны, если ваш вызов:

Membership.GetUserNameByEmail(email)

При необходимости будет вызван метод Initialize, я предполагаю, что он находится в базовом конструкторе или что-то еще (не копал больше).

Надеюсь, это поможет. - E.

1 голос
/ 08 марта 2009

В основном поток идет так,

Класс членства (статический класс) вызывает и использует MembershipProvider (абстрактный класс, производный от ProviderBase), который реализует SqlMembershipProvider (в вашем случае 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, это напоминает мне об этом методе выше.

Надеюсь, это поможет, Ray.

0 голосов
/ 01 января 2014

Вот код для инициализации провайдера:

                System.Collections.Specialized.NameValueCollection adProviderConfig;
                adProviderConfig = membershipSection.Providers[adProviderName].Parameters;
                var _ADProvider = new ActiveDirectoryMembershipProvider();
                _ADProvider.Initialize(adProviderName, adProviderConfig);
0 голосов
/ 07 марта 2013

это заставляет инициализацию называться

private readonly Provider _provider;

public AccountMembershipService(Provider provider)
{
   _provider = provider ?? (Provider) Membership.Provider;
}
0 голосов
/ 08 марта 2009

Пользовательский поставщик членства инициализируется автоматически и не предназначен для этого вручную.

В моей реализации есть метод Initialize, как показано ниже:

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: Название провайдера пусто.
  • System.ArgumentException: Длина имени провайдера равна нулю.

  • System.InvalidOperationException: Предпринята попытка вызвать System.Configuration.Provider.ProviderBase.Initialize (System.String, System.Collections.Specialized.NameValueCollection). на поставщика после того, как поставщик имеет уже инициализирован.

Разве это не последнее исключение, которое вы получаете?

...