2010年10月17日 星期日

使用WindDBG附加程序除錯Silverlight應用程式

 

使用的程式碼如下:

  1: private void MyButton_Click(object sender, RoutedEventArgs e)
  2: {
  3:     try
  4:     {
  5: 	    throw new Exception("Test exception");
  6:     }
  7:     catch
  8:     {
  9:     }
 10:     Thread.Sleep(25000);
 11:     MyButton.Content = "Pushed";
 12: } 

1. 首先要知道正在執行的應用程式ProcessID,這邊我使用Process Explorer這一套軟體來抓。


image


image 


2. 進入WinDBG,打開[File]->[Attach to a Process…],選取剛剛找到的ProcessID。


image


3. 載入正確的WinDBG Extension DLL – SOS.dll,讓我們可以看到.NET Framework的Managed 程式碼。


(據測試的結果,本步驟可省略,但用!eeversion.chain確認一下較好)


可以用Everything來看一下有哪些SOS.dll


image


看一下目前的執行期環境,我們要挑一個和目前執行期環境相同版本的SOS.dll。


0:022> lm v m *clr*  <== List Loaded Modules(v = verbose;m Pattern )
start    end        module name
63450000 637b9000   coreclr    (deferred)            
    Image path: c:\Program Files\Microsoft Silverlight\4.0.50917.0\coreclr.dll
    Image name: coreclr.dll
    Timestamp:        Fri Sep 17 12:06:19 2010 (4C92E93B)
    CheckSum:         00361079
    ImageSize:        00369000
    File version:     4.0.50917.0
    Product version:  4.0.50917.0
    File flags:       0 (Mask 3F)
    File OS:          4 Unknown Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft® Silverlight
    InternalName:     coreclr.dll
    OriginalFilename: coreclr.dll
    ProductVersion:   4.0.50917.0
    FileVersion:      4.0.50917.0 (SL_V4_SVC.050917-0000)
    FileDescription:  Microsoft .NET Runtime Common Language Runtime - WorkStation
    LegalCopyright:   © Microsoft Corporation.  All rights reserved.
    Comments:         Flavor=Retail


也可以使用!eeversion指令。


0:028> !eeversion ==> (顯示 Common Language Runtime 版本)
4.0.50917.0 retail
Workstation mode
SOS Version: 4.0.50917.0 retail build


0:011> .reload ==> (Reload Module)
Reloading current modules
................................................................
............................................................
0:011> .load C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll ==>(Load Extension DLL)


檢查Extension DLL是否已經正確載入


0:011> .chain ==>(List Debugger Extensions)
Extension DLL search Path:
    C:\Program Files\Debugging Tools for Windows (x86)\WINXP;C:\Program Files\Debugging Tools for Windows (x86)\winext;C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade;C:\Program Files\Debugging Tools for Windows (x86)\pri;C:\Program Files\Debugging Tools for Windows (x86);C:\Program Files\Debugging Tools for Windows (x86)\winext\arcade(...省略)
Extension DLL chain:
    C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos: image 4.0.50917.0, API 1.0.0, built Fri Sep 17 12:08:16 2010
        [path: C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll]
    C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll: image 4.0.50917.0, API 1.0.0, built Fri Sep 17 12:08:16 2010
        [path: C:\Program Files\Microsoft Silverlight\4.0.50917.0\sos.dll]
    dbghelp: image 6.12.0002.633, API 6.1.6, built Tue Feb 02 04:08:26 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\dbghelp.dll]
    ext: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:31 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\winext\ext.dll]
    exts: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:24 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\WINXP\exts.dll]
    uext: image 6.12.0002.633, API 1.0.0, built Tue Feb 02 04:08:23 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\winext\uext.dll]
    ntsdexts: image 6.1.7650.0, API 1.0.0, built Tue Feb 02 04:08:08 2010
        [path: C:\Program Files\Debugging Tools for Windows (x86)\WINXP\ntsdexts.dll]


4. 列出Internet Explorer裡面的執行序,找出應用程式使用的ThreadID和他的內容。


0:011> ~* e !clrstack ==>(~ = 執行序; * = 全部; e = 執行; !clrstack = 提供 Managed 程式碼的堆疊追蹤)
OS Thread Id: 0x7ac (0)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
(...省略)
OS Thread Id: 0x163c (4)
Child SP IP       Call Site
020ed848 77b164f4 [HelperMethodFrame: 020ed848] System.Threading.Thread.SleepInternal(Int32)
020ed888 62a68e05 System.Threading.Thread.Sleep(Int32)
020ed88c 041e042d
SilverlightApplication1.MainPage.MyButton_Click(System.Object, System.Windows.RoutedEventArgs)
020ed8c4 632a0b81 System.Windows.Controls.Primitives.ButtonBase.OnClick()
020ed8d8 632f9d24 System.Windows.Controls.Button.OnClick()
020ed8e4 632a058e System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs)
020ed8f4 63262e01 System.Windows.Controls.Control.OnMouseLeftButtonUp(System.Windows.Controls.Control, System.EventArgs)
020ed904 63260f44 MS.Internal.JoltHelper.FireEvent(IntPtr, IntPtr, Int32, Int32, System.String)
020ed948 632e702f DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int32, Int32, Int32, Int32, IntPtr)
020eda24 071c6dbc [ContextTransitionFrame: 020eda24]
OS Thread Id: 0xe10 (5)
Unable to walk the managed stack. The current thread is likely not a
managed thread. You can run !threads to get a list of managed threads in
the process
(...省略)


5. 列出Exception的記憶體回收堆積 (Heap) 資訊,取得最近的Method Table物件(這裡是指Exception物件)。


0:011> !dumpheap -type Exception ==>(列出記憶體回收堆積; –type 只會列出相同型別與子型別的物件)
Address       MT     Size
078e1024 62c52b94       80    
078e1074 62c5b580       80    
078e10c4 62c5b5c8       80    
078e1114 62c5b658       80    
078e1164 62c5da48       80    
078e11b4 62c5da48       80    
078e4c24 62c33358       32    
078eb200 633533ac       32    
078eb220 633782a0       32    
078fac6c 6334a330       32    
0791f8b4 62c52b94       80    
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
633782a0        1           32 MS.Internal.Error+GetExceptionTextDelegate
633533ac        1           32 MS.Internal.Error+ClearExceptionDelegate
6334a330        1           32 System.EventHandler`1[[System.Windows.ApplicationUnhandledExceptionEventArgs, System.Windows]]
62c33358        1           32 System.UnhandledExceptionEventHandler
62c5b658        1           80 System.ExecutionEngineException
62c5b5c8        1           80 System.StackOverflowException
62c5b580        1           80 System.OutOfMemoryException
62c5da48        2          160 System.Threading.ThreadAbortException
62c52b94        2          160 System.Exception
Total 11 objects


6. 列出參考到這個Method Table物件(這裡是指Exception物件)的位址


0:011> !dumpheap -mt 62c52b94 ==> (列出記憶體回收堆積; –mt 列出對應到 MethodTable 結構之物件)       
Address       MT     Size
078e1024 62c52b94       80    
0791f8b4 62c52b94       80    
total 0 objects
Statistics:
      MT    Count    TotalSize Class Name
62c52b94        2          160 System.Exception
Total 2 objects


7. 列出物件內容,這邊是Exception,所以使用!pe指令。


0:011> !pe 0791f8b4 ==>(print exception)
Exception object: 0791f8b4
Exception type:   System.Exception
Message:          Test exception
InnerException:   <none>
StackTrace (generated):
    SP       IP       Function
    020ED88C 041E0417 UNKNOWN!SilverlightApplication1.MainPage.MyButton_Click(System.Object, System.Windows.RoutedEventArgs)+0x57


StackTraceString: <none>
HResult: 80131500
The current thread is unmanaged


結論:


這個例子體現了尋找錯誤必須要由大往小,由粗往細的過程。


由Process到Thread: ProcessID => ~* e !clrstack


由物件到函式表:!dumpheap –type xxx => !dumpheap –mt xxx


參考資料:


2010年10月14日 星期四

讓Visio 2007支援Robustness Diagram(穩健圖、魯棒圖)的三種元素

  1. http://www.softwarestencils.com/uml/index.html#Visio2007下載範本
  2. 設定Vision的檔案路徑
    1. 選擇[工具]=>[選項]=>[進階]=>[檔案路徑] image
    2. 設定[我的圖形(M)][和範本(T)]image
  3. 將下載的檔案放在"C:\Users\<使用者名稱>\我的圖形\軟體與資料庫"下image
  4. 在[檔案]=>[新增]=>[快速入門]中可以見到新增的範本了。

image

2010年10月9日 星期六

Web 測試中的奇怪網址

在Vistual Studio 的Web 測試,錄製時產生了大量的奇怪網址:

https://urs.microsoft.com/urs.asmx?MSURS-Client-Key=...&MSURS-Patented-Lock=...

經過一番網路上的搜尋與自己的測試後,發現原來這個網址是微軟的"Smart Screen篩選"所使用。

在Web 測試中當然要把它關閉,不然除了增加管理與使用的困難,也增加了不必要的網路流量。

怎麼樣關閉Smart Screen篩選功能呢? 有以下三種方法(IE8):

  • (全域)[工具]—>[Smart Screen 篩選] –>[關閉Smart Screen 篩選...]—>選擇 關閉Smart Screen 篩選

image

  • (全域)[工具]—>[網際網路選項]—>[進階]—>關閉 啟用記憶體保護以協助避免網路攻擊

image

  • (區域)[工具]—>[安全性]—>[信任的網站/自訂等級]—>停用 Smart Screen 篩選

(記得要選擇可以信任的網站嘿~~)

image

安全性設定 - 信任的網站區域

參考資料:

ICONIX 開發方法

核心方法很簡單,也符合一般的流程,最重要的是,個人認為可以補足UML開發過程中的不足。

bridgingthechasm-sm

請注意其中的Robustness Diagram。

iconixprocess-lg

較詳細的圖片解說:

iconixprocessroadmap-lg

登入 Robustness Diagram(台:穩健圖、陸:魯棒圖)

登入頁魯棒圖

註冊 Robustness Diagram

註冊魯棒圖

 

參考資料:

深入偵錯程式碼

在程式碼偵錯時,可以顯示.Net Framework的原始程式碼,不但可以了解控制項或其他程序的流程,也可以對錯誤的原因有更進一步的認識,何樂而不為。

1. [啟用.NET Framework 來源步進]時,會取消Just My Code,請讓它取消。Just My Code的意思是偵錯只限定於自己寫的程式碼,現在我們要深入MS所提供的程式碼,所以要取消他。

0001-747x456_thumb1

2. 設定[符號檔(.pdf)位置(F):]與[從符號伺服器將符號快去至此目錄(C):]。本機位置請設定為相同。遠端位置請設定為 http://msdl.microsoft.com/download/symbols

 0003-747x456_thumb1

3. 按[確定]之後,會從遠端下載專案所需要的符號檔。符號檔以命名空間為一個單位,除非專案使用到的命名空間不同,否則這個步驟只會執行一次。

0002-747x456_thumb1

參考資料:

  1. 使用 Microsoft 符號伺服器取得偵錯符號檔
  2. Download Windows Symbol Packages

ASP.NET 狀態管理優缺點比較與建議事項

用戶端狀態管理選項

 

優點

缺點

檢視狀態 不需要伺服器資源
實作簡單
增強安全性功能
效能考量
裝置限制
潛在安全性風險
控制項狀態 不需要伺服器資源
可靠性
全面性
需要部分程式設計工作
隱藏欄位 不需要伺服器資源
廣泛支援
簡單實作
潛在安全性風險
簡單的儲存架構
效能考量
儲存限制
Cookie 可設定的到期規則
不需要伺服器資源
簡化
資料保存性
大小限制
使用者設定的拒絕
潛在安全性風險
查詢字串 不需要伺服器資源
廣泛支援
簡單實作
潛在安全性風險
容量限制

 

用戶端方法狀態管理摘要

狀態管理選項

建議的使用方式

檢視狀態 當您需要儲存網頁將回傳本身的少量資訊時使用。使用 ViewState 屬性會提供基本安全性功能。
控制項狀態 當您需要儲存伺服器來回往返之間控制的少量狀態資訊時使用。
隱藏欄位 您需要儲存網頁將回傳本身或其他網頁的少量資訊,而且不考量安全性的問題時使用。
(注意事項:您只能在送至伺服器的網頁上使用隱藏欄位。)
Cookie 當您需要在用戶端上儲存少量資訊,而且不考量安全性的問題時使用。
查詢字串 當您要將少量資訊從一網頁傳輸至另一網頁,而且不考量安全性的問題時使用。
(注意事項:只有在要求相同網頁,或透過連結要求另一網頁時,才能使用查詢字串。)

 

伺服器端狀態管理選項

  優點 缺點
應用程式狀態 實作簡單
應用程式範圍
應用程式範圍
有限的資料耐久性
資源需求
工作階段狀態 實作簡單
工作階段特定事件
資料保存性
平台延展性
Cookieless 支援
擴充性
效能考量
設定檔屬性 資料保存性
平台延展性
擴充性
效能考量
額外設定的需求
資料維護
資料庫支援 安全性
儲存空間
資料保存性
強固性和資料完整性
協助工具
廣泛支援
複雜度
效能考量

 

伺服器端方法狀態管理摘要

狀態管理選項

建議的使用方式

應用程式狀態 當您正在儲存變更頻率低、由許多使用者使用的全域資訊、而且不考量安全性的問題時使用。
請勿在應用程式狀態中儲存大量資訊。
工作階段狀態 當您要儲存個別工作階段專用且存留期短暫的資訊,同時必須顧慮安全性時使用。
請勿在工作階段狀態中儲存大量資訊。
請注意,工作階段狀態物件會在您應用程式中每個工作階段的存留期期間建立並維護。
在擁有許多使用者的應用程式中,這可能會佔用大量的伺服器資源並且影響延展性。
設定檔屬性 當您儲存在工作階段過期後需要保存的使用者特定資訊,並且在後續造訪應用程式需要再度擷取時使用。
資料庫支援 當您儲存大量資訊、管理交易、或是資料必須不受應用程式和工作階段重新啟動的影響時使用。
資料採擷是重要的,而且也必須顧慮安全性。

 

參考資料: ASP.NET 狀態管理建議事項

伺服器控制項與子屬性的視圖狀態比較

















public class BookNew : WebControl
public class StateManagedAuthor : IStateManager
     
private StateManagedAuthor authorValue;

[DesignerSerializationVisibility(
DesignerSerializationVisibility.Content),
PersistenceMode(PersistenceMode.InnerProperty)]
public virtual StateManagedAuthor Author
{
get
{
if (authorValue == null)
{
authorValue = new StateManagedAuthor();

if (IsTrackingViewState)
{
((IStateManager)authorValue).TrackViewState();
}
}
return authorValue;
}
}
private bool _isTrackingViewState;
private StateBag _viewState;

protected virtual StateBag ViewState
{
get
{
if (_viewState == null)
{
_viewState = new StateBag(false);

if (_isTrackingViewState)
{
((IStateManager)_viewState).TrackViewState();
}
}
return _viewState;
}
}
bool IStateManager.IsTrackingViewState
{
get
{
return _isTrackingViewState;
}
}
internal void SetDirty()
{
_viewState.SetDirty(true);
}
protected override void LoadViewState(object savedState)
{
Pair p = savedState as Pair;
if (p != null)
{
base.LoadViewState(p.First);
((IStateManager)Author).LoadViewState(p.Second);
return;
}
base.LoadViewState(savedState);
}
void IStateManager.LoadViewState(object savedState)
{
if (savedState != null)
{
((IStateManager)ViewState).LoadViewState(savedState);
}
}

protected override object SaveViewState()
{
object baseState = base.SaveViewState();
object thisState = null;

if (authorValue != null)
{
thisState = ((IStateManager)authorValue).SaveViewState();
}

if (thisState != null)
{
return new Pair(baseState, thisState);
}
else
{
return baseState;
}
}
object IStateManager.SaveViewState()
{
object savedState = null;

if (_viewState != null)
{
savedState =((IStateManager)_viewState).SaveViewState();
}
return savedState;
}
protected override void TrackViewState()
{
if (authorValue != null)
{
((IStateManager)authorValue).TrackViewState();
}
base.TrackViewState();
}
void IStateManager.TrackViewState()
{
_isTrackingViewState = true;

if (_viewState != null)
{
((IStateManager)_viewState).TrackViewState();
}
}
public override string ToString()
{
return ToString(CultureInfo.InvariantCulture);
}
public string ToString(CultureInfo culture)
{
return TypeDescriptor.GetConverter(
GetType()).ConvertToString(null, culture, this);
}

參考資料:


資料繫結(數據綁定、DataBind)概略流程

DataBind_thumb3

補充:DataSourceControl 類別

您可以把資料來源控制項想像成 DataSourceControl 物件及其相關資料清單 (稱為資料來源檢視) 的組合。每份資料清單都由 DataSourceView 物件表示。因為基礎資料儲存區包含一個或多個資料清單,所以 DataSourceControl 永遠與一個或多個具名 DataSourceView 物件產生關聯。IDataSource 介面會定義所有資料來源控制項與資料來源檢視互動時使用的方法:GetViewNames 方法是用來列舉目前與資料來源控制項關聯的資料來源檢視,而 GetView 方法則是用來依名稱擷取特定資料來源檢視執行個體。

您也可以把資料來源控制項想像成呼叫端用來存取資料的兩個不同介面。當頁面開發人員在開發 Web Form 網頁時,會直接與 DataSourceControl 類別這個介面互動,而資料繫結控制項和資料繫結控制項作者則會與 DataSourceView 類別這個介面互動。因為只有在執行階段才可使用 DataSourceView 物件,所以資料來源控制項或資料來源檢視的任何保存狀態,都必須由資料來源控制項直接公開。

簡單屬性與複雜屬性

簡單屬性

複雜屬性

1_thumb1[1]
在設計時期屬性介面中只有單一一項可設定的項目
1_thumb1
在設計時其屬性介面中項目的值由子項目決定,項目旁邊有一個小箭頭,表示項目可以展開
2_thumb10
項目屬於控制項的主要元素之一
2_thumb1 項目屬於控制項的子項目,通常以縮排方式顯示
使用ViewState["項目"]來使用ViewState機制 繼承IStateManager來使用ViewState機制
屬於.NET支援的實質型別,不需要TypeConverter 繼承ExpandableObjectConverter來使用TypeConverter機制

 

參考資料:

瀏覽器如何解釋 WebParts 中的 CallBack?

同樣的Server Code,兩家瀏覽器的內容竟然不一樣,來看一下,到底差多少?

Mozilla FireFox

<a 
	onclick="WebForm_DoCallback('ctl00$MainContent$WebPartManager1$VerbWebPart1','RefreshAjax',function(result, controlId){ document.getElementById(controlId).innerHTML = result;},'MainContent_WebPartManager1_VerbWebPart1',null,false);"
	title="Refresh the data2"
	href="javascript:__doPostBack('','')">
	<img title="Refresh the data2" src="/WebResource.axd?d=b0mWHY8S-KhFmq2i0Ng64vjCr7jtn6d1PqDQASYhlciLFSkUesn25v94jo0Hl8v3SSeikIor9zVbWy0TKuelog2&amp;t=634156742020331178"
	alt="Refresh2">
</a>

Internet Explorer

<a title="Refresh the data2"
   href="javascript:void(0)" 
   onclick="document.body.__wpm.Execute(&#39;WebForm_DoCallback(\&#39;ctl00$MainContent$WebPartManager1$VerbWebPart1\&#39;,\&#39;RefreshAjax\&#39;,function(result, controlId){ document.getElementById(controlId).innerHTML = result;},\&#39;MainContent_WebPartManager1_VerbWebPart1\&#39;,null,false);&#39;)" class="menuItem">
   <img src="/WebResource.axd?d=b0mWHY8S-KhFmq2i0Ng64vjCr7jtn6d1PqDQASYhlciLFSkUesn25v94jo0Hl8v3SSeikIor9zVbWy0TKuelog2&amp;t=634156681268366365"
   alt="Refresh the data2"
   width="16"
   height="16"
   style="border-style:none;vertical-align:middle;" />
&nbsp;Refresh2&nbsp;
</a>

在FireFox中,多送了一次PostBack,所以CallBack的結果被洗掉了。


解決方式:在Web Part页面上添加AJAX

WebResource 測試

請參考:建置動作(檔案屬性)

   ASP.NET 2.0 中的 Web Resource

    使用 ASP.NET 2.0 中的 Web 資源

  1: using System;
  2: using System.Collections.Generic;
  3: using System.ComponentModel;
  4: using System.Linq;
  5: using System.Text;
  6: using System.Web;
  7: using System.Web.UI;
  8: using System.Web.UI.WebControls;
  9: using System.Web.UI.WebControls.WebParts;
 10: 
 11: [assembly: WebResource("WebPartLibrary.Images.refresh.gif", "image/gif")]
 12: 
 13: namespace WebPartLibrary
 14: {
 15:     public class VerbWebPart : WebPart
 16:     {
 17:         public override WebPartVerbCollection Verbs
 18:         {
 19:             get
 20:             {
 21:                 string imgUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "WebPartLibrary.Images.refresh.gif");
 22: 
 23:                 List<WebPartVerb> menu = new List<WebPartVerb>();
 24:                 WebPartVerb menuItem = new WebPartVerb("Refresh",
 25:                                                         RefreshTest,
 26:                                                         "return confirm('Sure you send?')");
 27:                 menuItem.Text = "Refresh";
 28:                 menuItem.Description = "Refresh the data";
 29:                 menuItem.ImageUrl = imgUrl;
 30:                 menu.Add(menuItem);
 31: 
 32:                 return new WebPartVerbCollection(menu);
 33:                 //return base.Verbs;
 34:             }
 35:         }
 36: 
 37:         void RefreshTest(object sender, WebPartEventArgs e){ 
 38:         }
 39: 
 40:         private string _title = "This is a test part";
 41:         [Personalizable(true)]
 42:         [WebBrowsable(true)]
 43:         [WebDisplayName("Title")]
 44:         public override string Title
 45:         {
 46:             get { return _title; }
 47:             set { _title = value;}
 48:         }
 49: 
 50:         protected override void RenderContents(HtmlTextWriter output)
 51:         {
 52:             output.Write("Hello World!!");
 53:         }
 54:     }
 55: }

 


0001-1440x878_thumb4


產生的Code

<a onclick="return confirm('Sure you send?');"
   title="Refresh the data"
   href="javascript:__doPostBack('ctl00$MainContent$WebPartZone1','partverb:Refresh:VerbWebPart1')">
   <img title="Refresh the data" 
        src="/WebResource.axd?d=b0mWHY8S-KhFmq2i0Ng64vjCr7jtn6d1PqDQASYhlciLFSkUesn25v94jo0Hl8v3SSeikIor9zVbWy0TKuelog2&amp;t=634156163432539640"
		alt="Refresh">
</a>

Page.ClientScript.RegisterOnSubmitStatement測試

請參考HOW TO:以動態方式將用戶端指令碼加入至 ASP.NET Web 網頁

WebForm1.aspx

  1: <html xmlns="http://www.w3.org/1999/xhtml">
  2: <head runat="server">
  3:     <title></title>
  4:     <script type="text/javascript" src="script/check.js"></script>
  5: </head>
  6: <body>
  7:     <form id="form1" runat="server">
  8:     <div>
  9:     <input type="submit" />
 10:     </div>
 11:     </form>
 12: </body>
 13: </html>

check.js

  1: function check1() {
  2:     return confirm('submit this page?');
  3: }

WebForm1.aspx.cs

  1:         protected void Page_Load(object sender, EventArgs e)
  2:         {
  3:             Page.ClientScript.RegisterOnSubmitStatement(this.GetType(),
  4:                 "SubmitState1",
  5:                 "check1();");
  6:         }
  7: 

Html Source Code

  1: <html xmlns="http://www.w3.org/1999/xhtml">
  2: <head><title>
  3: 
  4: </title>
  5:     <script type="text/javascript" src="script/check.js"></script>
  6: </head>
  7: <body>
  8:     <form method="post" action="WebForm1.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">
  9: 
 10: <script type="text/javascript">
 11: //<![CDATA[
 12: function WebForm_OnSubmit() {
 13: check1();
 14: return true;
 15: }
 16: //]]>
 17: </script>
 18: 
 19:     <div>
 20:     <input type="submit" />
 21:     </div>
 22:     </form>
 23: </body>
 24: </html>
 25: 

除了以JS檔引入之外,也可以在.aspx.cs中直接使用JS Code。


WebForm1.aspx.cs

  1:         protected void Page_Load(object sender, EventArgs e)
  2:         {
  3:             string confirmScript = @"return confirm('submit this page?');";
  4: 
  5:             Page.ClientScript.RegisterOnSubmitStatement(this.GetType(),
  6:             "SubmitState1",
  7:             confirmScript);
  8:         }

系統分析師"好問題"

[寫給SA的UML/MDA實務手冊 邱郁惠著] 筆記,以另一種觀點整理

UC:

  1. 繪製企業UC:系統上線之後,可能會影響到哪幾條流程?
  2. 繪製企業參與者:什麼情況下會開始執行某流程,可有企業外部的人士會啟動或參與流程?
  3. 撰寫企業UC簡述:針對某一個企業UC,請用一兩句話簡單說明它是做什麼用的?

物件:

  1. 在執行這項工作時,你們會用到哪些專業概念?
  2. 你們在執行這項工作時,會需要用到哪些資料?

屬性:

  1. 物件需要記錄哪些屬性(Attribute)?
  2. 某物會記錄什麼資料呢?
  3. 某物可以提供我們哪些資料呢?
  4. 透過某物,可以讓我們查到哪些資料嗎?
  5. 探問屬性定義:可以請您(企業人員)用簡單的一、兩句話,解釋某屬性是什麼嗎?
  6. 判斷屬性的資料型態:可以請您舉個例子嗎?
  7. 判斷屬性的資料型態以及欄位大小:請問某屬性有範圍值嗎?
    • 數字型態:可被接受的數字,最大最小為何?
    • 字串型態:可被接受的字串,最長最短為何?
    • 列舉型態:預設的項目,有哪幾個?項目異動的頻率?
  8. 探問屬性的初始值:請問某數性有初始值嗎?
  9. 探問屬性的獲得方法:怎樣做才能夠得到某屬性值(Attribute Value)?
    • 鍵入值:請問誰會提供這項屬性值?
    • 查詢值:請問可以向哪裡查詢這項屬性值?
    • 計算值:請問計算公式為何?
    • 流水號或特定編碼:請問可有獨特的編碼方式?

操作:

  1. 物件可以提供哪些操作(Operations)?
  2. 某物可以做什麼用呢?
  3. 有了某物之後,我們可以拿它來做什麼事呢?
  4. 探問執行步驟:您(企業人員)通常都怎麼執行某操作的呢?可以告訴我,主要的執行步驟嗎?
  5. 探問資料的輸入及輸出:請告訴我這些執行步驟會需要使用到什麼資料?以及會產出什麼資料?
  6. 探問計算公式:請告訴我這些執行步驟會需要使用到計算公式嗎?
  7. 探問特殊限制:在執行某操作時,有沒有什麼重要的限制需要注意或遵守的?

有中文解釋的設計模式圖表

chatu_1

chatu_2

chatu_3

chatu_4

取自《設計模式之禪》試讀資料。

[系統分析] MDA(Model-Driven Architecture)開發程序

[寫給SA的UML/MDA實務手冊 邱郁惠著] 筆記

個人與邱郁惠有數面之緣,發現她寫的書比講課要清楚明白,希望她以後能多多分享她的經驗,大家也要對她的著作多多捧場唷。

MDA

CIM-1定義企業流程(企業UC模式)的產出,有下列兩項:

  1. 企業UC圖
  2. 企業UC簡述

CIM-2分析企業流程,在於切分工作項目,其準則如下:

  1. 依時間間隔切分工作項目
  2. 純人工/可資訊化的工作項目,分開
  3. 記錄系統上線之後的工作項目
  4. 每項工作只有一位負責人(真正執行該項工作的員工)

CIM-3定義系統範圍的產出,有下列兩項:

  1. 系統UC圖
  2. 系統UC簡述

系統分析師在定義系統UC時,可參考下列建議:

  • 每一個系統UC最好只有一個啟動者
  • 系統UC執行期間如果有連線其他系統,將它們列為支援者
  • 遇到定時啟動的系統UC,可以定義一個名為『定時啟動者(Timer)』的虛擬啟動者

系統分析師在繪製系統UC圖時,可以採用下列幾項常見做法:

  • 採用帶箭頭關係線,讓啟動者連線指向UC,UC連線指向支援者。這樣一來,從圖面上就可以明確分辨出啟動者與支援者。
  • 一個UC通常只有一個啟動者,不過可能出現多個支援者
  • 如果有多個啟動者的情況,常是切割成一人一例(One User, One Session)
  • 有時不同使用者都具有啟動UC的特性,建議在圖面上繪出最重要或最主要的啟動者,其餘啟動者紀錄在UC敘述裡,這樣可以降低圖面的複雜度

PIM-1:系統UC敘述

  1. UC基本資料
    • UC名稱
    • UC編號(ID)
    • UC簡述
    • UC圖
    • 系統:提供此UC的系統名稱
    • 參與者
    • 相關UC:包含(Include)關係與擴充(Extend)關係。有相同流程時,使用包含關係;有可選擇性過程時,使用擴充關係。
  2. 執行流程
    • 主要流程(Basic Flow)
    • 替代流程(Alternate Flows)
    • 例外流程(Exception Flows)
  3. 要件及規則
    • 啟動事件或條件(Triggers)
    • 執行前要件(Preconditions)
    • 成功時要件(Postconditions on Success)
    • 失敗時狀態(Status on Failure)
    • 企業規則(Business Rule)
  4. 相關文檔
    • UC敘述的歷史文本
    • UML圖
    • 參考畫面
    • 其他非UML文檔
  5. 其他事項
    • 優先性(Priority)
    • 循環等級(Iteration):替UC標示其細緻度或循環等級,方便開發人員經過多次循環的過程逐步定義出UC的細節。
    • 待解議題(Issues)
    • 基本假設(Assumptions)
    • 相關人員:將一個UC當成一個工作單元,加上相關人員的簽核之後,UC敘述文件就成了現成的工作單(Work Ticket)
    • 特殊需求(Special Requirements)

在進行PIM-1訪談時,針對每一個系統UC,系統分析師可以請企業人員協助回答下列問題,或者提供相關資料:

  • 條列出企業人員現行的執行步驟
  • 期望系統怎麼做,以改善現行作業的缺失
  • 提供相關的紙本表單或電子表單
  • 列出相關的企業規則和計算公式

PIM-2分析企業規則

企業規則:

  • 目的:企業透過一組規則(Busses Rules)來控制整體的運作,包括人員、流程、系統、概念的運作,接受制於企業規則。
  • 定義:企業領域中任何一項必須遵守的條件(Conditions)、限制(Constraints)或政策(Policies)都算是企業規則。

企業規則的分類:

  • 限制規則(Constraint Rules)
    • 刺激/反應規則(Stimulus/Response Rules):當某個重要的外界事件發生,而且物件如果恰好處於某種狀態下時,物件就會做出某種事先約定好的行為。
    • 操作規則(Operation Constraint Rules):用來保證操作會正確執行。通常又分為操作前規則及操作後規則。
    • 結構規則(Structure Constraints Rules):用來限制物件種類或結合關係必須永遠遵守規則。
  • 衍生規則(Deruvation Rules)
    • 推論規則(Inference Rules):指出某事實為真時,結局是可被推論得出。
    • 計算規則(Computation Rules):就是一般所謂的計算公式。

PIM-3定義靜態結構

系統分析師可以透過檢覈下列兩項要件,判斷是否採用結合關係:

  • 在企業領域的專業概念裡,兩種物件之間有一種固定不變且需要保存的靜態關係。
  • 在資訊化時,系統會用到這些靜態關係,而且必須將它們存到資料庫。

系統分析師可以透過檢覈下列兩項要件,判斷是否採用一般化關係:

  • 在企業領域的專業概念裡,特殊物件必須『是一種』(a kind of)一般物件。
  • 多種特殊物件裡,有部分通用的屬性與操作,也又部分獨有的屬性與操作。

系統分析師可以透過檢覈下列四項要件,判斷採用結合關係、聚合關係還是組合關係:

  1. 在企業領域的專業概念裡,兩種物件之間有一種固定不變且需要保存的靜態關係。(組合關係的要件)
  2. 在資訊化時,系統會用到這些靜態關係,而且必須將它們存到資料庫。(組合關係的要件,符合上述要件1~2,即可採用結合關係)
  3. 在企業領域的專業概念裡,兩種物件之間有Whole-Part的靜態關係。(聚合關係的要件,符合上述要件1~3,即可採用聚合關係)
  4. Part物件只能連結一個Whole物件,且Whole物件被註銷(Destory)時,Part物件必須一塊被註銷。(組合關係的要件,符合上述要件1~4,即可採用組合關係)

PIM-4:定義操作及方法

在建構PIM-4的循序圖時,系統分析師可以參考下列幾項建議:

  • 主要流程與其他流程分置於不同的循序圖中。千萬別在一張循序圖裡表達多條流程,避免造成圖面過於複雜,難以閱讀。
  • 扮演啟動者的參與者物件放至於循序圖最左方;扮演支援者的參與者物件放置於循序圖的最右方。訊息方向盡量由左指向右,符合橫式書寫與閱讀的習慣。
  • 私有操作只有物件自身可以呼叫。
  • 物件之間優先透過靜態關係傳送訊息,否則可於操作中建立暫時性的關係,以便傳送訊息。透過類別之間的結合關係,類別所產生之物件之間可以傳遞訊息。
  • 顯示訊息序號,有助於撰寫說明
  • 兩物件之間具有組合關係時,其他物件僅能看到Whole物件,不能直接使用Part物件。
  • 傳送物件,而非屬性,維持物件的封裝性
  • 物件封裝了屬性,以及操作之方法,僅對外透漏公開操作。在分析規劃物件的方法時,如果需要與其他物件互動,甚至是使用物件本身的屬性或操作,切記要嚴守下列三項要件:
    1. 不得直接提及物件的屬性
    2. 也不得假設物件的執行方法
    3. 僅能夠使用到物件的操作

系統分析師可參考下述步驟來繪製循序圖:

  1. 扮演啟動者的參與者物件放置於循序圖最左方;扮演支援者的參與者物件放置於物件的最右方。
  2. 針對系統UC敘述裡所記載的每項流程步驟,判斷執行時需要使用到哪些資料,且可指派擁有該資料的物件負責該項工作。
  3. 試著執行循序圖,以便調整流程,並且為操作加上參數。
  4. 把繪製循序圖時所找到的操作及屬性,回饋給類別圖。

Silverlight的應用程式與網站不同的地方

在建立新的Silverlight瀏覽應用程式時,必須要選擇使用ASP.NET Web 應用程式專案或是ASP.NET 網站。我們這邊來比較這兩者有什麼不同的地方。

0001-438x254

.sln ==> ASP.NET 網站 增加以下設定

  1: 	ProjectSection(WebsiteProperties) = preProject
  2: 		TargetFramework = "3.5"
  3: 		Debug.AspNetCompiler.VirtualPath = "/SilverlightWCFDemo.Web"
  4: 		Debug.AspNetCompiler.PhysicalPath = "SilverlightWCFDemo.Web\"
  5: 		Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\SilverlightWCFDemo.Web\"
  6: 		Debug.AspNetCompiler.Updateable = "true"
  7: 		Debug.AspNetCompiler.ForceOverwrite = "true"
  8: 		Debug.AspNetCompiler.FixedNames = "false"
  9: 		Debug.AspNetCompiler.Debug = "True"
 10: 		Release.AspNetCompiler.VirtualPath = "/SilverlightWCFDemo.Web"
 11: 		Release.AspNetCompiler.PhysicalPath = "SilverlightWCFDemo.Web\"
 12: 		Release.AspNetCompiler.TargetPath = "PrecompiledWeb\SilverlightWCFDemo.Web\"
 13: 		Release.AspNetCompiler.Updateable = "true"
 14: 		Release.AspNetCompiler.ForceOverwrite = "true"
 15: 		Release.AspNetCompiler.FixedNames = "false"
 16: 		Release.AspNetCompiler.Debug = "False"
 17: 		VWDPort = "24329"
 18: 		DefaultWebSiteLanguage = "Visual C#"
 19: 		ProjOutputReferences = "{15012D19-EC5F-4E9D-9C93-EF41083152E8}|ClientBin|false;"
 20: 	EndProjectSection

web.config ==> ASP.NET 網站 增加了vb 的設定

  1:     <system.codedom>
  2:       <compilers>
  3:         <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4"
  4:                   type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  5:           <providerOption name="CompilerVersion" value="v3.5"/>
  6:           <providerOption name="OptionInfer" value="true"/>
  7:           <providerOption name="WarnAsError" value="false"/>
  8:         </compiler>
  9:       </compilers>
 10:     </system.codedom>

Default.aspx ==> 網站用CodeFile;應用程式用CodeBehind,並配合Namespace使用


ASP.NET 網站

  1: <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

ASP.NET Web 應用程式專案

  1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SilverlightWCFDemo.Web._Default" %>

Default.aspx.cs


ASP.NET 網站

  1: public partial class _Default : System.Web.UI.Page 
  2: {
  3:     protected void Page_Load(object sender, EventArgs e)
  4:     {
  5: 
  6:     }
  7: }

ASP.NET Web 應用程式專案

  1: namespace SilverlightWCFDemo.Web
  2: {
  3:     public partial class _Default : System.Web.UI.Page
  4:     {
  5:         protected void Page_Load(object sender, EventArgs e)
  6:         {
  7: 
  8:         }
  9:     }
 10: }

結論:


建議以ASP.NET 網站來建置新的Silverlight網站,以獲得完整的設定描述,並運用ASP.NET Web 應用程式專案的繼承方式,以方便對網站做模組化應用。


如果使用MasterPage來建立網站,又沒有使用Namespace的繼承方式,那在使用使用者控制項(User Control)時,就不能夠繼承UserControl類別了。


參考資料: