哈,歡迎後 !我的名稱是 Parag Agarwal 在 Microsoft 的支援工程師。本月份我們要討論 Microsoft ASP.NET 2.0 中的虛擬路徑提供者。
概觀
本月份我們將討論如何藉由提供內容和編譯 ASP.NET 2.0 中的檔案的虛擬存取擴充 ASP.NET。這項功能可用來建立應用程式類似於 Microsoft SharePoint 入口網站伺服器內容儲存在實體檔案系統上而不是資料庫中的位置。我們將在本文章建置所要求的 Web 表單頁面的內容儲存在 Microsoft SQL Server 資料庫中的其中一個範例。
虛擬路徑提供者
虛擬路徑提供者提供一種機制,與我們可以擴充 ASP.NET 提供虛擬編譯系統的內容。比方說虛擬路徑提供者會提供方法來提供內容從檔案系統以外的位置。開發人員想要提供虛擬的內容必須執行下列工作:
- 建立 VirtualPathProvider 類別,並實作所有必要的方法,以便處理檔案和資料夾的要求。
- 虛擬路徑提供者,以讓 ASP.NET 裝載環境的暫存器知道會從服務內容。
- 建立要傳送串流內容的 VirtualFile 和 VirtualDirectory 物件。
如需有關
VirtualPathProvider 類別的詳細資訊,請造訪下列 Microsoft 開發 o 人 h 員 ? 工 u 具 ? 網路 (MSDN) 網站]:
可以虛擬化哪些內容?
browseable 的類型例如 ASPX]、 [主版頁面]、 [ASCX,] 和 [佈景主題,是唯一可以虛擬化的項目。
AppInitialize 靜態方法,並在
Global.asax 檔內定義的事件進行呼叫後,會初始化應用程式。這些方法呼叫都可以登錄
VirtualPathProvider 類別只有兩個地方。
諸如 [App_Code] 和 [App_Data] 資料夾的最上層項目編譯無法影響任何點,在您想要註冊的提供者應用程式的存留週期中。
若要將虛擬化非預設可瀏覽內容,您需要對應
BuildProvider 類別。如需有關
BuildProvider 類別和如何在 ASP.NET 建置環境使用
BuildProvider 類別中,以產生不同的檔案類型的原始程式碼的詳細資訊,請造訪下列 MSDN 網站:
編譯模型
我們建立一個範例之虛擬路徑提供者之前我們會經過 ASP.NET 2.0 編譯模型中主要的元件的概觀。本概觀將協助我們了解如何將內容編譯 ASP.NET] 建置系統無法開啟及 Microsoft Visual Studio 中建立 Web 站台,以瀏覽 Web 網頁。
ClientBuildManager 類別
ClientBuildManager 類別提供了建置組件、 產生原始碼及執行由與 ASP.NET 互動的預先編譯的 API 建置系統。
ClientBuildManager 類別提供 Microsoft 網際網路資訊服務 (IIS) 之外的建置系統的存取。利用
ClientBuildManager 類別 Visual Studio 2005 可提供如 IntelliSense]、 [陳述式完成] 和 [即時錯誤報告的酷炫功能。
ClientBuildManager 類別也會提供一或多個檔案的虛擬和實體路徑。如需詳細資訊請造訪下列 MSDN 網站:
BuildManager 類別
BuildManager 類別會管理程序的編譯組件和應用程式中的網頁。如需詳細資訊請造訪下列 MSDN 網站:
BuildProvider 類別
BuildProvider 類別會提供剖析特定檔案和產生檔案的相對應的程式碼的功能。如需詳細資訊請造訪下列 MSDN 網站:
AssemblyBuilder 類別
AssemblyBuilder 類別表示動態組件中的所有組件相依性清單。這個類別所預期原始程式碼或
CodeCompileUnit 物件在編譯過程中提供的組建提供者。如需詳細資訊請造訪下列 MSDN 網站:
擴充的虛擬路徑提供者提供虛擬來自資料庫的內容
既然我們已經一般瞭解虛擬路徑提供者和編譯模型,我們可以建立小型的 SharePoint 入口網站提供非檔案基礎內容的存取權的類似服務的應用程式。
附註我們開始建立範例應用程式之前讓我們看看資料庫結構和用範例中的 Web 站台階層:
沒有在資料庫中名為
VirtualFileSystem 只有一個資料表。此表格看起來如下所示:
Visual Studio 內網站階層架構看起來如下所示:
備忘稿- [App_Code] 資料夾包含實作一個虛擬路徑提供者的例如 VirtualPathProvider 類別、 VirtualDirectory 類別、 VirtualFile] 類別和 公用程式 類別所需的所有類別。
- SharePointDir 資料夾代表虛擬目錄。 這個虛擬目錄的內容儲存在資料庫中。在此資料夾內網頁的任何要求會視為視為虛擬檔案的要求,由 ASP.NET 執行階段。
- AdminstrationPage.aspx 頁面會顯示使用者介面,我們可以在其中執行 CRUD (建立、 讀取、 更新及刪除) 上的作業協助虛擬內容 GridView 控制項。AdminstrationPage.aspx 頁面看起來如下所示:
讓我們開始建置範例。
要這麼做,請您執行下列步驟:
- 啟動 Visual Studio 2005。
- 建立具有完全的階層架構和出現在較早的影像中的檔案的網站。
- 開啟 SharePointDirectory.cs 來源檔案。
- 確認下列命名空間會包含在 SharePointDirectory.cs 檔案:
using System;
using System.Collections;
using System.Data;
using System.Security.Permissions;
using System.Web;
using System.Web.Hosting;
- 宣告 SharePointProvider 類別和繼承 VirtualPathProvider class.
public class SharePointProvider :
VirtualPathProvider
- 宣告兩個私用 members.
//It contains the file name and content as a key-value pair retrieved
//from the database.
Hashtable virtualFiles = null;
DBUtility utility = null;
- 加入 AppInitialize 方法。AppInitialize 方法是在此處理程序中最重要的方法。在 ASP.NET 應用程式正在啟動時,執行階段引擎會呼叫這個方法。
附註這個方法可以視為我們用來讓 ASP.NET 執行階段載入這個類別沒有任何 Web.config 檔案的一個技巧。
如果我們一個以上的類別,這個方法搭配就建置時期錯誤。 這個方法內,我們會使用 ASP.NET 裝載環境註冊我們提供者。現在,Web 網頁的每個要求都會通過 public static void AppInitialize()
{
HostingEnvironment.RegisterVirtualPathProvider(new SharePointProvider());
} 這個提供者。 - 實作 SharePointProvider 類別的建構函式。這個步驟是我們將在其中擷取所有虛擬的檔案和其內容,以便快速存取的記憶體中。直到失效內容,我們將使用中記憶體結果集。只要在資料庫中變更內容,需要更新內容
public SharePointProvider(): base()
{
utility = new DBUtility();
virtualFiles = utility.GetVirtualFiles();
} - 接下來,加入 IsPathVirtual 方法。在使用此方法中,我們可以判斷要求的檔案是從虛擬路徑。我們已決定要求 SharePointDir 資料夾內該檔案將會被視為
private bool IsPathVirtual(string virtualPath)
{
String checkPath =
VirtualPathUtility.ToAppRelative(virtualPath);
return checkPath.StartsWith("~/SharePointDir".ToLower().ToString(), StringComparison.InvariantCultureIgnoreCase);
} 一個虛擬檔案。 - FileExists 方法會傳回該檔案是否存在。它會藉由驗證要求的檔案存在於資料庫中。如果檔案不存在,我們會在編譯系統中取得先前註冊的虛擬路徑提供者物件的參考,我們會嘗試呼叫 FileExists 方法來重新尋找檔案。如果仍然未找到該檔案,我們會收到另一個 「 404 (找不到檔案) 」 錯誤訊息
public override bool FileExists(string virtualPath)
{
if (IsPathVirtual(virtualPath))
{
SharePointVirtualFile file = (SharePointVirtualFile)GetFile(virtualPath);
// Determine whether the file exists on the virtual file
// system.
if (utility.CheckIfFileExists(virtualPath))
return true;
else
return Previous.FileExists(virtualPath);
}
else
return Previous.FileExists(virtualPath);
} - 同樣地,我們有 DirectoryExists 方法。這個方法會傳回提供者可以服務做為引數傳遞的虛擬檔案路徑,則為 True。否則,提供者會提供先前註冊的提供者的虛擬檔案路徑如往常般而且我們將接收 404 錯誤訊息再次如果資料夾不存在
public override bool DirectoryExists(string virtualDir)
{
if (IsPathVirtual(virtualDir))
{
// Right now, we are not storing the directory information in
// our SharePoint Portal Services database. We assume that all of the virtual
// content is served from a directory that is named SharePointDir and was
// created inside the ASP.NET Web site. Therefore, we will always
// return TRUE in this case.
SharePointVirtualDirectory dir = (SharePointVirtualDirectory)GetDirectory(virtualDir);
return true;
}
else
return Previous.DirectoryExists(virtualDir);
} - 接下來我們必須 GetFile 和 GetDirectory 方法。ASP.NET 執行階段會呼叫這些方法中虛擬路徑提供者之後 FileExists 和 DirectoryExists 方法的呼叫會成功。編譯系統使用
//This method is used by the compilation system to obtain a VirtualFile instance to
//work with a given virtual file path.
public override VirtualFile GetFile(string virtualPath)
{
if (IsPathVirtual(virtualPath))
return new SharePointVirtualFile(virtualPath, this);
else
return Previous.GetFile(virtualPath);
}
//This method is used by the compilation system to obtain a VirtualDirectory
//instance to work with a given virtual directory.
public override VirtualDirectory GetDirectory(string virtualDir)
{
if (IsPathVirtual(virtualDir))
return new SharePointVirtualDirectory(virtualDir, this);
else
return Previous.GetDirectory(virtualDir);
} - 我們必須新增幾個公用程式方法,將會用於由 VirtualFile 類別,稍後在
public string GetFileContents(string virPath)
{
return utility.GetFileContents(virPath);
}
public Hashtable GetVirtualData
{
get { return this.virtualFiles; }
set { this.virtualFiles = value; }
} 在這個範例中的 附註,來通知對虛擬內容所做的任何變更,對建置系統,我們沒有使用此機制。 這個範例。虛擬的提供者公開 API,名為 GetCacheDependency,用來協助快取虛擬資源。我們可以讓快取失效時的任何檔案會變成無效。如需詳細資訊請造訪下列 MSDN 網站: - 我們完成主要提供者類別。現在開啟 SharePointDirectory.cs 來源檔案。這個類別將當做虛擬化資源的抽象概念。如需有關 VirtualDirectory 類別的詳細資訊,請造訪下列 MSDN 網站:
- 因為 VirtualDirectory 類別是抽象類別我們需要覆寫所有抽象方法。不過,我們會不提供額外的實作上那些被覆寫的方法因為這個範例中,我們假設虛擬內容來自單一的虛擬目錄內。因此,類別定義將如下所示:
public class SharePointVirtualDirectory : VirtualDirectory
{
SharePointProvider spp;
public SharePointVirtualDirectory(string virtualDir, SharePointProvider provider) : base(virtualDir){spp = provider;}
private ArrayList children = new ArrayList();
public override IEnumerable Children {get {return children;}}
private ArrayList directories = new ArrayList();
public override IEnumerable Directories{get {return directories;}}
private ArrayList files = new ArrayList();
public override IEnumerable Files{get { return files;}}
} - 現在,我們已準備好要定義一個名為 SharePointVirtualFile 延伸 VirtualFile 抽象類別的多個類別。這個類別會具有名為 OpenFile 的一個覆寫抽象方法。OpenFile 方法會傳回資料流執行個體所使用的 ASP.NET 建置環境消耗虛擬檔案
public class SharePointVirtualFile : VirtualFile
{
private SharePointProvider spp;
private string virPath;
public SharePointVirtualFile(string virtualPath, SharePointProvider provider) : base(virtualPath)
{
this.spp = provider;
this.virPath = virtualPath;
}
public override Stream Open()
{
string fileContents = spp.GetFileContents(virPath);
Stream stream = new MemoryStream();
if (fileContents != null || fileContents.Equals(String.Empty))
{
// Put the page content on the stream.
StreamWriter writer = new StreamWriter(stream);
writer.Write(fileContents);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
}
return stream;
}
} - 在最後我們會定義 DBUtiliity 類別 DBUtility.cs 檔案中。未提供方法實作。DBUtiliity 類別由提供者類別用來從資料庫與幾個其他公用程式函式一起取得內容
public class DBUtility
{
SqlConnection cnn;
string connectionString = "connectionstring to DB…";
//Run a select query to obtain all files and their content, and
//store the result in a in memory hashtable to obtain fast access.
string cmdSelectAllFiles = "SELECT FileName,FileData FROM VirtualFileSystem";
Hashtable virtualFiles = null;
public DBUtility(){ virtualFiles = new Hashtable();}
public Hashtable GetVirtualFiles()
{
/* 1. Open a connection.
2. Select all the files.
3. Iterate through the result and store the file name as a Key and
content as a Value in a hashtable.
4. Finally return hashtable.
*/
return virtualFiles;
}
public string GetFileContents(string virPath)
{
//Obtain a file name from the virtual path.
string fileName = ExtractFileName(virPath);
//Ater you obtain the file name, find it in the hashtable, and then
//return the content for that file from the Values collection.
}
private string ExtractFileName(string virPath)
{
//Extract a file name from the virtual path and return it.
}
public bool CheckIfFileExists(string virPath)
{
string fileName = ExtractFileName(virPath);
//After you extract the file name, find it in the hashtable of
//virtual files. If the file name is found, return true. Otherwise, return false.
}
}
要牢記在心的 注意 一件事就是該註冊的提供者特殊權限的操作,因為它可以變更呈現內容。VirtualPathProvider、 VirtualDirectory 和 VirtualFile 類別的自訂類別必須在 完全 信任權限下執行。如需詳細資訊,請造訪下列 MSDN 網站: - 我們完成撰寫提供者的類別和現在我們的應用程式已準備好提供虛擬的內容。若要讓應用程式外觀和行為的 SharePoint 入口網站服務管理網頁我有建立 AdministrationPage.aspx 頁面在網站的根資料夾。 The page contains a GridView control that is bound with a virtual table.
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataSourceID="SqlDataSource1" >
<Columns>
<asp:BoundField DataField="FileName" HeaderText="FileName" />
<asp:TemplateField HeaderText="Remote Content" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text="FileContent...."></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="Label1" runat="server" Text='<%#
Eval("FileData", "{0}") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:HyperLinkField HeaderText="Virtual Path"
DataTextField="VirtualPath" Target="_self"
DataNavigateUrlFormatString= "{0}"
DataNavigateUrlFields="VirtualPath" />
<asp:CommandField ShowEditButton="True"
ShowDeleteButton="True" CausesValidation="false"
HeaderText="Operations" CancelText="Cancel" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$
ConnectionStrings:VirtualProviderDBConnectionString %>"
SelectCommand="SELECT [FileName], [FileData], [VirtualPath] FROM
[VirtualFileSystem] Where [FileName] LIKE '%aspx%'”>
</asp:SqlDataSource>
結論
這是所有的虛擬路徑提供者現在。我希望此資料行可協助您瞭解 ASP.NET 2.0 的基本編譯程序,而且我們可以讓 ASP.NET 執行階段使用非檔案基礎內容,例如內容的方式從一個資料庫服務。
感謝您的時間。我們預期寫入多上在 ASP.NET 2.0 中,加入新的功能。如需詳細資訊和範例,請造訪 MSDN 網站:
如往常請隨意送出您想要在將來解決資料行的主題或使用
Ask For It
(http://support.microsoft.com/common/survey.aspx?scid=sw;en;1176&p0=&p1=&p2=&p3=&p4=)
表單的知識庫中的想法。