The problem Membership.GetUser works fine if I use the GUID, but fails if I try it without parameters or with the name:
如果我使用GUID,则Membership.GetUser会正常工作,但如果我在没有参数或名称的情况下尝试它,则会失败:
//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);
Other 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);
The Setup
- MVC
- .NET 4.0
- Default SQL Membership Provider (no custom or overrides)
默认SQL成员资格提供程序(无自定义或覆盖)
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_* database tables with no customization or extra keys
- aspnet_Membership_GetAllUsers runs fine manually from the DB. Redirected output shows the expected results are being returned
- aspnet_Membership_GetUserByName is working as well from the DB
标准的aspnet_ *数据库表,没有自定义或额外的键
aspnet_Membership_GetAllUsers可以从DB手动运行。重定向输出显示正在返回预期结果
aspnet_Membership_GetUserByName也可以从数据库中运行
Exception Details
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)
Thoughts
It's almost like there's something wrong inside the Membership.GetUser method. I reflected out the code for the System.Web.Security.SqlMembershipProvider.GetUser for my System.Web.dll (version 4.0) and I get the following:
这几乎就像Membership.GetUser方法中的内容有问题。我为System.Web.dll(版本4.0)反映了System.Web.Security.SqlMembershipProvider.GetUser的代码,我得到以下内容:
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'm hoping to get some direction from the SO crowd on where I should go next. I figure I could either override this method and put together my own provider just to debug it, or I could just go around the darned thing and call out to the DB myself directly. This seems like a lot of heartache from some basic DB CRUD.
我希望从SO人群那里得到一些方向,我应该去哪里。我想我可以覆盖这个方法并将我自己的提供程序放在一起只是为了调试它,或者我可以绕过这个愚蠢的事情直接调用数据库。这看起来像一些基本的DB CRUD很多心痛。
Current Status
- 3/5/2013: I discovered this morning that my
aspnet_Users
table has theUserId
as annvarchar(256)
instead of auniqueidentifier
. Perhaps theSqlDataReader.GetGuid()
is choking there. I'll run some tests this evening to see if that's the problem. I'm wondering if my table structure is outdated, because online documentation shows this field as auniqueidentifier
.
2013年3月5日:我今天早上发现我的aspnet_Users表将UserId作为nvarchar(256)而不是uniqueidentifier。也许SqlDataReader.GetGuid()在那里窒息。今天晚上我会做一些测试,看看是不是问题。我想知道我的表结构是否过时,因为在线文档将此字段显示为uniqueidentifier。
2 个解决方案
#1
1
Why do you use membership.CurrentUserName()
? You can just use HttpContext.Current.User.Identity.Name;
为什么使用membership .CurrentUserName()?你可以使用HttpContext.Current.User.Identity.Name;
#2
1
Answer
My aspnet_User and aspnet_Membership tables had the UserId
set to a type of nvarchar(256)
.
我的aspnet_User和aspnet_Membership表将UserId设置为nvarchar(256)的类型。
Discussion
This appears to have been causing the error during the following line from the SqlMembershipProvider.GetUser method:
这似乎是在SqlMembershipProvider.GetUser方法的以下行中导致错误:
Guid guid = reader.GetGuid(8);
I ran aspnet_regsql.exe from both .NET frameworks 2 and 4, and both set the UserId to a uniqueidentifier, leading me to think I did not (after all) have a standard ASPNET DB.
我从.NET框架2和4运行了aspnet_regsql.exe,并且都将UserId设置为uniqueidentifier,这让我觉得我(毕竟)没有标准的ASPNET DB。
A little digging in the project's history reveals that this membership database was originally generated via a custom provider for MySql. I can only conclude that it was never regenerated when we switched back to the default provider.
对项目历史进行一点挖掘后发现,该成员资格数据库最初是通过MySql的自定义提供程序生成的。我只能得出结论,当我们切换回默认提供程序时,它永远不会重新生成。
Thanks to everyone for their feedback.
感谢大家的反馈。
#1
1
Why do you use membership.CurrentUserName()
? You can just use HttpContext.Current.User.Identity.Name;
为什么使用membership .CurrentUserName()?你可以使用HttpContext.Current.User.Identity.Name;
#2
1
Answer
My aspnet_User and aspnet_Membership tables had the UserId
set to a type of nvarchar(256)
.
我的aspnet_User和aspnet_Membership表将UserId设置为nvarchar(256)的类型。
Discussion
This appears to have been causing the error during the following line from the SqlMembershipProvider.GetUser method:
这似乎是在SqlMembershipProvider.GetUser方法的以下行中导致错误:
Guid guid = reader.GetGuid(8);
I ran aspnet_regsql.exe from both .NET frameworks 2 and 4, and both set the UserId to a uniqueidentifier, leading me to think I did not (after all) have a standard ASPNET DB.
我从.NET框架2和4运行了aspnet_regsql.exe,并且都将UserId设置为uniqueidentifier,这让我觉得我(毕竟)没有标准的ASPNET DB。
A little digging in the project's history reveals that this membership database was originally generated via a custom provider for MySql. I can only conclude that it was never regenerated when we switched back to the default provider.
对项目历史进行一点挖掘后发现,该成员资格数据库最初是通过MySql的自定义提供程序生成的。我只能得出结论,当我们切换回默认提供程序时,它永远不会重新生成。
Thanks to everyone for their feedback.
感谢大家的反馈。