2

在我最後的question about fine-tuning的所有答案都證明比我預期的更有用之後,我想我會問另一個關於MembershipProviders的類似問題。如何微調會員供應商?

好的,首先澄清一下:我知道什麼是會員,角色和配置文件提供程序,如何實現我自己的,如何配置它們以及關於它們的大部分事情。
實現角色和配置文件提供程序非常簡單,因爲它們大多數時間只需要簡單的CRUD。 (一行LINQ對於RoleProvider方法的大約一半是足夠的。)

但是,成員資格提供者是一個不同的野獸。你們中的許多人可能會意識到它違反了SR(單一責任)原則,因爲它必須做與用戶管理有關的所有事情。雖然這爲定製留下了很大空間,但它也有其不足之處。 互聯網上沒有關於他們的EXACT預期行爲的信息,比如他們什麼時候應該拋出異常或者簡單地返回null以及類似的東西。

我用this sample implementation作爲參考,但它也包含了幾個矛盾。

  • 例如,它使用自己的ValidateUser方法來檢查ChangePassword方法中的憑據。但是ValidateUser也會將用戶的LastLoginDate更新爲當前日期。那麼,框架是否期望我也將其設置在自己的提供者中,還是僅僅是樣本中的錯誤?
  • 另一種是:每次驗證新密碼時,ChangePassword方法都會引發異常,但CreateUser不會引發異常,它只會返回false。
  • 最後但並非最不重要的一點是:它計算用戶的無效密碼嘗試次數,並在通過閾值時鎖定它們。雖然這很好,但它需要手動操作來解鎖用戶。如果我的提供商在一段時間後自動解鎖用戶,這是否是一個問題?

  • (編輯)我幾乎忘了:示例中的CreateUser方法從方法參數插入ID。實際上,我認爲這是不好的做法,因爲我將自動入門與inters用作ID,所以從某些方法參數插入它們不是一種選擇。我應該忽略這個參數,還是要求它的值爲null,如果不是,則拋出異常?

總而言之,ASP.NET是否對MembershipProvider的行爲有任何假設?
是否有任何文檔描述應該何時拋出異常或僅返回null?我還試圖找到一組通用的單元測試,它將提供一些有關預期行爲的指導,但沒有運氣,我發現大量關於「單元測試是好的」的文章,以及「如何單元測試MembershipProvider 「,但沒有一個會有任何實際測試。

在此先感謝大家!

回答

4

你可以諮詢MSDN的指導。例如,RoleProvider.RemoveUsersFromRoles提供了以下指導意見:

RemoveUsersFromRoles由 RemoveUserFromRole, RemoveUsersFromRole, RemoveUserFromRoles和 RemoveUsersFromRoles的 角色類的方法被稱爲在 刪除從指定的角色中的指定 用戶數據源。 配置的ApplicationName的角色只有 修改。

如果任何指定角色名都沒有找到已配置的 的applicationName ,我們建議您 提供商拋出 ProviderException。

如果任何指定的用戶名是 不與任何已配置的applicationName的 的 指定角色名的關聯,我們 建議您的供應商拋出 ProviderException。

如果任何指定的用戶名爲 null或爲空字符串,我們建議您的提供商拋出 異常。

如果任何指定角色名稱爲 null或爲空字符串,我們建議您的提供商拋出 異常。

如果您的數據源支持 交易,我們建議您 包括每個刪除操作的 交易,你回滾 交易,如果 任何刪除操作將失敗拋出異常。

而且RoleProvider.GetRolesForUser說:

GetRolesForUser由Roles類的GetRolesForUser方法檢索指定的用戶與數據源相關聯的角色名字叫。僅檢索配置的ApplicationName的角色。

如果指定的用戶對於配置的applicationName不存在任何角色,我們建議您的提供者返回一個沒有元素的字符串數組。

如果指定的用戶名爲空或爲空字符串,我們建議您的提供者拋出異常。

但是,在實踐中,每個提供者中只有一些方法和行爲是需要和期望的。其餘的是支持你希望實現的功能。

經過多年處理默認提供程序堆棧之後,我開始理解一些讓您停下來關於您鏈接的示例的事情,例如,這是一個非常簡單的實現, ChangePassword方法。

如果您使用反射器並檢查SqlMembershipProvider,您會注意到一些顯着的差異...

例如:

  • 的ValidateUser更新登錄的日期,因爲,用戶登錄,並通過調用.CheckPassword與真正的UpdateLastLoginTime這樣做。更改密碼調用相同的方法,但提供false。

  • CreateUser方法接受ProviderUserKey,因爲SPROC也會接受UserId參數。這是爲了允許在成員和用戶表之間重新創建和同步。作爲API的使用者,您通常不會使用此功能,但提供者堆棧在內部完成。

  • 關於停工..這取決於你。這就是實現定製提供者的全部內容:獲得你想要的行爲。正如我所說,系統要求很少。

因此,這給我們帶來了你的問題的最後一部分(這兩段暗示同樣值得關注):預測行爲和單元測試...

由於供應商的行爲在很大程度上是任意的並且很少有預期的行爲,一套既定的通用測試將包含很少的方法。您需要編寫適用於您的實施行爲的測試。

作爲最後一點,我建議你的Asp.Net提供程序工具包示例爲finddownload。它爲您提供完整的Sql提供程序堆棧的工作源代碼,並將爲您提供有關如何實現「真實」提供程序的一些信息。

後記

在這個非常時刻,我實現一個完整的SQLite商棧與默認的SQL燃料電池堆100%兼容。該測試套件驗證我的堆棧和asp.net之間的行爲奇偶校驗。如果您通過我的個人資料打我的博客並與我聯繫,我會在測試完成時通知您,您可以將它們用作基準,以預測默認堆棧的預期結果。

+0

+1。感謝您的回答。但是,你忽略了最重要的部分。我應該在哪些方法中拋出異常,並且應該在哪些方法中返回false(或者在適用的情況下返回null)? – Venemo 2010-04-30 17:29:45

+0

@Venemo - 我更新了答案,爲您提供了您所要求的「正式」指導以及主觀指導。 – 2010-05-01 05:51:27

+0

非常感謝,這正是我一直在尋找的。 :)我不知道MSDN有這樣一個明確的指南。 (哦,如果你不介意,我會在你的博客上與你聯繫。) – Venemo 2010-05-01 11:56:41