2009-05-07 18 views
6

Próbowałem dużo na implementacji niestandardowego dostawcy profili w ASP.NET MVC. Przeczytałem wiele tutoriali, ale nie mogę znaleźć mojego problemu. Jest bardzo podobny do Implementing Profile Provider in ASP.NET MVC.Implementowanie niestandardowego dostawcy profilu w ASP.NET MVC

Ale chciałbym utworzyć mój własny profil Provider, tak I napisał następujące klasy, która dziedziczy 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(); 
     } 
    } 

Oto moje działanie CreateProfile w moim kontrolera:

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

Moja procedura usp_GetUserProcedure nie jest niczym szczególnym:

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 mój plik 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> 

Ale zawsze uzyskać ten wyjątek:

Procedura lub funkcja 'usp_GetUserProcedure' oczekuje parametr '@FirstName', który nie został dostarczony.

Jakieś myśli o tym, co robię źle?

Odpowiedz

2

Najbardziej prawdopodobną przyczyną jest to, że

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

(string)context["FirstName"] jest wartość null. Nawet jeśli wprowadzisz parametr do sproc, jeśli wartość jest null dla wymaganego parametru, zobaczysz ten błąd. Serwer SQL (efektywnie) nie rozróżnia między parametrami, które nie zostały przekazane, a tymi, które zostały przekazane z wartością pustą.

Widzisz błąd SQL. Nie ma to związku z MVC i MVC tak naprawdę nie powoduje twojego problemu. Określ, czy wartość null ma poprawną wartość context["FirstName"], a jeśli tak, zmień funkcję, aby akceptować wartości puste. Jeśli nie, sprawdź, dlaczego context["FirstName"] ma wartość null.

Ponadto, nie sądzę, że ta linia będzie poprawnie dodawać nazwy parametrów (z prefiksem "@").

myCommand.Parameters.AddWithValue (value.Name, value.Wartość nieruchomości);

Również ponieważ jest to MVC, upewnij się, że masz kontrolę nazwie FirstName sprawie delegowania formy do:

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

Odczytuje pól na podstawie nazwy, a nie ID

0

Tak, ponieważ używam klasy dla moich właściwości, ProfileCommon, która dziedziczy z 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; 
} 
} 

Widać, że używam tej klasy w pliku web.config:

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

I z ASP.NET MVC, jeśli pisałam właściwości w pliku web.config, nie mogę uzyskać dostęp do nich za pomocą Profile.PropertyName już. Może jest jakiś sposób, ale nie znajduję żadnych przykładów.

Powiązane problemy