カスタムVirtualPathProviderマッピングASP.NET MVC View
25720 ワード
複数のASPがあるとする.NET MVCアプリケーションソリューションは、Areaに基づいて同じサイトを展開します.複数のサイトは一貫した方法でレイアウトを切り替える必要があり、AreaがViewをマッピングする方法によって{AreaName}{Views}の形式で保存されます.このようなアクセス方式に比べて、複数のAreaに関連付けられたViewを固定ディレクトリに更新すると、App_などの管理が容易になります.Themes\{SkinName}\Views\{AreaName}\.カスタムViewEngineは関連付けることができます.もう1つの方法は、VirtualPathProviderをカスタマイズすることです.例えば/Views/Home/Indexを要求する.cshtml,ASP.NETは、VirtualPathProviderのFileExistsからパスが存在するかどうかを尋ね、存在する場合はGetFileを呼び出してVirtualFileを取得し続けます.ビューのコンテンツをデータベースに保存したり、マッピングプロファイルを追加したりすることができます.例えば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 }