2013-03-06 92 views
0

我正在使用ASP.NET MVC 4 SimpleMembership「開箱即用」。SimpleMembership MVC 4保持身份驗證,但未驗證

[Authorize(Roles = "User")].

它工作正常,設置身份驗證要求,因爲在控制器德科離開網站時,未註銷除外。下一次我回來時,Request.IsAuthenticated仍然如此,但是當我進入視圖時,我會看到「A network-related or instance-specific error occurred while establishing a connection to SQL.」事實上,它看起來像是試圖連接到本地數據庫:"SQLExpress database file auto-creation error' - 在App_Data文件夾中。但是我沒有指向這個的連接字符串,它全部在Azure Sql上。

不知道這是什麼?爲什麼它假裝保持登錄狀態?爲什麼試圖創建一個數據庫?

------------------------------------Stack trace------------------------------------------- 

[SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)] 
    System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5296071 
    System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +558 
    System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover) +5308555 
    System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover) +145 
    System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) +889 
    System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance) +307 
    System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions) +434 
    System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) +5311099 
    System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions) +38 
    System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) +5313314 
    System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) +143 
    System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) +83 
    System.Data.SqlClient.SqlConnection.Open() +96 
    System.Web.Management.SqlServices.GetSqlConnection(String server, String user, String password, Boolean trusted, String connectionString) +76 

[HttpException (0x80004005): Unable to connect to SQL Server database.] 
    System.Web.Management.SqlServices.GetSqlConnection(String server, String user, String password, Boolean trusted, String connectionString) +131 
    System.Web.Management.SqlServices.SetupApplicationServices(String server, String user, String password, Boolean trusted, String connectionString, String database, String dbFileName, SqlFeatures features, Boolean install) +89 
    System.Web.Management.SqlServices.Install(String database, String dbFileName, String connectionString) +27 
    System.Web.DataAccess.SqlConnectionHelper.CreateMdfFile(String fullFileName, String dataDir, String connectionString) +386 

回答

0

它是利用cookies來保存用戶登錄,如果您正在使用SimpleMembership「開箱即用」的設置。 SimpleMembership首先使用EF代碼,如果它不認爲已經存在,它將嘗試創建一個數據庫。它使用延遲加載機制,因此它不會嘗試創建它,直到您點擊AccountController(即您被帶到登錄或註冊頁面)。如果授權失敗,您將被重定向到登錄頁面。如果您使用「開箱即用」設置,那麼它想要在名爲DefaultConnection的web.config中使用連接字符串。它會是這個樣子

<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ProjectName-20130125152904;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ProjectName-20130125152904.mdf" providerName="System.Data.SqlClient" /> 

其中projectname是MVC項目的名稱,當你第一次與MVC 4 Internet公司的模板創建它。您需要將其更改爲使用Azure。

更新2013年3月7日 既然你不使用你需要更新在兩個地方使用的連接字符串中的默認連接字符串。你提到你在初始化器中更新了它,所以我假定你的意思是在SimpleMembershipInitializer中,代碼看起來像這樣。

public SimpleMembershipInitializer() 
    { 
     Database.SetInitializer<UsersContext>(null); 

     try 
     { 
      using (var context = new UsersContext()) 
      { 
       if (!context.Database.Exists()) 
       { 
        // Create the SimpleMembership database without Entity Framework migration schema 
         ((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); 
       } 
      } 

      WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true); 
     } 
     catch (Exception ex) 
     { 
      throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex); 
     } 

我假設(因爲你沒有提供你的問題的任何代碼),您在InitializeDatabaseConnection更新的第一個參數使用您的連接字符串的名稱。這很好,但它只處理配置數據庫連接。如果您查看檢測數據庫是否已創建並實際創建的代碼,則會在設置此連接的上方進行檢查。連接字符串也在UserContext中設置,您可以在AccountModels.cs中找到該連接字符串。代碼如下:

public UsersContext() 
    : base("DefaultConnection") 
{ 
} 

正如您所看到的,連接字符串被傳遞給基礎上下文。如果你在這裏沒有改變它,那麼它將使用DefaultConnection連接字符串檢查是否存在,並嘗試創建它。我相信如果連接字符串丟失,它會嘗試創建一個名爲DefaultConnection的本地數據庫。

如果您使用表單身份驗證,我會建議撕掉初始化程序並自行處理它爲described in this article。此初始化程序的設計使模板生成的代碼可以在開發人員不想使用表單身份驗證的情況下工作。

+0

我在web.config中有一個不同的連接字符串,它指向我的Azure數據庫。 「DefaultConnection」不存在了。因此,我在初始化程序中更改了引用,因此它指向新的連接字符串。請注意,身份驗證正常工作,如果我註銷並登錄。但如果我只關閉瀏覽器並回來,那麼我有問題。 – Anders 2013-03-06 20:29:50

+0

請參閱我更新的答案,該答案基於您在評論中提供的新信息。 – 2013-03-07 17:07:50

+0

感謝您的更新。 UsersContext構造函數中的連接字符串也被設置爲相同的連接字符串,並且它工作得很好。否則,我將無法登錄,如上所述,它工作得很好。問題出現在超時之後,即沒有註銷,然後轉到需要身份驗證的頁面。 – Anders 2013-03-07 17:39:16

0

我終於想通了這個問題!當我發現這個線程時,我遇到了同樣的問題,但由於沒有明確的答案,我不得不自己動手。

會發生什麼情況是UsersContext最終會丟失其連接的跟蹤。通過完全繞過UserContext並避免構造函數,連接將保持穩定。

注意:我不會自動生成簡單的會員表,所以我不確定這是否會出現,如果是這樣的話。

請參閱AccountModels.cs中的UsersContext。你應該註釋掉/刪除這段代碼。

public class UsersContext : DbContext 
{ 
    public UsersContext() 
     : base("YourDBContext") 
    { 
    } 

    public DbSet<UserProfile> UserProfiles { get; set; } 
    public DbSet<webpages_Membership> webpages_Memberships { get; set; } 
    public DbSet<UsersInRole> webpages_UsersInRoles { get; set; } 
    public DbSet<Role> webpages_Roles { get; set; } 
} 

添加從UsersContext的DbSets到你自己的上下文:

public class YourDBContext : DbContext 
{ 
    public DbSet<Blah> Blahs{ get; set; } 
    public DbSet<Something> Somethings { get; set; } 

    public DbSet<UserProfile> UserProfiles { get; set; } 
    public DbSet<webpages_Membership> webpages_Memberships { get; set; } 
    public DbSet<UsersInRole> webpages_UsersInRoles { get; set; } 
    public DbSet<Role> webpages_Roles { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
    } 

} 

當然以後你做的一切,你必須改變任何引用到UsersContext到YourDBContext,即

UsersContext uc = new UsersContext(); 

成爲

YourDBContext ydb = new YourDBContext(); 

這樣做的附加好處是您不必跟蹤兩個不同的DBContext。