Note that there are some explanatory texts on larger screens.

plurals
  1. POSqlMembershipProvider Membership.GetUser by name failing
    text
    copied!<p><strong>The problem</strong> Membership.GetUser works fine if I use the GUID, but fails if I try it without parameters or with the name:</p> <pre><code>//This works and adds records to aspnet_user &amp; 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); </code></pre> <p><strong>Other Mysteries</strong></p> <pre><code>//This works Int32 count = Membership.GetNumberOfUsersOnline(); //this fails (but totalRecords has the right value) Int32 totalRecords; MembershipUserCollection col = Membership.GetAllUsers(0,100, out totalRecords); </code></pre> <p><strong>The Setup</strong></p> <ul> <li>MVC</li> <li>.NET 4.0</li> <li>Default SQL Membership Provider (no custom or overrides)</li> </ul> <p>ex:</p> <pre><code>&lt;membership defaultProvider="SqlProvider"&gt; &lt;providers&gt; &lt;clear /&gt; &lt;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="" /&gt; &lt;/providers&gt; &lt;/membership&gt; </code></pre> <ul> <li>Standard aspnet_* database tables with no customization or extra keys</li> <li>aspnet_Membership_GetAllUsers runs fine manually from the DB. Redirected output shows the expected results are being returned</li> <li>aspnet_Membership_GetUserByName is working as well from the DB</li> </ul> <p><strong>Exception Details</strong></p> <pre><code>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) </code></pre> <p><strong>Thoughts</strong></p> <p>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:</p> <pre><code>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; } } </code></pre> <p><strong>Next Step</strong></p> <p>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.</p> <p><strong>Current Status</strong></p> <ul> <li>3/5/2013: I discovered this morning that my <code>aspnet_Users</code> table has the <code>UserId</code> as an <code>nvarchar(256)</code> instead of a <code>uniqueidentifier</code>. Perhaps the <code>SqlDataReader.GetGuid()</code> 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 a <code>uniqueidentifier</code>. </li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload