進入 ASP.NET 世界 – 第 1 部分:應用程式規劃與設計

來源:互聯網
上載者:User
http://www.microsoft.com/china/MSDN/library/archives/library/DNAspp/html/aspnet-jumpinto-part1.asp
進入 ASP.NET 世界 - 第 1 部分:應用程式規劃與設計

Mike Amundsen

2003 年 8 月

適用於:
    Microsoft ASP.NET

摘要:瞭解如何規劃和設計 ASP.NET 應用程式。本文以一個知識庫 Web 應用程式為例,討論實際應用程式建立實踐中最常見的幾個因素。(本文包含一些指向英文網站的連結。)

目錄

簡介
規劃基本 ASP.NET 應用程式
定義應用程式體繫結構
安全規劃
完成設計文檔
小結並付諸行動

簡介


迎來到“進入 ASP.NET 世界”。在隨後的幾周或幾個月中,本系列文章將逐步詳細介紹如何使用 Microsoft ASP.NET 和
Microsoft Visual Studio .NET 來設計、實現和部署典型的 Web
應用程式,以探討實際應用程式建立實踐中最常見的幾個因素。我們不僅僅布置一些 Web Form,也不局限於只對後端資料庫進行一些資料繫結。資料繫結和
Web Form布局很重要,但是有許多其他問題也非常重要。

例如,無論採用何種目標平台或語言,所有經過良好編
碼的項目都包括一些基本的規劃步驟,例如目標聲明、使用者方案文檔,甚至用於標識解決方案的物理邊界和邏輯邊界的體繫結構文檔。此外,在解決方案生命週期的
早期就將安全規劃包含在內是一種非常好的習慣。這些內容與良好的資料庫模型、精心設計的中介軟體組件以及簡潔的使用者介面設計一起,可以確保您最終在生產中部
署的應用程式是安全的、可靠的,並且是方便使用的。

此時,一些讀者可能會認為本文屬於那些基調很高的文章,目
標定位在某些超大型企業級方案,而這種方案根本不適用於一般的小工廠、愛好者或個人開發團體。其實並不是這樣!即使只是建立您自己個人使用的基於
Web 的小型解決方案,從一開始就進行完善的規劃將有助於確保流程最終的輕鬆實現和部署。而且,並不是進階的程式員或 Web
開發人員才可以使用這些技術。無論您的技術水平如何,也無論您屬於哪類目標讀者,我相信您都會發現這一系列文章對您很有協助,它為您提供了豐富的資訊,而
且(請允許我這樣說)十分有趣。

我們將產生一個稱為 DotNetKB 的樣本知識庫 Web
應用程式,這個過程將貫穿整個系列文章。在作為第一篇文章的本文中,我們將介紹典型項目的設計階段,包括基本規劃、應用程式體繫結構和實現方案設計。學習
完本文後,您將已經準備好所有的文檔,並會迫不及待地希望開始建立解決方案。

預備工作非常簡單,我們跳過這部分內容,直接開始第一步“應用程式規劃”。

規劃基本 ASP.NET 應用程式

使
用 Visual Studio .NET 建立基於 Web 的 ASP.NET 應用程式的第一步是制定基本的應用程式規劃
(AP)。制定規劃不僅對於由多個開發人員建立的大型解決方案而言是必不可少的,而且即使對於最小的應用程式,一個完善的 AP 也是非常重要的。建立
AP
有助於您在開始編碼“之前”就能仔細考慮一些常見問題。這樣,您可以在應用程式生命週期的早期便完全瞭解挑戰和解決方案,而不是在完全陷入窘境之後才發現
問題。在《Software Project Survival Guide》一書中,作者 Steve McConnell 指出:在軟體項目後期糾正錯誤所花的成本與在早期階段發現並糾正這些錯誤所花的成本相比,前者可能是後者的 50 - 200 倍。


個完善的專案規劃包含哪些內容?可以包含許多內容,但最基本的是要包含目標聲明和一系列使用者方案。還有其他很多有用的資料,包括需求文檔、編碼通訊協定、交付
進度、測試過程等。對於我們要建立的簡單樣本解決方案,將主要介紹簡單的應用程式聲明和一些使用者方案。同時還將解決一些其他問題。

應用程式聲明

此系列文章要建立的項目(稱為 DotNetKB)是一個簡單的知識庫 Web 網站,在這個網站中,使用者可以提各種問題,並可以得到授權“專家”的回答。這樣,以後訪問者在尋找常見 ASP.NET 問題的解決方案時,可以對得到的結果資料進行搜尋和過濾。


是對我們的 DotNetKB 項目的一個基本目標聲明。DotNetKB 是一個基於 Web
的應用程式,它可以列出訪問者提出的一系列問題,並顯示授權專家對這些問題作出的回複。訪問者可以向系統添加新問題,並可以按照問題的主題、問題和/或回
答中的關鍵字來搜尋和過濾這些問題。訪問者還可以按主題或按添加到系統中的日期來對問題列表進行排序。

授權專家可以登入到應用程式中已設定安全機制的部分,審閱問題,添加、編輯和刪除對一個問題的一個或多個回答。應用程式系統管理員還可以建立專家登入許可權和登入設定檔,以及添加、編輯和刪除問題主題。

此外,還提供了一些基本統計資訊,包括系統中問題和回答的數量,以及每個專家的回複數量和至今已被訪問的頁面數量。


如您從上面的聲明中看到的那樣,該解決方案非常簡單。在閱讀目標聲明時,您可能會開始考慮可以添加到這個應用程式的許多其他功能,以使應用程式更加強大。
這說明了項目目標聲明的一個主要依據,即避免“功能蔓延”。我們都清楚,如果更改最終結果本來基於的概念,簡單的想法將導致非常龐大且歪曲的結果。有句老
格言:“如果不知道要去往何方,你可能會在某個地方停下來”,它原本揭示的是夏季公路旅行,其道理同樣可用於軟體項目。

一些項目的目標聲明中可能需要包含更多的資訊。而對於我們的使用,上面的目標聲明就符合要求。現在我們對於要完成的應用程式有了一個清晰的認識,接下來需要一些詳細的資訊來描述使用者如何與系統互動以及使用者需要執行哪些任務來完成目標。我們需要一系列使用者方案。

文檔化使用者方案


戶方案沒有什麼令人驚異之處。通常,它們只是描述使用者如何與應用程式互動。使用者方案的關鍵價值在於記錄了關於每個人對使用者希望系統如何運行以及應用程式應
如何響應的設想。通過完成這個過程,您將可以完全瞭解處理各種使用者與系統的互動時所需的資料點和函數。換句話說,編寫完善的使用者方案將有助於您確定完成解
決方案需要實現的資料庫、中介軟體和使用者介面元素。

注意:Visual
Studio .NET Enterprise Architect 有一項非常不錯的功能,即允許您使用 Microsoft Visio 通過
UML(整合模組化語言)建立使用者方案,然後產生這些方案的基本代碼。在這裡,我不打算深入探討這些細節,但是您可以在 MSDN Academic
Alliance 網站找到一篇關於這一主題的好文章 Generating .NET Code Using Visio Enterprise Architect's UML,作者是 Sreedhar Koganti。

有了上一節的目標聲明後,下面是 DotNetKB 項目的幾個樣本使用者方案。

搜尋知識庫


名使用者可以輸入一個或多個關鍵字並執行搜尋,搜尋將返回包含這些關鍵字的問題和/或回答列表。使用者可以將關鍵字搜尋鎖定在僅搜尋問題、僅搜尋回答或者二者
都搜尋。返回的列表將顯示問題及其回複數和被其他使用者訪問的次數。單擊連結將返回以時間先後逆序排列的回複(純文字)列表。

將新問題輸入到知識庫中


名使用者可以瀏覽用於向資料庫輸入新問題以供授權專家審閱和回複的螢幕。使用者可以輸入問題的標題和內容,並可以選擇在一系列主題中的某個主題下記錄該問題。
使用者還可以輸入他們的名字和相關的 URL(電子郵件、Web
地址等)。輸入將被驗證,以確保包含必需的資料並確保所有輸入資料不會受到指令碼攻擊等。一旦資料經過驗證並被儲存到資料庫中,使用者將看到一個響應螢幕,感
謝使用者的支援並將使用者直接連接到首頁。此外,使用者還可以選擇讓該網站“記住”他們的姓名和 URL 以備以後訪問該網站時使用。

您已經瞭解它的工作原理了,對嗎?每一個方案都嘗試細化使用者互動的重要方面。例如,上面列出的兩個方案表明使用者為“anonymous”(匿名使用者),這表示這類使用者不需要登入或進行其他方式的授權。第二個樣本還標識了若干輸入值、驗證步驟和可選操作。


然,這隻是兩個樣本;完整的系統需要更多的方案。此外,需要特別注意的是,“使用者”不僅僅可以是人,也可以是您的程式需要與其通訊的其他應用程式,甚至還
可以是您的應用程式的其他部分。例如,一個方案描述首頁如何列出最近添加到知識庫中的內容,以供任何人查看。此例中的“使用者”將是首頁自身。還有一些方案
描述專家如何尋找和回複新問題以及管理員如何更新主題列表並管理系統的其他部分。我已為討論這個簡單的應用程式識別碼了 20 多種方案。您可以在 DotNetKB 中找到當前列表(以及與此項目相關的所有其他資料)。

至此我們就有了目標聲明和一些使用者方案。現在,是時候稍憩一下,然後學學一些技術了。我們需要定義應用程式體繫結構,這可以協助我們以“鮮活有效代碼”實際實現方案。

定義應用程式體繫結構


了基本的目的和為解決方案開發的使用者方案列表後,您需要開始籌劃整體的體繫結構。主要目標是標識應用程式的邏輯方面和物理方面,即如何將應用程式拆分為各
種有用的部分。在本節中還添加了安全性方面的內容。安全是在規劃的“一開始”您就需要考慮的問題,而不是在開發週期中“最後添加”的內容。我們稍後會在本
節中詳細討論這個問題。

邏輯體繫結構


邏輯上講,您需要規劃解決方案以標識資料存放區、資料訪問、商務規則、使用者介面等之間的“邊界”。通常,Web 開發人員會選擇一個兩階段模型,並用
Web Form儲存用於訪問現有資料存放區系統(例如 Microsoft SQL Server)的所有代碼。一個更有效方法是建立一個位於 Web
表單使用者介面與 SQL Server 資料存放區系統之間的中介層組件庫。這種三層方法(Web
表單、組件、資料庫)通常是大多數應用程式所需的。但是,在某些情況下,可能需要一個其他層來處理伺服器之間傳輸的資料。這個傳輸層可以使用獨立於平台的
協議(例如 XML-SOAP)來實現。但是,如果您從頭到尾都使用 Microsoft .NET 技術,則可以使用 .NET
遠程協議的二進位版來完成這一任務,而且速度比使用 XML-SOAP 要快得多。

對於我們的樣本,我們將定義三個邏輯邊界:使用者介面(Web Form)、中介層(一個 .NET 組件程式集)和資料層(SQL Server 資料庫)。圖 1 顯示了如何表示這一內容。

圖 1:三層圖


在我們有一個簡單的邏輯模型。它是如何起作用的?它有助於我們考慮各個邏輯組之間的邊界。每個邏輯層應盡量與其他層獨立。理想的情況是,圖層中的更改應該
對整體產生最小的影響。例如,如果將資料存放區從 SQL Server 更改到 XML
資料檔案,唯一受到影響的圖層應是中介層圖層。使用者介面應該根本無需考慮更改。這會使您進行思考:如何?解決方案的實際編碼以實現此原則。

另外,邏輯層有助於我們考慮安全問題。各個圖層之間的邊界都存在潛在的安全性漏洞。而且,各個圖層可能有自己特定的安全措施(SQL Server 許可權、.NET 運行時許可權、ASP.NET 安全等)。同樣,我們稍後會在本節中詳細討論這個問題。

物理體繫結構


定邏輯層後,考慮物理層也很重要。例如,您可以在同時安裝有 SQL Server、Internet Information
Server、ASP.NET 和 .NET 運行時的單個實際電腦上實現這個應用程式。這將是一個物理層。但更可靠且可擴充的方法是:在由三個
Web 服務器組成的簇上部署 Web Form,在兩個應用伺服器上部署 .NET 組件程式集,在兩個故障復原模式的 SQL Server
上部署資料庫。這樣產生的物理體繫結構將七個 Windows 伺服器包含在三個主要組中:Web
簇、組件簇和資料庫簇。如果您瞭解系統的不同邏輯組件可以位於不同的電腦上,您可能會實現不同的代碼。

對於
我們的樣本,我們採用一個有效且強大的兩層模型:Web 服務器託管使用者介面和組件,資料庫伺服器託管 SQL Server
資料存放區。如果通訊量非常大,這個模型使我們可以靈活地在簇中添加更多的伺服器,並使其保持足夠的簡潔以便於處理。下面的映像顯示了此物理體繫結構與前面
定義的邏輯體繫結構之間的映射關係。

圖 2:物理體繫結構與三層體繫結構之間的映射關係

正如您看到的那樣,邏輯體繫結構和物理體繫結構不必相同。在規劃階段還要考慮一項內容:安全。

安全規劃

Microsoft
有一個關於安全性與軟體這一主題的歌訣:“Secure by design, secure by default, and secure by
deployment(設計安全,預設安全和部署安全)”。即,在安全中設計,期待系統在預設情況下是安全的,以及建立可以在安全環境中成功部署的解決方
案。安全始終是重要的。既然越來越多的軟體要在公用的 Internet 上“生存”,編寫安全的軟體就更加關鍵。對於我們而言,幸運的是,.NET
運行時和 Windows
作業系統提供廣泛的安全選項和功能,我們可以輕鬆地將其包含在我們的應用程式中。無需過分注重標識和消除聯機解決方案中安全性漏洞的細節,我們可以指出其中
一些最常見的漏洞並指出我們的應用程式規劃如何進行處理。

注意:有關可用選項的詳細資料,請參閱 Microsoft Security Developer Center。

緩衝區溢位


可能是已編譯應用程式中最常見的安全性漏洞。由於我們將使用 .NET
運行時,而它是設計用來在記憶體中安全啟動並執行,因此不太可能發生緩衝區溢位。此外,我們使用 Microsoft Visual Basic .NET
對解決方案進行編碼,而 Microsoft Visual Basic .NET 不像 C 或 C++
那樣容易受到緩衝區溢位問題的影響。但是,即使我們打算用 C++ 建立組件,我們還可以使用編譯器的特殊功能,GS
轉換,來保護我們免受大多數緩衝區溢位的攻擊。

資料庫攻擊


一種常見的安全性漏洞可能會使惡意使用者獲得訪問儲存在資料庫中的未經處理資料的許可權。為了防止駭客獲得資料的控制權,我們僅使用 SQL Server
預存程序,而不使用“內聯查詢”。這樣可以大大減少試圖在輸入資料流中插入其他 SQL
命令的攻擊。我們還在程式中多個位置處使用輸入驗證,以確保所有輸入僅包含有效字元。

交叉網站指令碼攻擊


Web 應用程式進行的常見攻擊還有一種,它涉及到使用者在輸入資料流中添加客戶方指令碼,這類攻擊將執行附加的對話並誘騙使用者將個人資料發送到駭客自己的
Web 網站。要解決這個問題,我們使用 ASP.NET 1.1
的一個新功能,過濾出這種惡意代碼的所有輸入,防止將它置入系統中。顯示螢幕上還包含附加代碼,它將自動禁用任何指令碼或顯示可能會插入到資料存放區中的標
記。

至此,我們已獲得了應用程式的邏輯模型和物理模型,以及確保實現方案包含的安全功能清單。擁有了這些以及目標聲明和使用者方案,我們可以開始這次“編碼前”探險的最後一部分了。

完成設計文檔


直接進入項目的編碼部分之前,需要花一點時間實際勾畫出應用程式的邏輯組件,這非常重要。在我們的樣本解決方案中,我們要實現解決方案的三個邏輯組件:數
據庫、.NET 資料訪問組件和 ASP.NET
使用者介面。在下面幾篇文章中,我們將非常詳細地介紹如何?這些組件。但現在,我們只是勾畫出每個組件的大致輪廓,討論過程中最重要的方面,即文檔化組件
間的互動。

資料庫

對於 DotNetKB 應用程式,我們需要將資料存放區在三張表中:主題、問題和回答(請參閱)。

圖 3:主題、問題和回答表


們需要使用預存程序,以使中介層組件也可以安全地訪問資料。有關資料庫的細節,我們將在下一篇文章中討論。這裡,我們只是指出:列出表名稱及所有列細節、
預設索引和預存程序列表的資料庫文檔,應該包含在一個完整的資料庫設計文檔中。即,文檔中應該具有成功實現系統資料存放區部分所需的詳細資料。

注意:如果留心的話,您可能會注意到我們未提及將專家資料存放區在資料庫中。只是為了使項目更加有趣(同時給我們一個機會使用直接 XML 資料存放區),我們將專家資訊儲存在一個 XML 資料檔案中。

資料訪問組件


據訪問組件設計文檔描繪與資料存放區系統的互動以及與使用者介面的互動的所有細節。在有些系統中,資料訪問組件實際上是處理過程中各種問題的多個程式集。例
如,可能會有一系列商務規則呈現在與資料存放區和檢索完全獨立的使用者介面上。在這種情況下,將業務組件與資料訪問組件分開實現可能比較明智。

在我們的樣本中,實際實現的是兩個單獨的組件:Message 組件和 DataAccess 組件。如果在支援基於 XML 的資料的傳輸服務(例如 SOAP Web Service)中進行規劃,這種面向訊息的實現方案將會特別有成效。

訊息組件


息組件定義一系列用於在各圖層之間傳輸資料的類。這些訊息可以作為二進位或 XML
文本資料存在。訊息圖層的價值在於:保護系統的其餘部分,使其獨立於資料存放區實現方案的具體細節,例如 SQL Server、XML
檔案等。此外,通過實現訊息圖層而不是更複雜的“智能對象”庫,我們的解決方案可以更輕鬆地支援那些不能同時發送資料和類層級邏輯的遠程調用服務,例如
XML-SOAP。

下面是一個訊息類樣本,在該樣本中實現了 Topic 訊息及其集合:

Public Class Topic
Private _ID As Integer
Private _Title As String
Private _Description As String

Public Property ID() As Integer
Get
Return _ID
End Get
Set(ByVal Value As Integer)
_ID = Value
End Set
End Property

Public Property Title() As String
Get
Return _Title
End Get
Set(ByVal Value As String)
_Title = Value
End Set
End Property

Public Property Description() As String
Get
Return _Description
End Get
Set(ByVal Value As String)
_Description = Value
End Set
End Property

End Class

Public Class Topics
Inherits System.Collections.CollectionBase

Default Public Property Item(ByVal index As Integer) As Topic
Get
Return CType(List(index), Topic)
End Get
Set(ByVal Value As Topic)
List(index) = Value
End Set
End Property

Public Function Add(ByVal s As Topic) As Integer
Return List.Add(s)
End Function

Public Sub Remove(ByVal index As Integer)
List.Remove(index)
End Sub

End Class

注意:如果您
已嘗試過面向訊息的設計,便會瞭解我們想要使這些訊息類系列化,以便在應用程式圖層之間輕鬆地來回傳送。幸運的是,.NET
運行時知道如何進行這項操作,而無需我們做過多的工作。但是,當我們學習建立訊息的文章時,我們將詳細討論 .NET
運行時如何系列化類,以及我們如何進行操作以使代碼中的過程最佳化。

在後面實現訊息組件和資料訪問組件時,文章中將介紹此方法的細節。設計文檔將包含一個由所有資訊及其屬性與資料類型組成的列表。現在,我們只是考慮如何使用此訊息方法來封裝圖層間的資料轉送,如何建立一種與本地方案和遠程方案配合使用的常規資料服務。

資料訪問組件

定義訊息類的概念後,資料訪問組件可以集中精力處理與資料存放區系統直接對話的細節,並以正確的訊息格式返回資訊。在我們的樣本中,這將涉及到使用來自使用者介面的請求映射 SQL Server 預存程序,並建立可返回到使用者介面進行顯示的訊息(或訊息集合)。

例如,下面是一個資料訪問組件的一部分範例程式碼,該組件將從資料存放區中檢索單個 Topic 記錄,並將正確的訊息格式返回到使用者介面。

Public Function GetTopicRecord(ByVal ID As Integer) As Messages.Topic
Dim t As Messages.Topic = New Messages.Topic
cn = New SqlConnection(secureConnectionString)
cd = New SqlCommand("GetTopic", cn)
cd.CommandType = CommandType.StoredProcedure
cd.Parameters.Add("@ID", ID)
cn.Open()
dr = cd.ExecuteReader()
dr.Read()
With t
.ID = ID
.Title = dr("Title")
.Description = dr("Description")
End With
Return t
End Function

設計文檔將包括一系列用於處理來自使用者介面的各個請求的類和方法,並含有有關調用哪個預存程序以及返回何種訊息格式的詳細資料。同樣,我們將在後面主要介紹資料訪問圖層的文章中討論此過程的細節。

Web 使用者介面

最後,使用者介面設計文檔將包括完成各種方案所需的所有使用者輸入和顯示。通常來說,使用者介面文檔包括介面機制的細節以及使使用者介面呈現唯一性的圖形設計項目。例如,色彩配置、字型和總體頁面設計,與用於擷取搜尋查詢的正確資料的輸入名稱和輸入數量一樣重要。


使文檔簡潔,通常在一個與圖形設計單獨的文檔中概要描述機制細節。這是我們將要在樣本中做的工作。在後面的一篇文章中,我們將建立一個綜合性使用者介面文檔
和實現方案,詳細說明每個螢幕的元素和相關操作。在另一篇文章中,我們將處理應用程式有關圖形的各個方面,重點討論作為一種外觀服務的階層式樣式表的使用。

下面是一個典型的使用者介面描述,它涉及“主題”編輯方案。

主題輸入螢幕

“主
題”螢幕將顯示所有當前主題(主題 ID
和主題名稱)的一個縮減列表,在每個主題旁邊還將顯示一個“編輯”連結。單擊“編輯”連結將會調用關聯的主題記錄並將其顯示在一系列的輸入框中。“標題”
和“描述”是可編輯的,而“主題
ID”是唯讀。使用者可以編輯標題和描述,然後按“儲存”按鈕將更改寫入資料存放區。輸入將被驗證。兩者都是必需的輸入項,“標題”的長度限制為 30
個字元,“描述”的長度限制為 500 個字元。更新完成後,將顯示一條響應訊息指出已確認更新;如果更新失敗,則顯示一條訊息指出錯誤狀況。

使用者還可以刪除現有的主題記錄,方法是單擊列表中的“編輯”連結,審核顯示螢幕上的記錄細節後,單擊“刪除”連結。刪除完成後,將顯示一條響應訊息指出已確認更新;如果更新失敗,則顯示一條訊息指出錯誤狀況。請注意,使用者不能刪除與現有問題或回答相關聯的主題。


外,使用者可以完整地添加新主題記錄,方法是在初始顯示螢幕上單擊“建立主題”連結。將顯示“標題”和“描述”輸入(不顯示 ID
輸入)並提供一個“儲存”按鈕。輸入將被驗證。兩者都是必需的輸入項,“標題”的長度限制為 30 個字元,“描述”的長度限制為 500
個字元。更新完成後,將顯示一條響應訊息指出已確認更新;如果更新失敗,則顯示一條訊息指出錯誤狀況。

利用上面的敘述,您可以輕鬆地實現一個完整的功能螢幕。判斷一個好的設計文檔的方法是:它能夠使讀者完成工作,且不會提出額外的問題。最終的使用者介面設計文檔將包括應用程式中每個螢幕的此類敘述。

小結並付諸行動


們簡要介紹了資料庫、中介層和使用者介面實現方案的最終設計文檔。加上體繫結構和初始規劃文檔,它們形成了我們的完整設計包。在實際的情況中,即使是最小的
系統,完成這些文檔也至少需要幾個小時。對於大型系統,可能需要幾周甚至可能幾個月的時間。有些人可能會對此有一點挫敗感,但是通過事先完成這些工作,您
可以在進入項目的編碼階段之前很早就瞭解完成解決方案面臨的幾乎所有主要障礙。這樣可以減少編寫實際代碼的時間,並且還可以減少您會遇到的錯誤和障礙的數
量。

在下一篇文章中,我們將討論使用 Visual Studio .NET 在 SQL Server 中建立資料存放區系統的有關細節。我們將定義資料表,建立必需的預存程序,並設定正確的資料訪問,以確保任何組件和資料本身之間具有安全可靠的串連。

至此,您已經看到了一個如何建立應用程式規劃的可用樣本,可以開始考慮如何在您自己的工作中使用這些元素來提高項目的整體品質和生產率。有關專案規劃以及規劃如何影響軟體品質的詳細資料,請參閱 Steve McConnell 的 Software Project Survival Guide。

Mike Amundsen 提供培訓、演講和諮詢服務。要瞭解他的詳細資料或與他聯絡,請訪問他的網站 http://amundsen.com/。此外,還可以在 http://www.amundsen.com/DotNetKB 網站上找到本文的更新和相關資料。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.