Asp.Net中虚拟文件系统的使用
生活随笔
收集整理的這篇文章主要介紹了
Asp.Net中虚拟文件系统的使用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在Asp.Net的開發過程中頁面文件等都是放在當前網站目錄下的,其實我們可以利用.Net2.0新增的虛擬文件系統(VirtualPathProvider)將頁面、圖片等信息保存到數據庫或其他目錄中去,達到靈活配置。
本文以一個例子來說明虛擬文件系統的使用,要實現的功能場景描述如下:
以前開發Asp.Net的web用戶控件時,需要把用戶控件和當前項目作為同一個項目時才能正常使用,而且發布時需要把dll文件和所有的ascx文件都發布才能使用;另外也不方便作為公用類給其他人使用
利用虛擬文件系統后可以把ascx文件作為資源打包到dll中,下次只要有這個dll就可以使用了,不需要ascx文件,很方便。
具體實現步驟如下:
一、開發web用戶控件
這一步和以前的開發沒有區別。
1、首先新建一個web應用程序(需要VS2005 sp1支持)
2、然后在里面開發幾個web用戶控件
3、在ascx文件上右鍵-〉屬性-〉生成操作選擇嵌入的資源
4、生成dll就可以了(dll的名字為:Test.Control.dll,后面會用到)
二、開發一個虛擬文件系統提供類
這一步是最重要的一步。
具體思路就是:在系統中注冊這個類,然后在每訪問一個文件/資源的時候會自動調用這個類,在這個類中判斷文件的路徑是否是我們定義的,如果是就用我們的邏輯來處理,即從dll中取出資源。
首先把類的代碼貼出來,我想可能許多人應該和我一樣,喜歡直接先看代碼:)
DllVirtualPathProvider
????public?class?DllVirtualPathProvider?:?System.Web.Hosting.VirtualPathProvider
????{
????????public?DllVirtualPathProvider()
????????{
????????}
????????public?override?string?CombineVirtualPaths(string?basePath,?string?relativePath)
????????{
????????????if?(IsAppResourcePath(basePath))
????????????{
????????????????return?null;
????????????}
????????????return?Previous.CombineVirtualPaths(basePath,?relativePath);
????????}
????????public?override?System.Runtime.Remoting.ObjRef?CreateObjRef(Type?requestedType)
????????{
????????????return?Previous.CreateObjRef(requestedType);
????????}
????????public?override?bool?DirectoryExists(string?virtualDir)
????????{
????????????if?(IsAppResourcePath(virtualDir))
????????????{
????????????????return?true;
????????????}
????????????else
????????????{
????????????????return?Previous.DirectoryExists(virtualDir);
????????????}
????????}
????????public?override?string?GetCacheKey(string?virtualPath)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?null;
????????????}
????????????else
????????????{
????????????????return?Previous.GetCacheKey(virtualPath);
????????????}
????????}
????????public?override?string?GetFileHash(string?virtualPath,?IEnumerable?virtualPathDependencies)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?null;
????????????}
????????????else
????????????{
????????????????return?Previous.GetFileHash(virtualPath,?virtualPathDependencies);
????????????}
????????}
????????private?bool?IsAppResourcePath(string?virtualPath)
????????{
????????????String?checkPath?=?VirtualPathUtility.ToAppRelative(virtualPath);
????????????return?checkPath.StartsWith("~/MyUserControl/Test.Control.dll/",?StringComparison.InvariantCultureIgnoreCase);
????????}
????????public?override?bool?FileExists(string?virtualPath)
????????{
????????????return?(IsAppResourcePath(virtualPath)?||?Previous.FileExists(virtualPath));
????????}
????????public?override?VirtualFile?GetFile(string?virtualPath)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?new?AssemblyResourceVirtualFile(virtualPath);
????????????}
????????????else
????????????{
????????????????return?Previous.GetFile(virtualPath);
????????????}
????????}
????????public?override?System.Web.Caching.CacheDependency?GetCacheDependency(string?virtualPath,
???????????????System.Collections.IEnumerable?virtualPathDependencies,?DateTime?utcStart)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????string?path?=?HttpRuntime.AppDomainAppPath?+?virtualPath.Substring(1);
????????????????return?new?System.Web.Caching.CacheDependency(path);
????????????}
????????????else
????????????{
????????????????return?Previous.GetCacheDependency(virtualPath,?virtualPathDependencies,?utcStart);
????????????}
????????}
????} 重點有以下幾個:
1、必須從VirtualPathProvider類繼承
2、IsAppResourcePath方法是用來判斷是否為我們定義的路徑格式:~/MyUserControl/Test.Control.dll/,下面調用的時候就使用這個路徑
3、注意GetCacheKey方法: ????????public?override?string?GetCacheKey(string?virtualPath)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?null;
????????????}
????????????else
????????????{
????????????????return?Previous.GetCacheKey(virtualPath);
????????????}
????????} 這里當符合條件時一定要返回null,如果返回"",會導致所有的用戶控件都使用一個key值,從而所有的用戶控件都顯示同樣的內容了。如果返回其他非空字符,會報異常(它會去查找cache,我們是沒有的)
另外所有的方法當不符合我們的條件時一定要調用 Previous.**** 因為系統中可能有多個虛擬文件提供程序的。
4、GetCacheDependency方法: if?(IsAppResourcePath(virtualPath))
????????????{
????????????????string?path?=?HttpRuntime.AppDomainAppPath?+?virtualPath.Substring(1);
????????????????return?new?System.Web.Caching.CacheDependency(path);
????????????} 這個方法是用來決定Cache的使用的,如果返回null,會導致性能嚴重下降,每次調用用戶控件時都會重新編譯,這里返回的當前路徑(需要在網站目錄下再建立子目錄:MyUserControl\Test.Control.dll),這個目錄下是空的,這樣當每次取Cache時都會認為我們的ascx沒有修改,不需要重新編譯。
5、在GetFile方法中我們返回的是一個AssemblyResourceVirtualFile類: ????class?AssemblyResourceVirtualFile?:?VirtualFile
????{
????????string?path;
????????public?AssemblyResourceVirtualFile(string?virtualPath)
????????????:?base(virtualPath)
????????{
????????????path?=?VirtualPathUtility.ToAppRelative(virtualPath);
????????}
????????public?override?System.IO.Stream?Open()
????????{
????????????string[]?parts?=?path.Split('/');
????????????string?assemblyName?=?parts[2];
????????????string?resourceName?=?parts[3];
????????????assemblyName?=?Path.Combine(HttpRuntime.BinDirectory,?assemblyName);
????????????System.Reflection.Assembly?assembly?=?System.Reflection.Assembly.LoadFrom(assemblyName);
????????????if?(assembly?!=?null)
????????????{
????????????????return?assembly.GetManifestResourceStream(resourceName);
????????????}
????????????return?null;
????????}
????} 這個類的目的就是從我們的dll中讀出資源文件。
三、注冊這個虛擬文件提供程序
這一個很簡單,在global.asax中注冊: ????????protected?void?Application_Start(object?sender,?EventArgs?e)
????????{
????????????System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new?DllVirtualPathProvider());
????????}
四、調用dll中的用戶控件 ????????????????Control?control1?=?this.LoadControl("/MyUserControl/Test.Control.dll/Test.Control.Sample.List.ascx");
????????????????Control?control2?=?this.LoadControl("/MyUserControl/Test.Control.dll/Test.Control.Sample.Sample.ascx");
????????????????form1.Controls.Add(control1);
????????????????form1.Controls.Add(control2); 比較簡單,就是路徑要和前面的一致。
后記:
首先感謝 Leepy? 同志認真踏實的精神,找出了我這篇文章中的一個BUG。
原來我的第四步:調用dll中的用戶控件,是一個web應用程序,如果是一個web站點的話就會出現問題。因為在VS2005中調試時這兩種方式呈現出來的Url是不一樣的:
web應用程序:http://localhost:****/Default.aspx
web站點?????:http://localhost:****/WebSite1/Default.aspx
也就是說我原來的程序沒有考慮到非根目錄部署的情況,針對這個BUG要修改的地方有(為了BUG的原始記錄,我就不在原文中修改了,把修改點列在下面):
1、GetCacheDependency方法:
GetCacheDependency
????public?override?System.Web.Caching.CacheDependency?GetCacheDependency(string?virtualPath,
???????????System.Collections.IEnumerable?virtualPathDependencies,?DateTime?utcStart)
????{
????????if?(IsAppResourcePath(virtualPath))
????????{
????????????string?path?=?HttpRuntime.BinDirectory;
????????????return?new?System.Web.Caching.CacheDependency(path);
????????}
????????else
????????{
????????????return?Previous.GetCacheDependency(virtualPath,?virtualPathDependencies,?utcStart);
????????}
????} 這里改成直接改成當前網站的bin目錄還可以省掉建空目錄的步驟了
2、在調用的地方修改成以下方式:
????????Control?control1?=?this.LoadControl("~/MyUserControl/MyWebApplication.dll/MyWebApplication.Sample1.ascx");
????????Control?control2?=?this.LoadControl("~/MyUserControl/MyWebApplication.dll/MyWebApplication.Sample2.ascx");
????????form1.Controls.Add(control1);
????????form1.Controls.Add(control2);
?
本文以一個例子來說明虛擬文件系統的使用,要實現的功能場景描述如下:
以前開發Asp.Net的web用戶控件時,需要把用戶控件和當前項目作為同一個項目時才能正常使用,而且發布時需要把dll文件和所有的ascx文件都發布才能使用;另外也不方便作為公用類給其他人使用
利用虛擬文件系統后可以把ascx文件作為資源打包到dll中,下次只要有這個dll就可以使用了,不需要ascx文件,很方便。
具體實現步驟如下:
一、開發web用戶控件
這一步和以前的開發沒有區別。
1、首先新建一個web應用程序(需要VS2005 sp1支持)
2、然后在里面開發幾個web用戶控件
3、在ascx文件上右鍵-〉屬性-〉生成操作選擇嵌入的資源
4、生成dll就可以了(dll的名字為:Test.Control.dll,后面會用到)
二、開發一個虛擬文件系統提供類
這一步是最重要的一步。
具體思路就是:在系統中注冊這個類,然后在每訪問一個文件/資源的時候會自動調用這個類,在這個類中判斷文件的路徑是否是我們定義的,如果是就用我們的邏輯來處理,即從dll中取出資源。
首先把類的代碼貼出來,我想可能許多人應該和我一樣,喜歡直接先看代碼:)
DllVirtualPathProvider
????public?class?DllVirtualPathProvider?:?System.Web.Hosting.VirtualPathProvider
????{
????????public?DllVirtualPathProvider()
????????{
????????}
????????public?override?string?CombineVirtualPaths(string?basePath,?string?relativePath)
????????{
????????????if?(IsAppResourcePath(basePath))
????????????{
????????????????return?null;
????????????}
????????????return?Previous.CombineVirtualPaths(basePath,?relativePath);
????????}
????????public?override?System.Runtime.Remoting.ObjRef?CreateObjRef(Type?requestedType)
????????{
????????????return?Previous.CreateObjRef(requestedType);
????????}
????????public?override?bool?DirectoryExists(string?virtualDir)
????????{
????????????if?(IsAppResourcePath(virtualDir))
????????????{
????????????????return?true;
????????????}
????????????else
????????????{
????????????????return?Previous.DirectoryExists(virtualDir);
????????????}
????????}
????????public?override?string?GetCacheKey(string?virtualPath)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?null;
????????????}
????????????else
????????????{
????????????????return?Previous.GetCacheKey(virtualPath);
????????????}
????????}
????????public?override?string?GetFileHash(string?virtualPath,?IEnumerable?virtualPathDependencies)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?null;
????????????}
????????????else
????????????{
????????????????return?Previous.GetFileHash(virtualPath,?virtualPathDependencies);
????????????}
????????}
????????private?bool?IsAppResourcePath(string?virtualPath)
????????{
????????????String?checkPath?=?VirtualPathUtility.ToAppRelative(virtualPath);
????????????return?checkPath.StartsWith("~/MyUserControl/Test.Control.dll/",?StringComparison.InvariantCultureIgnoreCase);
????????}
????????public?override?bool?FileExists(string?virtualPath)
????????{
????????????return?(IsAppResourcePath(virtualPath)?||?Previous.FileExists(virtualPath));
????????}
????????public?override?VirtualFile?GetFile(string?virtualPath)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?new?AssemblyResourceVirtualFile(virtualPath);
????????????}
????????????else
????????????{
????????????????return?Previous.GetFile(virtualPath);
????????????}
????????}
????????public?override?System.Web.Caching.CacheDependency?GetCacheDependency(string?virtualPath,
???????????????System.Collections.IEnumerable?virtualPathDependencies,?DateTime?utcStart)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????string?path?=?HttpRuntime.AppDomainAppPath?+?virtualPath.Substring(1);
????????????????return?new?System.Web.Caching.CacheDependency(path);
????????????}
????????????else
????????????{
????????????????return?Previous.GetCacheDependency(virtualPath,?virtualPathDependencies,?utcStart);
????????????}
????????}
????} 重點有以下幾個:
1、必須從VirtualPathProvider類繼承
2、IsAppResourcePath方法是用來判斷是否為我們定義的路徑格式:~/MyUserControl/Test.Control.dll/,下面調用的時候就使用這個路徑
3、注意GetCacheKey方法: ????????public?override?string?GetCacheKey(string?virtualPath)
????????{
????????????if?(IsAppResourcePath(virtualPath))
????????????{
????????????????return?null;
????????????}
????????????else
????????????{
????????????????return?Previous.GetCacheKey(virtualPath);
????????????}
????????} 這里當符合條件時一定要返回null,如果返回"",會導致所有的用戶控件都使用一個key值,從而所有的用戶控件都顯示同樣的內容了。如果返回其他非空字符,會報異常(它會去查找cache,我們是沒有的)
另外所有的方法當不符合我們的條件時一定要調用 Previous.**** 因為系統中可能有多個虛擬文件提供程序的。
4、GetCacheDependency方法: if?(IsAppResourcePath(virtualPath))
????????????{
????????????????string?path?=?HttpRuntime.AppDomainAppPath?+?virtualPath.Substring(1);
????????????????return?new?System.Web.Caching.CacheDependency(path);
????????????} 這個方法是用來決定Cache的使用的,如果返回null,會導致性能嚴重下降,每次調用用戶控件時都會重新編譯,這里返回的當前路徑(需要在網站目錄下再建立子目錄:MyUserControl\Test.Control.dll),這個目錄下是空的,這樣當每次取Cache時都會認為我們的ascx沒有修改,不需要重新編譯。
5、在GetFile方法中我們返回的是一個AssemblyResourceVirtualFile類: ????class?AssemblyResourceVirtualFile?:?VirtualFile
????{
????????string?path;
????????public?AssemblyResourceVirtualFile(string?virtualPath)
????????????:?base(virtualPath)
????????{
????????????path?=?VirtualPathUtility.ToAppRelative(virtualPath);
????????}
????????public?override?System.IO.Stream?Open()
????????{
????????????string[]?parts?=?path.Split('/');
????????????string?assemblyName?=?parts[2];
????????????string?resourceName?=?parts[3];
????????????assemblyName?=?Path.Combine(HttpRuntime.BinDirectory,?assemblyName);
????????????System.Reflection.Assembly?assembly?=?System.Reflection.Assembly.LoadFrom(assemblyName);
????????????if?(assembly?!=?null)
????????????{
????????????????return?assembly.GetManifestResourceStream(resourceName);
????????????}
????????????return?null;
????????}
????} 這個類的目的就是從我們的dll中讀出資源文件。
三、注冊這個虛擬文件提供程序
這一個很簡單,在global.asax中注冊: ????????protected?void?Application_Start(object?sender,?EventArgs?e)
????????{
????????????System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new?DllVirtualPathProvider());
????????}
四、調用dll中的用戶控件 ????????????????Control?control1?=?this.LoadControl("/MyUserControl/Test.Control.dll/Test.Control.Sample.List.ascx");
????????????????Control?control2?=?this.LoadControl("/MyUserControl/Test.Control.dll/Test.Control.Sample.Sample.ascx");
????????????????form1.Controls.Add(control1);
????????????????form1.Controls.Add(control2); 比較簡單,就是路徑要和前面的一致。
后記:
首先感謝 Leepy? 同志認真踏實的精神,找出了我這篇文章中的一個BUG。
原來我的第四步:調用dll中的用戶控件,是一個web應用程序,如果是一個web站點的話就會出現問題。因為在VS2005中調試時這兩種方式呈現出來的Url是不一樣的:
web應用程序:http://localhost:****/Default.aspx
web站點?????:http://localhost:****/WebSite1/Default.aspx
也就是說我原來的程序沒有考慮到非根目錄部署的情況,針對這個BUG要修改的地方有(為了BUG的原始記錄,我就不在原文中修改了,把修改點列在下面):
1、GetCacheDependency方法:
GetCacheDependency
????public?override?System.Web.Caching.CacheDependency?GetCacheDependency(string?virtualPath,
???????????System.Collections.IEnumerable?virtualPathDependencies,?DateTime?utcStart)
????{
????????if?(IsAppResourcePath(virtualPath))
????????{
????????????string?path?=?HttpRuntime.BinDirectory;
????????????return?new?System.Web.Caching.CacheDependency(path);
????????}
????????else
????????{
????????????return?Previous.GetCacheDependency(virtualPath,?virtualPathDependencies,?utcStart);
????????}
????} 這里改成直接改成當前網站的bin目錄還可以省掉建空目錄的步驟了
2、在調用的地方修改成以下方式:
????????Control?control1?=?this.LoadControl("~/MyUserControl/MyWebApplication.dll/MyWebApplication.Sample1.ascx");
????????Control?control2?=?this.LoadControl("~/MyUserControl/MyWebApplication.dll/MyWebApplication.Sample2.ascx");
????????form1.Controls.Add(control1);
????????form1.Controls.Add(control2);
?
轉載于:https://www.cnblogs.com/firstyi/archive/2008/04/19/1161431.html
總結
以上是生活随笔為你收集整理的Asp.Net中虚拟文件系统的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 给FlvDownloader加了一个视频
- 下一篇: js window.event 对象学习