zoukankan      html  css  js  c++  java
  • 自定义VirtualPathProvider映射ASP.NET MVC View

    假设有多个ASP.NET MVC 应用解决方案,基于Area部署同一个站点。多个站点需要以一致的方式进行布局切换,不同Area映射View的方式不同,它们都以{AreaName}\{Views}的格式存放。相比这种访问方式,将多个Area关联的View更新到一个固定目录更便于管理,比如:App_Themes\{SkinName}\Views\{AreaName}\。自定义ViewEngine可以关联起来,还有一种方式就是自定义VirtualPathProvider。比如当请求一个/Views/Home/Index.cshtml,ASP.NET会通过VirtualPathProvider的FileExists询问路径是否存在,如果存在则会继续调用GetFile获取一个VirtualFile。我们可以将一个View的内容存放到数据库或者添加一个映射配置文件。比如对于A应用的Index.cshtml的虚拟路径:/A/Views/Home/Index.cshtml实际映射到/App_Themes/{SkinName}/Views/A/Index.cshtml,只需要继承于VirtualFile并重写Open函数。下面是一个简单示例:

    1 <?xml version="1.0" encoding="utf-8" ?>
    2 <map>
    3   <view virtualPath="" mapTo="" />
    4 </map>
     1 /// <summary>
     2 /// 视图映射
     3 /// </summary>
     4 [XmlType(TypeName = "view")]
     5 public class ViewMap
     6 {
     7     /// <summary>
     8     /// 虚拟路径
     9     /// </summary>
    10     [XmlAttribute(AttributeName = "virtualPath")]
    11     public String VirtualPath { get; set; }
    12 
    13     /// <summary>
    14     /// 映射到
    15     /// </summary>
    16     [XmlAttribute(AttributeName = "mapTo")]
    17     public String MapTo { get; set; }
    18 }
      1 /// <summary>
      2 /// 视图映射路径提供器
      3 /// </summary>
      4 public sealed class ViewMapPathProvider : VirtualPathProvider
      5 {
      6     /// <summary>
      7     /// 序列化提供器
      8     /// </summary>
      9     private static readonly XmlSerializer SerializeProvider;
     10 
     11     /// <summary>
     12     /// 静态构造函数
     13     /// </summary>
     14     static ViewMapPathProvider()
     15     {
     16         SerializeProvider = new XmlSerializer(typeof(List<ViewMap>), new XmlRootAttribute("map"));
     17     }
     18 
     19     private IDictionary<String, ViewMap> m_views;
     20     private FileSystemWatcher m_fileWatcher;
     21 
     22     /// <summary>
     23     /// 构造函数
     24     /// </summary>
     25     /// <param name="xmlPath">文件路径</param>
     26     public ViewMapPathProvider(String xmlPath)
     27     {
     28         if (String.IsNullOrEmpty(xmlPath))
     29             throw new ArgumentException("xmlPath不能为空");
     30 
     31         if (!File.Exists(xmlPath))
     32             throw new FileNotFoundException(String.Format("文件{0}不存在", xmlPath));
     33 
     34         this.XmlPath = xmlPath;
     35 
     36         m_fileWatcher = new FileSystemWatcher(Path.GetDirectoryName(xmlPath));
     37         m_fileWatcher.Changed += new FileSystemEventHandler(OnFileChanged);
     38     }
     39 
     40     /// <summary>
     41     /// 文件路径
     42     /// </summary>
     43     public String XmlPath { get; private set; }
     44 
     45     /// <summary>
     46     /// 视图集合
     47     /// </summary>
     48     public IDictionary<String, ViewMap> Views
     49     {
     50         get
     51         {
     52             if (m_views == null)
     53             {
     54                 using (TextReader textReader = new StreamReader(this.XmlPath, true))
     55                 {
     56                     List<ViewMap> views = SerializeProvider.Deserialize(textReader) as List<ViewMap>;
     57 
     58                     m_views = views.ToDictionary(p => p.VirtualPath);
     59                 }
     60             }
     61 
     62             return m_views;
     63         }
     64     }
     65 
     66     /// <summary>
     67     /// 文件是否存在
     68     /// </summary>
     69     /// <param name="virtualPath">虚拟路径</param>
     70     /// <returns>是否存在</returns>
     71     public override Boolean FileExists(String virtualPath)
     72     {
     73         if (this.Views.ContainsKey(virtualPath))
     74             return true;
     75 
     76         return base.FileExists(virtualPath);
     77     }
     78 
     79     /// <summary>
     80     /// 获取文件
     81     /// </summary>
     82     /// <param name="virtualPath">虚拟路径</param>
     83     /// <returns>虚拟文件</returns>
     84     public override VirtualFile GetFile(String virtualPath)
     85     {
     86         if (this.Views.ContainsKey(virtualPath))
     87         {
     88             ViewMap viewMap = this.Views[virtualPath];
     89 
     90             return new ViewMapFile(virtualPath, viewMap);
     91         }
     92 
     93         return base.GetFile(virtualPath);
     94     }
     95 
     96     /// <summary>
     97     /// 文件变化
     98     /// </summary>
     99     /// <param name="sender">发送方</param>
    100     /// <param name="e">事件参数</param>
    101     private void OnFileChanged(Object sender, FileSystemEventArgs e)
    102     {
    103         if (String.Equals(e.FullPath, this.XmlPath, StringComparison.CurrentCultureIgnoreCase))
    104             m_views = null;
    105     }
    106 }
     1 /// <summary>
     2 /// 视图映射文件
     3 /// </summary>
     4 public class ViewMapFile : VirtualFile
     5 {
     6     /// <summary>
     7     /// 构造函数
     8     /// </summary>
     9     /// <param name="virtualPath">虚拟路径</param>
    10     /// <param name="viewMap">视图映射</param>
    11     public ViewMapFile(String virtualPath, ViewMap viewMap)
    12         : base(virtualPath)
    13     {
    14         this.ViewMap = viewMap;
    15     }
    16 
    17     /// <summary>
    18     /// 视图映射
    19     /// </summary>
    20     public ViewMap ViewMap { get; private set; }
    21 
    22     /// <summary>
    23     /// 打开
    24     /// </summary>
    25     /// <returns></returns>
    26     public override Stream Open()
    27     {
    28         return new FileStream(this.ViewMap.MapTo, FileMode.Open, FileAccess.Read);
    29     }
    30 }
     1 /// <summary>
     2 /// 启动
     3 /// </summary>
     4 protected void Application_Start()
     5 {
     6     AreaRegistration.RegisterAllAreas();
     7 
     8     RegisterGlobalFilters(GlobalFilters.Filters);
     9     RegisterRoutes(RouteTable.Routes);
    10 
    11     String xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"App_Data\ViewMap.xml");
    12     HostingEnvironment.RegisterVirtualPathProvider(new ViewMapPathProvider(xmlPath));
    13 }
  • 相关阅读:
    如何高效的学习技术
    面试连环炮系列(二十三): StringBuffer与StringBuild的区别
    面试连环炮系列(二十二):常用的设计模式有哪些
    算法天天练709:字符串转小写
    面试连环炮系列(二十一):你们的项目怎么使用kafka
    算法天天练771:查找字符串出现的次数
    初次进入职场如何工作与学习
    面试连环炮系列(二十):TCP的滑动窗口协议是什么
    算法天天练334:字符串翻转
    面试连环炮系列(十九):分布式锁的实现方案
  • 原文地址:https://www.cnblogs.com/junchu25/p/2631125.html
Copyright © 2011-2022 走看看