Das Problem Membership.GetUser funktioniert gut, wenn ich die GUID verwenden, aber nicht, wenn ich es ohne Parameter oder mit dem Namen versuchen:SqlMembershipProvider Membership.GetUser namentlich andernfalls
//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);
Andere Mysteries
//This works
Int32 count = Membership.GetNumberOfUsersOnline();
//this fails (but totalRecords has the right value)
Int32 totalRecords;
MembershipUserCollection col = Membership.GetAllUsers(0,100, out totalRecords);
Das Setup
- MVC
- .NET 4.0
- Standard SQL-Mitgliedschaftsanbieter (keine benutzerdefinierte oder Überschreibungen)
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>
- Standard-aspnet_ * Datenbanktabellen ohne Anpassung oder zusätzliche Tasten
- aspnet_Membership_GetAllUsers r wir fine manuell aus der DB. Umgeleitete Ausgabe zeigt, sind die erwarteten Ergebnisse
- aspnet_Membership_GetUserByName arbeitet auch aus dem DB
Ausnahmedetails
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)
Gedanken
Es ist fast, als gäbe es etwas falsch zurückgegeben wird in der Membership.GetUser-Methode. Ich dachte den Code für die System.Web.Security.SqlMembershipProvider.GetUser für meine System.Web.dll aus (Version 4.0) und ich folgendes:
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;
}
}
Nächster Schritt
I‘ Ich hoffe auf eine Richtung von der SO-Crowd auf wo ich als nächstes gehen sollte. Ich denke, ich könnte diese Methode entweder außer Kraft setzen und meinen eigenen Provider zusammenstellen, nur um es zu debuggen, oder ich könnte einfach um das verdammte Ding herumgehen und mich direkt an die DB wenden. Dies scheint eine Menge Herzschmerz von einigen grundlegenden DB CRUD.
Aktuelle Stand
- 3/5/2013: entdecken ich heute Morgen, dass meine
aspnet_Users
Tabelle dieUserId
alsnvarchar(256)
anstelle einuniqueidentifier
hat. Vielleicht erstickt dieSqlDataReader.GetGuid()
dort. Ich werde heute Abend ein paar Tests machen, um zu sehen, ob das das Problem ist. Ich frage mich, ob meine Tabellenstruktur veraltet ist, weil Online-Dokumentation dieses Feld alsuniqueidentifier
zeigt.
Wie schlägt es fehl? Ausnahmedetails bitte. –
Ausnahmedetails hinzugefügt. Die Zeile: System.Data.SqlClient.SqlDataReader.GetGuid (Int32 i) scheint sicher seltsam. – maulkye
Wenn Sie den Code "reflect-out"/reverse-engine/decompile-for-insight ermitteln möchten, sollten Sie sich die Methode GetUser() für die statische Membership-Klasse Membership.GetUser() - it ansehen Dort werden Annahmen über die Identität des aktuellen Benutzers gemacht. GetUser() geht davon aus, dass Details über den CURRENT USER in einer Webanwendung abgerufen werden. –