2009-03-08 12 views
19

He leído todas las preguntas relacionadas, pero aún no puedo obtener la solución correcta por alguna razón, algo no está bien de mi parte, pero no estoy seguro de qué lo está causando.¿Cómo puedo llamar a Initialize en un MembershipProvider personalizado?

He creado un proveedor personalizado, también cambió mi web.config para:

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

Aquí es el código de mi método 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."); 
     } 
    } 

} 

Y me he dado cuenta de que la inicialización método no fue llamado, leí las preguntas aquí y la gente decía que no tenía que llamarlo manualmente, si conecté correctamente mi web.config, no tengo que hacer nada, pero sí intenté llamarlo manualmente, pero me dio una InvalidCastException cuando estaba intentando g para lanzar NameValueCollection.

¿Alguien me puede ayudar? Gracias

Respuesta

3

Es cierto que su método Initialize debe llamarse automáticamente siempre que su proveedor esté configurado correctamente (como parece estar en su muestra de código).

Tendrá que aclarar cómo lo 'llamó manualmente', y dónde intentó lanzar NameValueCollection. ¿Ocurrió dentro de Initialize?

Tal vez las que debe mostrar su método de inicialización (que no olvida la palabra clave override, ¿verdad ;-)

Editar:? Pues bien, el método Initialize parece muy bien también.

Tenga en cuenta: Membership es una clase estática, y carga e inicializa los proveedores configurados de manera perezosa. Por lo tanto, la construcción de su proveedor y la llamada a su método Initialize no se realizarán hasta que se realice una llamada a la propiedad Membership.Provider o Membership.Providers. La mayoría de los otros métodos estáticos (como GetUser()) harán esto, pero la conclusión es que no se invocará su método Initialize hasta que realmente se use la API de membresía.

¿Ha hecho esto, explícitamente o mediante el uso de un control de inicio de sesión u otros?

+0

Ya he puesto el código Initialize en mi pregunta, y tengo la palabra clave override activada, y no se activa, no estoy seguro de por qué. – PlayKid

+0

Tiene razón, es estático, no es un singleton en este caso, voy a editar mi publicación. ¡Gracias! –

1

Básicamente el flujo dice así,

clase de miembros (una clase estática) llamadas y utiliza MembershipProvider (una clase abstracta derivada de ProviderBase) que implementa SqlMembershipProvider (en su caso MyMemberShipProvider), lo que le dio la implementación del código de acceso a datos a su fuente de datos en MyMemberShipProvider pero no llama a la inicialización usted mismo.

El Initialize() es un método virtual en ProviderBase, al crear su MyMemberShipProvider que lo sustituya, como a continuación

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

Sin ver su código, cuando usted dice tiene una excepción que tiene que ver con NameValueCollection, se me recuerda este método anterior.

Espero que esto ayude, Ray.

+0

He incluido mi código en mi pregunta, es similar al tuyo, pero el problema es que nunca se dispara. – PlayKid

+0

En realidad, la membresía no es un singleton, es estático. –

+0

Tiene razón, es estático, no es un singleton en este caso, voy a editar mi publicación. ¡Gracias! –

0

El proveedor de membresía personalizado se inicializa automáticamente y no está destinado a hacerlo manualmente.

En mi aplicación, existe la inicialización metód, como a continuación:

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


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

Tenga en cuenta, que el método base.Initialize está en la clase ProviderBase que tiene las siguientes excepciones definidas:

excepciones:

  • System.ArgumentNullException: El nombre del proveedor es nulo.
  • System.ArgumentException: El nombre del proveedor tiene una longitud de cero.

  • System.InvalidOperationException: Se hace un intento para llamar System.Configuration.Provider.ProviderBase.Initialize (System.String, System.Collections.Specialized.NameValueCollection) en un proveedor después de que el proveedor ya ha sido inicializado .

¿No es la última excepción la que obtienes?

+0

No, el problema es que Initialize no se inició, entonces lo que hice es poner un método como MyMembershipProvider() público y funciona, pero no creo que sea la manera correcta de hacerlo. – PlayKid

+0

asegurarse, que tienen lo siguiente en su web.config: twk

+0

Asegúrese, que tienen el atributo 'tipo' consta de 2 partes: type = "MyNameSpace.MyMemberShipProvider, MyNamespace" donde "MyNameSpace" es el nombre dll de su clase de proveedor. – twk

2

estoy tratando de averiguar lo que ha hecho .... creo que haya procedido de la siguiente manera:

  • creado una clase personalizada llamada MyMembershipProvider heredando de MembershipProvider
  • web.config Configurado (parece correcto para mí)
  • crea un control web que desencadena un evento para hacer algo (por ejemplo, para autenticar a un inicio de sesión) Entonces ...
  • en este caso, se ha tratado de hacer algo como esto y wond por qué no se invoca Initialize() al recorrer su código:

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

Solución: - Use este lugar:

bool IsAuthorised = Membership.ValidateUser(txtLogin, txtPass); 
  • no se crea una instancia de la clase por sí mismo, en lugar vamos .NET hacer esto para usted mediante la clase estática membresía , lo que garantiza que solo existe una instancia de MyMemberShipProvider a lo largo de la vida de la aplicación. Si instancia su propia clase y llama a Initialize(), su código no será seguro para subprocesos.
46

Para llamar a Initialize(), tendrá que crear una instancia de su proveedor de membresía personalizado de cierta manera. De esta manera:

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

Ahora, cuando use myProvider, se llamará Initialize() desde su proveedor personalizado.

+3

+1 Gracias. Para aquellos que desean acceder a la membresía desde un proyecto externo, la membresía pertenece a System.Web.Security y requiere System.Web.dll. – CRice

+0

Y para mayor claridad, "NameOfMembershipProviderInConfig" tiene que coincidir exactamente con la propiedad "name" de su entrada de archivo de configuración MembershipProvider. Había puesto accidentalmente el valor de la propiedad "type" y no-go. –

0

esto obliga a la inicialización de ser llamado

private readonly Provider _provider; 

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

Aquí está el código para inicializar un proveedor:

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

que tenía un problema hace algún tiempo con este método Initialize(), lo haré publicarlo aquí puede ser útil para alguien.

Imaginemos que tiene la implementación de su proveedor personalizado en:

MyEnterprise.MyArea.MyProviders.CustomProvider 

Y lo que desea es utilizar el método GetUserNameByEmail que está dentro de la implementación del proveedor. Hay dos formas de llamar a este método, a través de:

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

cual no se disparará el método de inicialización como la que está llamando por su cuenta, por otro lado, si la llamada es:

Membership.GetUserNameByEmail(email) 

El Se llamará al método Initialize si es necesario, supongo que está en el constructor base o algo así (no cavó más).

Espero que esto ayude. - E.

Cuestiones relacionadas