將 ASP.NET 網站部署在 UNC 路徑上最重要的步驟

如果要將 ASP.NET 網站安裝在遠端的 UNC 路徑上,在設定 IIS 時除了一般檔案的存取權限外,最重要的就是 ASP.NET 的執行權限是否有正確設定,由於所有置於 UNC 路徑上的 .NET 應用程式都會預設套用 LocalIntranet 群組,所以你無法將 ASP.NET 佈署在 UNC 路徑上,除非自行新增 .NET 安全性原則。

在沒設定 .NET 安全性群組之前,不管你怎麼設定都會出現以下安全性例外狀況的錯誤訊息:

安全性例外狀況 :: 例外詳細資訊: System.Security.SecurityException: 型別 'System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' 的使用權限要求失敗。

SecurityException: Request for the permission of type ‘System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ failed

 

解決此問題的步驟如下:

1. [開始] / [執行] / 輸入 cmd 並按下 Enter

2. 進入 .Net Framework 的安裝目錄(注意:x86 架構與 x64 架構的目錄並不相同)

    如果是 x64 架構請進入 C:\Windows\Microsoft.NET\Framework64\v2.0.50727

    如果是 x86 架構請進入 C:\Windows\Microsoft.NET\Framework\v2.0.50727

    注意: 如果進入錯誤的路徑,怎麼設定還是無法使用,這取決於你的 .NET 應用程式是跑什麼架構!

3. 執行 CASPOL.exe 工具授權特定 UNC 路徑為「完全信任」,請參考以下指令

caspol -m -ag 1. -url "file://\\server\share\*" FullTrust -exclusive on

  接著畫面會問你是否確認要執行這個動作,它會要你輸入 yes 或 no,但你只能輸入 yn 喔!( 按 y )

  

  我們可以透過 caspol -listgroups 指令驗證此安全性原則是否設定成功:

 

4. 最後去設定 IIS ( IIS6 或 IIS 7 ),如果先前已經設定好請務必記得「回收應用程式集區」才能讓生效!

 

其他補充說明:

1. 如果你不小心新增了兩個重複的 UNC 路徑到 .NET 安全性原則中會造成 ASP.NET 無法執行

   錯誤訊息是: 不允許一個以上的獨佔群組。More than one exclusive group is not allowed.

   System.Security.Policy.PolicyException: 不允許一個以上的獨佔群組。

2. 如果 CASPOL.exe 本身在執行的時候會引發例外(Exception),那可能要重新開機才能解決此問題!

3. 若要移除先前設定的安全性原則,可以參考以下指令:

caspol -rg 1.6

注意:所有 .NET 安全性原則都有個編號,記得先用 caspol -listgroups 列出所有群組,並找出你之前新增的安全性原則編號,然後才能帶入指令中。

 

相關連結

  

此文章由 will 發表於 2010/2/28 下午 12:13:20

永久連結 | 評論 (0) | 此文章的RSSRSS comment feed |

分類: IIS | ASP.NET | 系統管理

標籤: , , , , , ,

收藏:

注意 Windows 對於檔案複製與搬移的 NTFS 權限變化 [重要]

之前在客戶那邊發生過好幾次檔案權限不足的問題,每次客戶拿到我們提供的更新檔,他都會先將檔案先複製到「桌面」,然後才會「搬移」到 C:\inetpub\wwwroot 網站目錄,結果每次更新檔案都會發生權限不足的問題,且他每次更版都要手動調整那些複製進去的檔案的檔案權限,這都是起因於 NTFS 權限在檔案被複製搬移時雖時都有可能發生權限的變更,此基本且重要的觀念不可不知!

將檔案從一個目錄「複製」到另一個目錄時 ( Ctrl + C , Ctrl + V )

由於「複製」檔案時,視同在「新目錄」下「建立新檔案」,所以複製檔案時原本該檔案的 NTFS 權限並不會帶過去,而複製過去的檔案會直接繼承該目標目錄的存取權限。

例如:我要將 C:\DirA\test.txt 複製到 C:\DirB\test.txt 時,C:\DirB\test.txt 的權限就會變成是繼承 C:\DirB 目錄的 NTFS 權限!

將檔案從一個目錄「搬移」到另一個目錄時 ( Ctrl + X , Ctrl + V )

在「搬移」檔案時,情況稍稍複雜一些,共有兩種狀況:

1. 在相同磁碟之間搬移檔案 ( 例如從 C:\DirA 複製到 C:\DirB )

  • 這種情況下,檔案被搬移過去後,檔案的 NTFS 權限會被完整保留
  • 這種相同磁碟搬移檔案的過程就好像在同一個目錄下將檔案「重新命名」一樣,而在作業系統中實際上也真的只是做重新命名的動作而已!

2. 在不同的磁碟之間搬移檔案( 例如從 C:\ 複製到 D:\ )

  • 這種情況與「複製」檔案是一樣的,檔案必須先在目的磁碟建立新檔,然後再將來源檔案刪除!
  • 換個角度想,如果你有一個 50GB 的大檔案,如果從 C:\DirA 目錄搬移到 C:\DirB 目錄,也許只要 1 秒的時間,但是若你將這個 50GB 的大檔案,從 C:\ 目錄搬移到 D:\ 目錄,可能會花上 10 分鐘之久。

額外補充一個不算觀念的觀念(算常識)

  • 如果你將檔案搬移或複製到非 NTFS 的檔案磁區 (例如: FAT, FAT32, … ),那麼所有的 NTFS 權限也將會全部遺失。
  • 如果你的檔案從非 NTFS 的檔案磁區複製或搬移到 NTFS 的檔案磁區 (FAT, FAT32, … ),那麼這些檔案會直接繼承目的目錄的權限。
  • 簡言之:FAT, FAT32 沒有權限概念!
  • 所以,如果你的 USB 隨身碟不是 NTFS 權限的話(大部分都不是),那麼也就不用那麼考慮權限變更的問題。

這一個簡單的小觀念可能會對網站部署造成大影響,因此不可不知!

  

此文章由 will 發表於 2010/2/25 下午 10:11:57

永久連結 | 評論 (6) | 此文章的RSSRSS comment feed |

分類: 系統管理 | Tips

標籤: , , ,

收藏:

ASP.NET MVC 開發心得分享 (16):在網站專案下運作

之前有很多人問我 ASP.NET MVC 到底可不可以在 Visual Studio 的網站專案(WebSite Project)模式下運作,也就是在 ASP.NET 動態編譯的架構下運行 ASP.NET MVC,事實上是沒問題且非常容易的,唯一的缺點就是會失去 Visual Studio 開發工具的有效支援,例如 Add Controller 或 Add View 等等的工作可能會變的沒辦法自動化等等。

1. 我們先在一個方案中建立一個基本的「網站專案」( WebSite Project ) 與一個 ASP.NET MVC 專案

2. 修改如上圖 WebSite2 專案的 web.config 讓專案本身能支援 ASP.NET MVC 所需的設定
   ( 如下圖的這些宣告都可以從 MvcApplication1 專案取得 )

調整 <system.web> / <compilation> / <assemblies> 載入與 ASP.NET MVC 相關的組件

調整 <system.web> / <pages> 下,新增 <namespaces> 宣告
【可參考:ASP.NET 如何預設匯入指定的命名空間(Namespace)

調整 <system.web> / <httpHandlers> 與 <httpModules> 下,新增以下宣告

如果你的網站會安裝到 IIS7 上面執行,那你也要修改 <system.webServer> 的設定

3. 在網站專案新增 Global.asax 檔案,並將 MvcApplication2 中的 Routing 相關程式碼複製進來

4. 將 Views, Scripts, Content 目錄移至 WebSite2 專案下,將 Controllers 目錄移至 App_Code 目錄下

5. 如果你希望讓首頁 ( http://localhost/ ) 也能執行 ASP.NET MVC 的話,那你也可以將 Default.aspx 也移至 WebSite2 專案,但有些地方要調整過才能符合 WebSite 專案的要求。

以上五個步驟完成後,ASP.NET MVC 就可以順利在 WebSite 專案的模式下運作,而且可以享用動態編譯的特性,你隨時可以修改 App_Code\Controllers 下的程式碼,而且立即生效!

備註:如果你要將此網站安裝在 IIS6 上,請記得要設定「萬用字元應用程式對應」,如下圖示:

  

此文章由 will 發表於 2010/2/22 下午 11:50:00

永久連結 | 評論 (1) | 此文章的RSSRSS comment feed |

分類: ASP.NET MVC

標籤: , ,

收藏:

與 Roy Osherove 探討單元測試的藝術 (心得筆記)

過年期間在家聽了 The Art of Unit Testing with Roy Osherove 節目,感覺獲益良多,因此將節目的對話內容做了個簡單的整理,由於是 Scott HanselmanRoy Osherove 的現場對話,內容感覺有點雜亂,我不確定可否將重點整理的夠清楚,但有些 Roy Osherove 分享的觀念是我覺得是很棒的,也解開我這段時間懵懵懂懂的 TDD 觀念,大家可以看完若覺得有問題可以留言討論看看。

要成功導入單元測試有三個主要的基本要素:

1. 信任你的測試結果 ( Trustworthiness )

  • 你是否能信任你的測試結果?
  • 如果你不斷的對測試結果失去信心,那麼你也不會繼續堅持撰寫單元測試
  • 有許多人搞不清楚「單元測試」與「整合測試」的差別,以致於感覺自己寫的單元測試過於薄弱而不相信測試的結果。(註: 該文章後面會提到單元測試整合測試的差別)
  • 如果你因為某些原因導致測試失敗,直接去改 Code 或直接去改 Test Code 都不是好事,你的首要目的是要能找出測試失敗發生的主因,而非只是看錯誤這件事,這樣你才能信任你的測試程式。

2. 測試程式的可維護性 ( Maintainability )

  • 你是否能夠持續的維護你的測試程式?
  • 如何有效的降低維護測試程式的成本?
  • 註: 透過一些 Testable Design Pattern 可以有效提升可維護性。例如: Repository Pattern, Service Pattern, …。好的軟體架構也能增強可維護性,例如: High Cohesion, Low Coupling, SRP, …

3. 測試程式的可讀性 ( Readability )

  • 你的測試程式的命名是否易於理解?
  • 當你測試失敗時是否能從測試失敗的測試方法(TestMethod)明確看出實際失敗的原因?
  • 當讀取測試數據的人看不懂你的測試,人們就不會執行這些測試、也不會去維護這些測試,久而久之就會越來越惡化。

----------

何謂「單元測試」?「單元測試」的注意事項!

  • 測試的最小單位,必須是可信任的、可重複執行的。
    例如: 測試某一個類別(Class)的某一個方法(Method)
  • 必須與「整合測試」做非常清楚的切割,兩者個概念完全不同
  • 單元測試程式不應該接觸到任何與任何 外部資源 (External Resources) 或 靜態物件 (Statics)。例如: File I/O, 資料庫操作, 網路連線, … 等等,且由於靜態方法會牽扯到狀態,所以不建議在單元測試中存取任何靜態物件。
  • DAL (Data Access Layer) 的程式不建議撰寫「單元測試」
    • 因為 DAL 的程式會與資料庫直接產生關聯,而資料庫中可能還會有 Trigger, Stored Procedure, 表格關聯, … 等,這些東西都會打破「單元測試」的原則,所以建議放入「整合測試」來進行。
  • 在「單元測試」類別裡,通常不會用到 Setup Attribute 與 Teardown Attribute,如果為了要簡化各 TestMethod 中許多重複的程式碼,建議使用 Factory method Pattern 來降低個別 TestMethod 之間的耦合關係。
  • 開發人員在撰寫程式時,務必要讓所有測試結果都亮起綠燈,沒有藉口。

何謂「整合測試」?與「整合測試」的注意事項!

  • 針對軟體專案的一部份或全部進行測試,可以跨越不同的類別與方法,並可直接存取的外部資源。例如: File I/O, 資料庫操作, 網路連線, … 等等。
  • 通常做「整合測試」都會需要先設置(Configure)測試所需的環境,測試完畢後通常要清除測試所產生的殘留資料,以利下次測試或避免影響其他整合測試的結果。
    • 可套用 Setup Attribute
    • 可套用 Teardown Attribute ( 或 Cleanup Attribute )
    • 註: 通常你看到測試專案中有用到 Teardown Method (即套用 Teardown 屬性的方法) 通常就意味著這是一個「整合測試」的測試方法。

----------

什麼是 Fake 物件?

  • 基本上我們為了要測試,所以會準備一些假的資料,由於「單元測試」不會接觸到外部資源,所以會需要透過一些假的物件模擬輸入的資料,所以當我們提到 faking something 時,意思就是提供一個假的、模擬的資料而已。
  • Fake 物件包含了兩種定義:
    • Mock 物件
    • Stub 物件

什麼是 Mock 物件?

  • Mock 物件主要的目的是為了用來做驗證(Assert)測試的結果是通過還是失敗
  • 所以 Mock 物件也是 Fake 物件的一種,用來假設該物件最後的執行結果為何,如果執行的結果與我們定義的 Mock 物件相符合,那就代表測試成功
  • 通常一個單元測試的 TestMethod 中只會有一個 Mock 物件

什麼是 Stub 物件?

  • 由於執行測試時可能會傳入許多參數或資料,為了能讓測試程式能夠執行,我們必須準備一些資料讓「單元測試」程式能夠順利執行,所以所有與驗證結果無關的 Fake 物件都稱為 Stub 物件
  • 通常一個單元測試的 TestMethod 中可能會有多個 Stub 物件,目的只是為了讓測試能夠順利進行

----------

「整合測試」與「單元測試」的差異,以一個簡單的例子解釋

如果你有一個 Storage 類別,該類別有個 Method 要被測試,該 Method 會呼叫 Service Layer 中的一個 Logger 物件,該物件可能是一個 Web Service 或直接存取資料庫。

而我們在撰寫單元測試時僅需 驗證 (Assert) 是否呼叫 Logger 物件的方法即可,並不需要讓 Logger 物件真正執行寫入 Log 或執行 Web Service 等動作,所以在 TestMethod 中你可能需要建立個 Fake Logger 物件(Mock Object),並且讓 Fake Logger 物件能透過 Mock Framework 或 Isolation Framework 之中獨立出來,並直接驗證其執行結果。若更進一步你可以在「單元測試」中撰寫一些輸入資料驗證的狀況,例如登 Log Message 大於 512 bytes 時引發例外狀況…等等。

如果是在做整合測試時,就必須要驗證「Log 檔案是否被建立或寫入」或「資料是否正確寫入資料庫」等等。

「單元測試」確保程式執行的行為與物件之間互動的情況,「整合測試」確保程式執行的結果,這兩者之間的測試程式也許類似,但需要被驗證(Assert)的東西可能不太一樣,而就是「整合測試」與「單元測試」最主要的差異。

----------

如何聞出「單元測試程式」的壞味道(Code Smell)

  • 每個 TestMethod 之間不能有任何關聯
    • 有些人為了在測試專案避免重複的程式碼,會讓其中一個 TestMethod 呼叫另一個 TestMethod,但這反而可能會影響測試程式之間的結果
  • 每個 TestMethod 之間不能有任何執行順序的要求。
    • 例如: 要先執行 TestMethodA 再執行 TestMethodB,這就是一個臭掉的 Code
  • 在一個 TestMethod 不要同時間驗證(Assert)兩件事以上
    • 一個 TestMethod 中如果有兩個以上的 Assert 命令,通常 90% 的情況都是有問題的,但如果這兩個以上的 Assert 命令是為了驗證同一件事,那就可以接受。
    • 重點在於你所定義的 TestMethod 是不是一個完整的「邏輯測試單位」,如果你測試的是「一件事」但有多個可以驗證的目標,那就可以擁有多的 Assert 驗證。
    • 例如在 ASP.NET MVC 2 RC 的 Visual Studio 2008 專案範本中內建的單元測試範例就有一個不好的例子(如下程式碼),從「測試方法的命名」看來是要驗證回傳結果是不是一個 View,但是他在同一個 TestMethod 中同時也驗證了 ViewData 的值,依照 Roy Osherove 的建議來看,這個 ChangePassword_Get_ReturnsView() 應該要拆開成兩個 TestMethod 才對:
[TestMethod]
public void ChangePassword_Get_ReturnsView()
{
// Arrange
AccountController controller = GetAccountController();

// Act
ActionResult result = controller.ChangePassword();

// Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
Assert.AreEqual(10, ((ViewResult)result).ViewData["PasswordLength"]);
}

----------

單元測試中的 TestMethod 的命名規則

  • 方法名稱會切割成三段,每段以底線 ( _ ) 分隔
  • 第 1 段:被測試的 Method 名稱
  • 第 2 段:測試的情境(Scenario)
  • 第 3 段:預期測試的結果
  • 並不以「單字」作為分段的依據,而是以這三段的分別來分隔
  • 例如:
    • 第 1 段:我們要測試 ChangePassword 方法
    • 第 2 段:情境是透過 HTTP GET 取得頁面時
    • 第 3 段:預期會回傳一個 ViewResult
  • 這時該測試方法的命名就可以為:
    • ChangePassword_Get_ReturnViewResult

----------

對測試專案的組織方法

  • 假設你原本專案名稱為:ProjectX
  • 單元測試專案可命名為:ProjectX.Tests
  • 整合測試專案可命名為:ProjectX.IntegratedTests
  • 剛開始導入單元測試建議一個專案對應一個單元測試專案,先不要多個專案共用一個單元測試專案

----------

單元測試到底要寫多少才夠?

還記得「單元測試有三個成功因素」的第 1 項嗎?信任你的測試結果 ( Trustworthiness ) !

單元測試要寫到能讓自己有信心的地步為止,只要你寫到感覺放心了,那測試程式就算寫夠了,而寫到多少、多細才算真的放心?那就看個人了,也因為沒有標準,所以單元測試才被稱為一種「藝術」。

有些人會花許多時間測試使用者可能輸入的值,尤其是 Monkey Test,但經常不知道要測到哪種程度才算夠,我的裡解是:

  • 先測試合理的輸入值,確認功能與架構
  • 再測試無理的輸入值,確認超出範圍的輸入值可否被正確處理

相關連結

  

此文章由 will 發表於 2010/2/21 下午 06:37:48

永久連結 | 評論 (0) | 此文章的RSSRSS comment feed |

分類: Unit Testing

標籤: , , , ,

收藏:

網域中的伺服器如果直接對外服務建議不要登錄 IP 到 DNS 中

網域中的伺服器如果有兩張以上的網路介面,而且也這些介面都有設定與啟用的話,在預設的情況下所有 IP 位址都會被動態註冊到網域主控站的 DNS 伺服器中,而這個動態註冊的過程卻會導致這台電腦的網域名稱 (例如: Web1.MyDomain.local ) 被多重註冊進 DNS 裡,進而形成 Round robin DNS 的情況,如果其中一個介面的 IP 不屬於網域內所使用的內部 IP 就很有可能造成一些不必要的問題發生。

要針對特定網路介面關閉自動登錄 DNS 就要修改 TCP/IP 的設定:

1. 開啟網路連線功能 ( ncpa.cpl )

2. 選取網路介面,並按下右鍵 / 內容

3. 選取 網際網路通訊協定第 4 版 (TCP/IPv4),並按下 [內容] 按鈕

4. 點選 [進階] 按鈕

5. 切換到 [DNS] 頁籤,並取消勾選 [在 DNS 中登錄這個連線的位址]

 

這樣就不會讓網域網路的網路連線大亂了。

  

此文章由 will 發表於 2010/2/14 上午 04:10:19

永久連結 | 評論 (1) | 此文章的RSSRSS comment feed |

分類: 系統管理

標籤: , , , , ,

收藏: