2009-03-08 11 views
19

Przeczytałem wszystkie powiązane pytania, ale nadal nie mogę uzyskać odpowiedniego rozwiązania z jakiegoś powodu, coś jest nie w porządku po mojej stronie, ale nie jestem pewien, co jest przyczyną.Jak wywołać Initialize na niestandardowym MembershipProvider?

Stworzyłem niestandardowe Membership Provider, zmienił też moje web.config do:

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

Oto kod mojego metody 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."); 
     } 
    } 

} 

i zauważyłem, że Initialize metoda nie została wywołana, przeczytałem tutaj pytania i ludzie mówili, że nie muszę tego ręcznie wywoływać, jeśli poprawnie podłączyłem mój web.config, nie muszę nic robić, ale starałem się wywołaj to ręcznie, ale dało mi to wyjątek InvalidCastException, gdy próbowałem g, aby rzucić NameValueCollection.

Czy ktoś może mi pomóc? Dzięki

Odpowiedz

3

To prawda, że ​​twoja metoda Initialize powinna być wywoływana automatycznie, o ile twój dostawca jest skonfigurowany poprawnie (jak się wydaje, znajduje się w twoim przykładzie kodu).

Musisz wyjaśnić, w jaki sposób "nazwałeś to ręcznie" i gdzie próbowałeś rzucić NameValueCollection. Czy to się stało w Initialize?

Może powinieneś pokazać nam swoją metodę Initialize (ty nie zapomniał słowa kluczowego override, prawda ;-)

Edit: Cóż, metoda Initialize wydaje się zbyt dobrze.

Należy pamiętać: Membership to klasa statyczna, która ładuje i inicjuje skonfigurowanych dostawców w leniwy sposób. Tak więc budowa twojego dostawcy i wywołanie jego metody Initialize nie nastąpi, dopóki nie zostanie wykonane wywołanie do właściwości Membership.Provider lub Membership.Providers. Większość innych statycznych metod (takich jak GetUser()) zrobi to, ale konkluzja jest taka, że ​​twoja metoda Initialize nie zostanie wywołana, dopóki API Membership nie zostanie faktycznie użyty.

Czy zrobiłeś to jednoznacznie lub używając formantu Login lub podobnego?

+0

Umieściłem już kod Initialize na moim pytaniu, a mam już słowo kluczowe "override" i nie uruchamia się, nie wiem dlaczego. – PlayKid

+0

Masz rację, to jest statyczne, a nie singleton w tym przypadku, będę edytować mój post. Dzięki! –

1

Zasadniczo przepływ idzie tak,

klasy członków (klasa statyczna) połączeń i używa MembershipProvider (klasa abstrakcyjna pochodzi od ProviderBase), który SqlMembershipProvider narzędzia (w przypadku MyMemberShipProvider), co dałeś implementację kodu dostępu do danych do źródła danych w MyMemberShipProvider, ale nie wywołujesz samodzielnie inicjalizacji.

Initialize() jest wirtualna metoda na ProviderBase, podczas tworzenia MyMemberShipProvider zastąpić go jak poniżej

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

Bez zobaczyć swój kod, gdy mówisz mieć wyjątek, który ma do czynienia z NameValueCollection, to przypomina mi tę metodę powyżej.

Mam nadzieję, że to pomoże, Promień.

+0

Zawarłem mój kod na moje pytanie, jest podobny do twojego, ale problem polega na tym, że nigdy się nie strzela. – PlayKid

+0

W rzeczywistości członkostwo nie jest pojedyncze - jest statyczne. –

+0

Masz rację, to jest statyczne, a nie singleton w tym przypadku, będę edytować mój post. Dzięki! –

0

Niestandardowy dostawca członkostwa jest inicjowany automatycznie i nie jest przeznaczony do tego ręcznie.

W mojej realizacji, nie jest Inicjowanie Metod jak poniżej:

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


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

Należy pamiętać, że metoda base.Initialize jest w klasie ProviderBase która ma zdefiniowane następujące wyjątki:

wyjątkami:

  • System.ArgumentNullException: Nazwa dostawcy jest zerowa.
  • System.ArgumentException: Nazwa dostawcy ma długość zero.

  • System.InvalidOperationException: Podjęto próbę zadzwonić System.Configuration.Provider.ProviderBase.Initialize (system.string, System.Collections.Specialized.NameValueCollection) na operatora po usługodawca już zainicjowany .

Czy to nie ostatni wyjątek?

+0

Nie, problem polega na tym, że Initialize nie uruchomił się, więc zrobiłem metodę jako publiczną MyMembershipProvider() i działa, ale nie sądzę, że jest to właściwy sposób. – PlayKid

+0

Upewnij się, że masz następujące w Twojej web.config: twk

+0

Upewnij się, że masz atrybut 'typ' zawiera 2 części: type = "MyNameSpace.MyMemberShipProvider, MyNamespace" gdzie "MyNameSpace" jest nazwą biblioteki dll twojej klasy dostawcy. – twk

2

staram się zorientować, co masz zrobić .... Myślę, że masz przebiegała następująco:

  • Utworzono niestandardowej klasy o nazwie MyMembershipProvider przez dziedziczenie z MembershipProvider
  • skonfigurowano web.config (wygląda poprawna do mnie)
  • Utworzony web Control, który uruchamia zdarzenie coś zrobić (np uwierzytelnić login) potem ...
  • W tym przypadku, próbowałeś zrobić coś takiego i wond ering Dlaczego funkcja Initialize() nie jest wywoływana podczas przechodzenia przez twój kod:

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

Rozwiązanie: - Użyj tego zamiast:

bool IsAuthorised = Membership.ValidateUser(txtLogin, txtPass); 
  • Nie tworzy instancję klasy przez siebie, zamiast pozwolić .NET to zrobić dla Ciebie za pomocą członkostwa klasę statyczną , co zapewnia, że ​​tylko jedna instancja MyMemberShipProvider istnieje przez cały okres istnienia aplikacji. Jeśli utworzysz własną klasę i wywołasz Initialize(), twój kod nie będzie bezpieczny dla wątków.
46

Aby wywołać funkcję Initialize(), należy utworzyć instancję niestandardowego dostawcy członkostwa w określony sposób. Tak jak poniżej:

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

Teraz, gdy używasz myProvider, wywoływana jest funkcja Initialize() od Twojego dostawcy.

+3

+1 Dzięki. Dla tych, którzy chcą uzyskać dostęp do członkostwa z zewnętrznego projektu, członkostwo należy do System.Web.Security i wymaga System.Web.dll. – CRice

+0

I tylko dla większej przejrzystości, "NameOfMembershipProviderInConfig" musi dokładnie pasować do właściwości "name" wpisu pliku konfiguracyjnego MembershipProvider. Przypadkowo ustawiłem wartość właściwości "typ" i nie używam. –

0

ten wymusza initialize nazywać

private readonly Provider _provider; 

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

Oto kod zainicjować Provider:

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

miałem problem jakiś czas temu z tej metody initialize(), będę opublikuj tutaj, może to być pomocne dla kogoś.

Wyobraźmy sobie masz realizację dostawcy zlecenie w:

MyEnterprise.MyArea.MyProviders.CustomProvider 

i co chcesz to użyć metody GetUserNameByEmail który jest wewnątrz realizacji operatora. Istnieją dwa sposoby, aby wywołać tę metodę, dzięki:

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

Które nie będzie ogień metodę Initialize jak dzwonisz go przez siebie, z drugiej strony, jeśli połączenie jest:

Membership.GetUserNameByEmail(email) 

Inicjowana metoda zostanie wywołana w razie potrzeby, zakładam, że jest to na konstruktorze podstawowym lub czymś (nie wykopałem więcej).

Mam nadzieję, że to pomoże. - E.

Powiązane problemy