在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);

转载于:https://www.cnblogs.com/firstyi/archive/2008/04/19/1161431.html

Asp.Net中虚拟文件系统的使用相关推荐

  1. 基于ASP.NET Core的模块化设计: 虚拟文件系统

    土牛亲自录制的本文介绍视频 Abp中文网(https://cn.abp.io/)提供翻译字幕 基于ASP.NET Core的模块化设计: 虚拟文件系统 简介 创建模块化的应用程序很困难. 构建模块化的 ...

  2. 【Linux 内核】Linux 操作系统结构 ( Linux 内核在操作系统中的层级 | Linux 内核子系统及关系 | 进程调度 | 内存管理 | 虚拟文件系统 | 网络管理 | 进程间通信 )

    文章目录 一.Linux 内核在操作系统中的层级 二.Linux 内核子系统 三.Linux 内核子系统之间的关系 一.Linux 内核在操作系统中的层级 Linux 内核 所在层级 : 整个计算机系 ...

  3. Emscripten中的虚拟文件系统

    一.加载文件(读数据) 使用fopen,fread等操作. 编译选项中添加: --preload-file a.data 二.写数据 只有MEMFS文件系统是默认包含的,其他必须使用链接标志使能. N ...

  4. Gox语言中使用内存虚拟文件系统提升IO处理速度-GX43.1

    Gox语言中,1.06a版本以上,可以利用内置的github.com/topxeq/afero包来将内存中虚拟出一个文件系统.这样,如果内存足够大,完全可以利用它来提升一些文件IO处理的效率. 该包实 ...

  5. ABP虚拟文件系统(VirtualFileSystem)实例------定制菜单栏显示用户姓名

    ABP默认的MVC启动模板在登录后, 右上角显示的是用户名: 如果想让它显示用户的姓名该如何做呢?这就需要用到ABP一个非常强大的功能------虚拟文件系统. 前期准备 使用ABP CLI创建一个名 ...

  6. asp net服务器虚拟路径,asp.net获取服务器虚拟路径

    ASP.NET获取路径的方法 原文:[转载]ASP.NET获取路径的方法 HttpContext.Current.Request.PhysicalPath;获得当前页面的完整物理路径.比如 F:\XF ...

  7. 在ASP.NET中跟踪和恢复大文件下载

    在Web应用程序中处理大文件下载的问题一直出了名的困难,因此对于大多数站点来说,如果用户的下载被中断了,它们只能说悲哀降临到用户的身上了.但是我们现在不必这样了,因为你可以使自己的ASP.NET应用程 ...

  8. 如何在ASP.Net 中把图片存入数据库

    介绍 可能有很多的时候,我们急需把图片存入到数据库当中.在一些应用程序中,我们可能有一些敏感的资料,由于存储在文件系统(file system)中的东西,将很容易被某些用户盗取,所以这些数据不能存放在 ...

  9. 在ASP.NET中随意创建图形信息

    如果没有一个外部组件的支持,在ASP中是不能动态创建图形的,不管它是一个图表,一个横幅或仅仅是一个图形计数器.可喜的是,这一点在ASP.NET中改变了.现在,我们只需要使用内置功能,就能够很容易动态创 ...

最新文章

  1. win7 打开“计算机”慢,win7电脑启动慢解决方法
  2. java semaphore 等待_Java并发编程系列之Semaphore详解
  3. 解决:A component required a bean of type ‘javax.jms.Queue‘ that could not be found.
  4. iOS 获取手机信息
  5. 谷歌浏览器调用本地exe_无需修改前端和后端代码本地跨域开发设置
  6. Java compiler level does not match the version of the installed Java project fac
  7. 基于MyEclipse+Mysql+Tomcat+SSH开发的运动会管理系统
  8. 局域网服务器的安全管理与维护,局域网组建与维护
  9. python是一种解释型、面向什么的计算机程序设计语言_Python \解释型计算机程序设计语言...
  10. PayPal付款状态解释-中英文对照
  11. 两部手机怎样才能把数据都传过来_两个手机如何互传照片、文件 ,教你四大绝招...
  12. idea切换工作空间_IDEA中如何在一个工作空间中管理多个项目
  13. socket.io实现简易版群聊
  14. QT实现Qt3D材质系统加载PBR材料
  15. 新版《鹿鼎记》史上最低分!今天用数据分析告诉你韦小宝跟哪个老婆最亲
  16. 中国防卫科技学院计算机,2014高考专业介绍:科技防卫
  17. 坑爹大冒险html5游戏在线玩,《史上最坑爹的大冒险》 图文全通关攻略
  18. R语言用quantstrat包获取股票、债券、基金、黄金、原油、指数、外汇和全球经济数据
  19. Java中var类型的用法和使用var的注意事项和使用var的优缺点
  20. 将la,lb链表合并成lc。

热门文章

  1. 操作系统(十五)调度算法的评价指标
  2. C语言再学习 -- 声明与定义
  3. 【译】A gentle introduction to self-sovereign identity
  4. How to save your Ethereum Dapp users from paying gas for transactions
  5. 谈谈离散卷积和卷积神经网络
  6. Kafka基础知识入门
  7. morlet小波matlab代码,morlet小波matlab程序
  8. java同名类_java两个不同名类 在里面建立两个同名的类 怎么破
  9. julia 调用python库_Julia调用Python实现超像素分割SLIC算法
  10. java代码分类_08 java代码块的概述和分类