2009-05-07 19 views
6

Intenté mucho implementar un proveedor de perfil personalizado en ASP.NET MVC. He leído muchos tutoriales, pero no puedo encontrar mi problema. Es bastante similar al Implementing Profile Provider in ASP.NET MVC.Implementación de proveedor de perfil personalizado en ASP.NET MVC

Pero me gustaría crear mi propio proveedor de perfil, así que escribí la siguiente clase que hereda de ProfileProvider:

public class UserProfileProvider : ProfileProvider 
{ 
    #region Variables 
    public override string ApplicationName { get; set; } 
    public string ConnectionString { get; set; } 
    public string UpdateProcedure { get; set; } 
    public string GetProcedure { get; set; } 
    #endregion 

    #region Methods 
    public UserProfileProvider() 
    { } 

    internal static string GetConnectionString(string specifiedConnectionString) 
    { 
     if (String.IsNullOrEmpty(specifiedConnectionString)) 
      return null; 

     // Check <connectionStrings> config section for this connection string 
     ConnectionStringSettings connObj = ConfigurationManager.ConnectionStrings[specifiedConnectionString]; 
     if (connObj != null) 
      return connObj.ConnectionString; 

     return null; 
    } 
    #endregion 

    #region ProfileProvider Methods Implementation 
    public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) 
    { 
     if (config == null) 
      throw new ArgumentNullException("config"); 

     if (String.IsNullOrEmpty(name)) 
      name = "UserProfileProvider"; 

     if (String.IsNullOrEmpty(config["description"])) 
     { 
      config.Remove("description"); 
      config.Add("description", "My user custom profile provider"); 
     } 

     base.Initialize(name, config); 

     if (String.IsNullOrEmpty(config["connectionStringName"])) 
      throw new ProviderException("connectionStringName not specified"); 

     ConnectionString = GetConnectionString(config["connectionStringName"]); 

     if (String.IsNullOrEmpty(ConnectionString)) 
      throw new ProviderException("connectionStringName not specified"); 


     if ((config["applicationName"] == null) || String.IsNullOrEmpty(config["applicationName"])) 
      ApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath; 
     else 
      ApplicationName = config["applicationName"]; 

     if (ApplicationName.Length > 256) 
      throw new ProviderException("Application name too long"); 

     UpdateProcedure = config["updateUserProcedure"]; 
     if (String.IsNullOrEmpty(UpdateProcedure)) 
      throw new ProviderException("updateUserProcedure not specified"); 

     GetProcedure = config["getUserProcedure"]; 
     if (String.IsNullOrEmpty(GetProcedure)) 
      throw new ProviderException("getUserProcedure not specified"); 
    } 

    public override System.Configuration.SettingsPropertyValueCollection GetPropertyValues(System.Configuration.SettingsContext context, System.Configuration.SettingsPropertyCollection collection) 
    { 
     SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); 

     SqlConnection myConnection = new SqlConnection(ConnectionString); 
     SqlCommand myCommand = new SqlCommand(GetProcedure, myConnection); 
     myCommand.CommandType = CommandType.StoredProcedure; 

     myCommand.Parameters.AddWithValue("@FirstName", (string)context["FirstName"]); 

     try 
     { 
      myConnection.Open(); 
      SqlDataReader reader = myCommand.ExecuteReader(CommandBehavior.SingleRow); 

      reader.Read(); 

      foreach (SettingsProperty property in collection) 
      { 
       SettingsPropertyValue value = new SettingsPropertyValue(property); 

       if (reader.HasRows) 
       { 
        value.PropertyValue = reader[property.Name]; 
        values.Add(value); 
       } 
      } 

     } 
     finally 
     { 
      myConnection.Close(); 
      myCommand.Dispose(); 
     } 

     return values; 
    } 

    public override void SetPropertyValues(System.Configuration.SettingsContext context, System.Configuration.SettingsPropertyValueCollection collection) 
    { 
     SqlConnection myConnection = new SqlConnection(ConnectionString); 
     SqlCommand myCommand = new SqlCommand(UpdateProcedure, myConnection); 
     myCommand.CommandType = CommandType.StoredProcedure; 

     foreach (SettingsPropertyValue value in collection) 
     { 
      myCommand.Parameters.AddWithValue(value.Name, value.PropertyValue); 
     } 

     myCommand.Parameters.AddWithValue("@FirstName", (string)context["FirstName"]); 

     try 
     { 
      myConnection.Open(); 
      myCommand.ExecuteNonQuery(); 
     } 

     finally 
     { 
      myConnection.Close(); 
      myCommand.Dispose(); 
     } 
    } 

Aquí está mi acción CreateProfile en mi controlador:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult CreateProfile(string Username, string Password, string FirstName, string LastName) 
{ 
    MembershipCreateStatus IsCreated = MembershipCreateStatus.ProviderError; 
    MembershipUser user = null; 

    user = Membership.CreateUser(Username, Password, "[email protected]", "Q", "A", true, out IsCreated); 

    if (IsCreated == MembershipCreateStatus.Success && user != null) 
    { 
     ProfileCommon profile = (ProfileCommon)ProfileBase.Create(user.UserName); 

     profile.FirstName = FirstName; 
     profile.LastName = LastName; 
     profile.Save(); 
    } 

    return RedirectToAction("Index", "Home"); 
} 

Mi procedimiento usp_GetUserProcedure no es nada especial:

ALTER PROCEDURE [dbo].[usp_GetUserProcedure] 
-- Add the parameters for the stored procedure here 
@FirstName varchar(50) 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 

-- Insert statements for procedure here 
SELECT * FROM dbo.Users WHERE FirstName = @FirstName 
END 

A nd mi archivo Web.Config:

<profile enabled="true" 
     automaticSaveEnabled="false" 
     defaultProvider="UserProfileProvider" 
     inherits="Test.Models.ProfileCommon"> 
<providers> 
<clear/> 
<add name="UserProfileProvider" 
     type="Test.Controllers.UserProfileProvider" 
     connectionStringName="ApplicationServices" 
     applicationName="UserProfileProvider" 
     getUserProcedure="usp_GetUserProcedure" 
     updateUserProcedure="usp_UpdateUserProcedure"/> 
</providers> 
</profile> 

Pero siempre consigo esta excepción:

procedimiento o función 'usp_GetUserProcedure' espera el parámetro '@Nombre', que no fue suministrado.

¿Alguna idea sobre lo que podría estar haciendo mal?

Respuesta

2

La causa más probable es que

myCommand.Parameters.AddWithValue("@FirstName", (string)context["FirstName"]); 

(string)context["FirstName"] es un valor nulo. Incluso si pasa un parámetro a un sproc, si el valor es nulo en un parámetro requerido, verá este error. SQL Server (efectivamente) no diferencia entre un parámetro no pasado y uno pasado con un valor nulo.

Aparece un error de SQL. Esto no está relacionado con MVC y MVC realmente no está causando su problema. Determine si null es un valor válido context["FirstName"], y si es así, cambie su función para aceptar valores nulos. De lo contrario, averigüe por qué context["FirstName"] es nulo.

Además, no creo que esta línea vaya a agregar los nombres de sus parámetros correctamente (con el prefijo "@").

myCommand.Parameters.AddWithValue (value.Name, value.El valor de la propiedad);

Además, dado que se trata de MVC, asegúrese de que tiene un control nombrado FirstName en el formulario de envío a:

public ActionResult CreateProfile(string Username, string Password, string FirstName, string LastName) 

Se lee campos basados ​​en el nombre, no el ID

0

Sí, es porque estoy usando una clase para mis propiedades, ProfileCommon que hereda de ProfileBase.

public class ProfileCommon : ProfileBase 
{ 
public virtual string Label 
{ 
    get 
    { 
     return ((string)(this.GetPropertyValue("Label"))); 
    } 
    set 
    { 
     this.SetPropertyValue("Label", value); 
    } 
} 

public virtual string FirstName 
{ 
    get 
    { 
     return ((string)(this.GetPropertyValue("FirstName"))); 
    } 
    set 
    { 
     this.SetPropertyValue("FirstName", value); 
    } 
} 

public virtual string LastName 
{ 
    get 
    { 
     return ((string)(this.GetPropertyValue("LastName"))); 
    } 
    set 
    { 
     this.SetPropertyValue("LastName", value); 
    } 
} 

public virtual ProfileCommon GetProfile(string username) 
{ 
    return Create(username) as ProfileCommon; 
} 
} 

Se puede ver que estoy usando esta clase en el archivo Web.config:

<profile enabled="true" 
    automaticSaveEnabled="false" 
    defaultProvider="UserProfileProvider" 
    inherits="Test.Models.ProfileCommon"> 
[...] 

Y con ASP.Net MVC, si escribía mis propiedades en Web.Config, no puedo acceder a ellos usando Profile.PropertyName más. Tal vez hay una manera, pero no encuentro ningún ejemplo.

Cuestiones relacionadas