6

Problem Membership.GetUser działa dobrze, jeśli mogę użyć GUID, ale nie powiedzie się, gdy próbuję go bez parametrów lub z nazwą:SqlMembershipProvider Membership.GetUser wg nazwy upadającego

//This works and adds records to aspnet_user & aspnet_Membership tables 
MembershipUser membershipUser = Membership.CreateUser(_name, _pwd, _email, null, null, true, null, out createStatus); 

//These fail with an InvalidCastException 
MembershipUser membershipUser2 = Membership.GetUser(_name, true); 
MembershipUser membershipUser3 = Membership.GetUser(); 

//If I go look up the GUID for this user (userId), this works! 
MembershipUser membershipUser4 = Membership.GetUser(new Guid("E1428CD3-CF17-494E-AB77-CF8F6010F585"), true); 

inne tajemnice

//This works 
Int32 count = Membership.GetNumberOfUsersOnline();  

//this fails (but totalRecords has the right value) 
Int32 totalRecords; 
MembershipUserCollection col = Membership.GetAllUsers(0,100, out totalRecords); 

Setup

  • MVC
  • .NET 4.0
  • Domyślnie SQL Membership Provider (nie ma niestandardowy lub nadpisania)

ex:

<membership defaultProvider="SqlProvider"> 
    <providers> 
     <clear /> 
     <add name="SqlProvider" 
      type="System.Web.Security.SqlMembershipProvider" 
      connectionStringName="MyDB" 
      enablePasswordRetrieval="false" 
      enablePasswordReset="true" 
      requiresQuestionAndAnswer="false" 
      applicationName="myapp" 
      requiresUniqueEmail="false" 
      passwordFormat="Hashed" 
      maxInvalidPasswordAttempts="5" 
      minRequiredPasswordLength="2" 
      minRequiredNonalphanumericCharacters="0" 
      passwordAttemptWindow="10" 
      passwordStrengthRegularExpression="" /> 
    </providers> 
</membership> 
  • Standardowy aspnet_ * tabele bazy danych bez dostosowywania lub dodatkowe klucze
  • aspnet_Membership_GetAllUsers r nie jest dobrze ręcznie z DB. przekierowany przedstawia oczekiwane wyniki są zwracane
  • aspnet_Membership_GetUserByName pracuje także z DB

Exception Szczegóły

Specified cast is not valid. 
    at System.Data.SqlClient.SqlBuffer.get_SqlGuid() 
    at System.Data.SqlClient.SqlDataReader.GetGuid(Int32 i) 
    at System.Web.Security.SqlMembershipProvider.GetUser(String username, Boolean userIsOnline) 
    at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline) 

Myśli

To prawie jak coś jest nie tak wewnątrz metody Membership.GetUser. Zastanowiłem się kod dla System.Web.Security.SqlMembershipProvider.GetUser dla mojego System.Web.dll (wersja 4.0) i mam następujące:

public override MembershipUser GetUser(string username, bool userIsOnline) 
{ 
    SecUtility.CheckParameter(ref username, true, false, true, 256, "username"); 
    SqlDataReader reader = (SqlDataReader) null; 
    try 
    { 
    SqlConnectionHolder connectionHolder = (SqlConnectionHolder) null; 
    try 
    { 
     connectionHolder = SqlConnectionHelper.GetConnection(this._sqlConnectionString, true); 
     this.CheckSchemaVersion(connectionHolder.Connection); 
     SqlCommand sqlCommand = new SqlCommand("dbo.aspnet_Membership_GetUserByName", connectionHolder.Connection); 
     sqlCommand.CommandTimeout = this.CommandTimeout; 
     sqlCommand.CommandType = CommandType.StoredProcedure; 
     sqlCommand.Parameters.Add(this.CreateInputParam("@ApplicationName", SqlDbType.NVarChar, (object) this.ApplicationName)); 
     sqlCommand.Parameters.Add(this.CreateInputParam("@UserName", SqlDbType.NVarChar, (object) username)); 
     sqlCommand.Parameters.Add(this.CreateInputParam("@UpdateLastActivity", SqlDbType.Bit, (object) (bool) (userIsOnline ? 1 : 0))); 
     sqlCommand.Parameters.Add(this.CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, (object) DateTime.UtcNow)); 
     SqlParameter sqlParameter = new SqlParameter("@ReturnValue", SqlDbType.Int); 
     sqlParameter.Direction = ParameterDirection.ReturnValue; 
     sqlCommand.Parameters.Add(sqlParameter); 
     reader = sqlCommand.ExecuteReader(); 
     if (!reader.Read()) 
     return (MembershipUser) null; 
     string nullableString1 = this.GetNullableString(reader, 0); 
     string nullableString2 = this.GetNullableString(reader, 1); 
     string nullableString3 = this.GetNullableString(reader, 2); 
     bool boolean1 = reader.GetBoolean(3); 
     DateTime creationDate = reader.GetDateTime(4).ToLocalTime(); 
     DateTime lastLoginDate = reader.GetDateTime(5).ToLocalTime(); 
     DateTime lastActivityDate = reader.GetDateTime(6).ToLocalTime(); 
     DateTime lastPasswordChangedDate = reader.GetDateTime(7).ToLocalTime(); 
     Guid guid = reader.GetGuid(8); 
     bool boolean2 = reader.GetBoolean(9); 
     DateTime lastLockoutDate = reader.GetDateTime(10).ToLocalTime(); 
     return new MembershipUser(this.Name, username, (object) guid, nullableString1, nullableString2, nullableString3, boolean1, boolean2, creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, lastLockoutDate); 
    } 
    finally 
    { 
     if (reader != null) 
     reader.Close(); 
     if (connectionHolder != null) 
     connectionHolder.Close(); 
    } 
    } 
    catch 
    { 
    throw; 
    } 
} 

Next Step

I Mam nadzieję, że uda mi się znaleźć jakiś kierunek od tłumu SO, gdzie powinienem pójść dalej. Sądzę, że mógłbym zastąpić tę metodę i złożyć mojego dostawcę tylko po to, żeby go zdebugować, albo mógłbym po prostu obejść to cholerstwo i osobiście zadzwonić do DB. Wydaje się, że dużo bólu z niektórych podstawowych DB CRUD.

Obecny status

  • 3/5/2013: Odkryłem dziś rano, że mój aspnet_Users stół ma UserId jako nvarchar(256) zamiast uniqueidentifier. Być może SqlDataReader.GetGuid() się tam dusi. Dziś wieczorem poprowadzę testy, żeby sprawdzić, czy to jest problem. Zastanawiam się, czy moja struktura tabel jest nieaktualna, ponieważ dokumentacja online pokazuje to pole jako uniqueidentifier.
+0

Jak to nie? Szczegóły wyjątku proszę. –

+0

Dodano szczegóły wyjątku. Linia: System.Data.SqlClient.SqlDataReader.GetGuid (Int32 i) pewny wydaje się dziwne. – maulkye

+0

Ponadto, jeśli masz zamiar „odzwierciedlają-out”/reverse-inżynier/dekompilować-for-wgląd kod, należy spojrzeć na metody getUser() na statycznym klasy Membership - Membership.GetUser() - to jest TAM, gdzie poczyniono założenia dotyczące tożsamości obecnego użytkownika. GetUser() zakłada, że ​​pobiera szczegółów na temat bieżącego użytkownika w aplikacji internetowej –

Odpowiedz

1

odpowiedzi

My aspnet_User i aspnet_Membership stoły miał UserId zestaw do rodzaju nvarchar(256).

Dyskusja

To wydaje się być przyczyną błędu podczas następnej linii od sposobu SqlMembershipProvider.GetUser:

Guid guid = reader.GetGuid(8); 

wpadłem aspnet_regsql.exe z obu ram .NET 2 i 4 i oba ustawiają UserId na uniqueidentifier, co prowadzi mnie do myślenia, że ​​nie mam (mimo wszystko) standardowej ASPNET DB.

Trochę grzebania w historii projektu wynika, że ​​ta baza danych członków pierwotnie wygenerowane przez dostawcę niestandardowego dla MySql. Mogę tylko stwierdzić, że nigdy nie był on regenerowany, kiedy przełączyliśmy się z powrotem na domyślnego dostawcę.

Dzięki wszystkim za ich opinie.

1

Dlaczego używasz membership.CurrentUserName()?można po prostu użyć HttpContext.Current.User.Identity.Name;