見 http://msdn.microsoft.com/zh-tw/library/system.windows.threading.dispatcherframe.aspx
execution (執行) 怎麼會翻譯成例外(exception) 呢?機器翻譯時不會翻錯字,這明顯地不是機器翻譯的,而是人去翻譯的。
結論
沒有人會故意犯錯,但只要是人,就很可能犯錯。(當然包括我)
可以的話,還是看原文比較好。雖然較吃力,但至少不會被誤導而不自知。
見 http://msdn.microsoft.com/zh-tw/library/system.windows.threading.dispatcherframe.aspx
execution (執行) 怎麼會翻譯成例外(exception) 呢?機器翻譯時不會翻錯字,這明顯地不是機器翻譯的,而是人去翻譯的。
沒有人會故意犯錯,但只要是人,就很可能犯錯。(當然包括我)
可以的話,還是看原文比較好。雖然較吃力,但至少不會被誤導而不自知。
最近在使用 WCF Data Services 時,WCF Data Services Client library 使用 DELETE HttpMethod 時,發生了 HTTP Error 405.0 - Method Not Allowed 的錯誤。
The page you are looking for cannot be displayed because an invalid method (HTTP verb) is being used.
經過不少的測試,也試過移除IIS 7 的 WebDAV module,都不成功。最簡單的方法,是在 Web.Config 中增加下面的設定。感謝 IIS 7。
<system.webServer> <validation validateIntegratedModeConfiguration="false" /> <modules> <remove name="WebDAVModule" /> </modules> <handlers> <remove name="WebDAV" /> </handlers> </system.webServer>
近來幾乎所有的 Middle Tier 的功能,微軟都是使用 IIS 來作 Host,最有名的就是WCF。如果要建置跨平台的解決方案,使用 xml + Http 幾乎是不二人選,binary 的 protocal 就把它忘了吧。
然而, xml + http 為人最為垢病的地方,就是它實在痴肥。為了讓它減肥,我不得已來 study 如何在 IIS 7 上壓縮網頁的輸出。
如下圖,我呼叫叫了一個 WebService,回傳的是 xml,但大小竟然是 1.5 MB!!這叫我如何能接受?
說實話,我已在 IIS 6 上實作過了。IIS 6 的過程實在不人道,我也不想 POST 到部落格上。而 IIS 7 就簡單許多。
首先,要了解的是 IIS 7 預設就打開了靜態內容的壓縮。不像 IIS 6預設都不壓縮。這大概與 IIS 壓縮的成熟度有關吧。
打開 IIS 7, 點到 Compression 的功能,右方出現一排字「The dynamic content compression module is not installed」,意思就是沒有安裝 dynamic content compression 這一個 module。
使用 Programs and Features,執行左方 Menu 的 Turn Windows features on or off,並勾選「Dynamic Content Compression」,按OK建進行安裝。
安裝完成後,再到 IIS 上執行Compress 的設定。check 一下,果然設定成功了。
只有安裝 dynamic content compression 模組是不夠的。IIS 此時尚不知道要對什麼動態內容作壓縮,接下來設定的就是:「告訴 IIS 什麼樣的內容要作動態壓縮」
在 IIS 上,點選 machine 名稱,執行「Configuration Editor」。
選 Section : system.webServer/httpCompression,並調整「dynamicTypes」
按右方 Actions Pane 的 Add 連結,並輸入 application/atom+xml
記得完成後,要按右上的 Apply 鍵完成設定。
最後,還要重新起動 IIS
再使用Fiddler 測試一下相同的網頁。Oh, My God, 1.5MB的內容壓縮過後只剩 149 KB,壓縮成原來的 10% ,省下的頻寬實在可觀。
繼上次的 TFS 建置:Coded UI 自動測試 問題後,好久好久我都沒再碰 TFS 的 Build 設定了。
這次,目的在建立 Web 的自動部署。
這次的環境較為複雜。有開發機,TFS Server,Build Server,Test WebServer.
希望可以達成的需求:在開發機上要求一個 Build後,TFS Server 向 Build Server 要求啟動一個 Build。Build Server 完成 Compile 後,將 Web Application 自動部署到 Test WebServer。
過程還有些漫長,最大的原因還是「太久遠的記憶」是不可靠的。下面是我試出來的結果。
在 MSBuild Arguments 我設定如下
/p:DeployOnBuild=True /p:DeployTarget=MsDeployPublish /p:MSDeployPublishMethod=RemoteAgent /p:CreatePackageOnPublish=True /p:DeployIisAppPath="Default Web Site/YourApp" /p:MsDeployServiceUrl=http://172.199.199.199/MsDeployAgentService /p:username=administrator /p:password=adminpassword
Build Server 上,必須安裝了 Visual Studio 2010。我試的結果,不裝,就不會自動部署。我不知道到底我錯過了什麼環結,雖然設定了上述的 MSBuild Arguments,但就是不跑 Deploy。
安裝時,我選了 c# 與Visual Web Developer。理論上只需安裝 Visual Web Developer即可,但我不想再浪費時間試了。
另外,在 Visual Studio 2010 Web Application 的專案屬性上,也有一些玄機。如果有勾選「Include IIS settings as configured in IIS」或「Include application pool settings used by this Web project」的話,在 Build Server 就要安裝 IIS 並且有相同的設定。因為當 Build Server 要打包 package 時,需要讀IIS的設定。讀不到設定就會出現下面的錯誤訊息。
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets (1657): "MapUriToIisWebServer" 工作發生未預期的失敗。 System.Runtime.InteropServices.COMException (0x80005000): 未知的錯誤 (0x80005000)
此時的我,顧不得完美了,先不要勾選這兩個選項了。
1 在待部署的 Web Server 上,必須安裝 Web Deployment Tool。安裝時,必須注意要選「完整」安裝。
2 安裝完畢後,需要在服務中啟動 Web Development Agent Service
3 Build 執行後出現下面的錯誤
Web deployment task failed.((2011/6/2 下午 05:14:42) An error occurred when the request was processed on the remote computer.) (2011/6/2 下午 05:14:42) An error occurred when the request was processed on the remote computer. The application pool that you are trying to use has the 'managedRuntimeVersion' property set to 'v2.0'. This application requires 'v4.0'.
由於我沒有選擇要打包 IIS 的設定,部署後的應用程式是下 Default Web Site 下。Default Web Site 預設是.net framework v2.0, MSDeploy 在建立 application 時會預設同上一層的 application pool。
我的解法是直接將上一層的 Default Web Site 改用 v4.0 的 application pool。
上述設定,一定還有調整優化的空間。之後有空再寫 blog好了。
雖然很麻煩,但想到之後不必再手動部署測試環境時,心裡也就舒坦了許多。
今天早上客戶寄來一封資安檢測結果,說我們維護的Web系統有漏洞。
弱點大意是:Web Server 提供了 PUT, TRACE, DELETE, CONNECT 的 Http Method. 應該關閉。
並且把這項缺失列為中等風險,寫的很厲害的樣子。「PUT method 允許用戶端上傳檔案至伺服器, DELETE method 允許用戶端將伺服器的檔案刪除. 將允許遠端攻擊者可任意上傳檔案至伺服器而置換網頁, 若攻擊者上傳惡意程式到具有執行權限的目錄, 將可達到更大的破壞.」
記得我們沒有開 WebDAV 啊!為什麼寫的這麼離譜?使用 Fiddler 查一下吧!
使用 Fiddler 的 Request Builder 查開發機 IIS
再選到 Inspectors,看查詢的 Request 及 Response (結果)
OPTIONS 會列出該 Web Server 可使用的 Http Method.
結果列出來,只有一項 TRACE 是有爭議的。根據 RFC 2616 指出,這是用來 Debug 用的 Method,可能揭露出不必要的資訊。因此會被列為風險。在 Apache 上更可能被偷取 cookie。
為什麼在IIS 上 TRACE 預設是可以使用的呢?再使用 Fiddler,這次使用 TRACE 查一下吧。
這次的結果是 HTTP/1.1 501 Not Implemented (未實作)。HttpStatus 500 以上代表伺服器錯誤。
雖然有開放 TRACE 這個 Method,但一律回未實作。這妙吧。
因此,沒有漏洞。
再使用 DELETE 查一下。結果是 405 Not allowed(不允許)。這證明 IIS 上的WebDAV 果然沒有開啟。
一看到資安檢測結果時,雖然只有這一項目,還是心裡不舒服。
看來該資安廠商是使用工具掃出來的結果。雖然只有一個 TRACE 看來符合,但把整個 PUT, DELETE, TRACE, CONNECT 全部列上去,看來比較有「價值」。
另外, IIS 為什麼要列為可用的Method,然後再回應 501 未實作呢?這裡就不深究原因了。
NuGet 也可以直接安裝 Enterprise Library 了。
舉例來說,之前在使用 Enterprise Library Exception Handling Application Block 時,需要在專案上加入下列參考
Microsoft.Practices.EnterpriseLibrary.Common
Microsoft.Practices.EnterpriseLibrary.ExceptionHandling
沒有經驗的人,很難一次引用正確。
Add Library Package Reference
安裝指定的 package
完成!還比想像中多了一些 dll,這些 unity 在用的 dll,什麼時候會用到我也不知道。
可惜的是,引用 package 並不會直接產生 .config 的設定。原因很簡單,它不知道我們要設定些什麼。
Enterprise Library 的設定太靈活了,要設定的話,還是乖乖地使用 Enterprise Library Configuration Editor 來設定吧。
在WPF 中如何一次對所有的 UserControl 作樣式設定呢?
在 WPF 中,要對同一個 Control 作預設的樣式設定很簡單。只需要在 App.xaml 中設定即可。
App.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="UserControl">
<Setter Property="Background" Value="Gray" />
</Style>
</Application.Resources>
</Application>
在 Visual Studio 中,可以在 designer 看到 usercontrol 的樣式套用了指定的樣式,看起來是可以的樣子哦!(當然沒這麼簡單,不然就不用寫這一篇了)
執行起來畫面就是沒有套用到。
程式的部份,請看附件的 WpfApplicatioin1 這個專案。
不信邪的我,稍稍改動了一下,讓樣式直接指定 UserControl1。這樣就可以套用樣式了。
<Application x:Class="WpfApplication2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="{x:Type local:UserControl1}">
<Setter Property="Background" Value="Gray" />
</Style>
</Application.Resources>
</Application>
這樣子只能套用到指定的 UserControl1,而非所有的樣式。原因是:樣式雖然可以像「繼承」樣子套用到指定的 Type,但不是繼承出來的 Type 都可以套用父類別的樣式。
程式的部份,請看附件的 WpfApplicatioin2 這個專案
這一版,自已加上了一個自訂的 MyUserControl 並繼承自 UserControl。之後,所有的 UserControl 都改繼承自訂的 MyUserControl。
在 App.xaml 中,樣式使用 BaseOn 這個關鍵。
<Application x:Class="WpfApplication3.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="UserControl" x:Key="baseStyle">
<Setter Property="Background" Value="Gray" />
</Style>
<Style TargetType="{x:Type local:MyUserControl}" BasedOn="{StaticResource baseStyle}" />
</Application.Resources>
</Application>
滿心歡喜地以為這樣萬事 OK 了,結果還是失敗。使用 Snoop 來查一下,Style 並沒有值。
程式的部份,請看附件的 WpfApplicatioin3 這個專案
不知道這是不是 bug。結果還是動用了 code behind 來解決事情。
public class MyUserControl : UserControl
{
public MyUserControl()
{
this.Style = this.FindResource("baseStyle") as Style;
}
}
使用 Snoop 來看,終於有套用到 style 了
程式的部份,請看附件的 WpfApplicatioin4 這個專案
這是 WPF 4 的 bug 嗎?不知道。只知道浪費了2小時的時間。