1 using System.Collections; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Text; 6 using System.Web.UI; 7 using System.Web.UI.WebControls; 8 using System.Collections.Specialized; 9 using System.Diagnostics; 10 using System.Web.Resources; 11 using System.Globalization; 12 using System.Web.Caching; 13 using System.Web.Hosting; 14 15 namespace System.Web.DynamicData { FileChangedCallback(string path)16 delegate void FileChangedCallback(string path); 17 18 class FileChangeNotifier { 19 private static VirtualPathProvider _vpp; 20 21 internal static VirtualPathProvider VirtualPathProvider { 22 private get { 23 if (_vpp == null) { 24 _vpp = HostingEnvironment.VirtualPathProvider; 25 } 26 return _vpp; 27 } 28 // For unit test purpose 29 set { 30 _vpp = value; 31 } 32 } 33 34 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", 35 MessageId = "System.Web.DynamicData.FileChangeNotifier", 36 Justification="The object deals with file change notifications and we don't need to hold on to it")] Register(string virtualPath, FileChangedCallback onFileChanged)37 internal static void Register(string virtualPath, FileChangedCallback onFileChanged) { 38 new FileChangeNotifier(virtualPath, onFileChanged); 39 } 40 41 private FileChangedCallback _onFileChanged; 42 FileChangeNotifier(string virtualPath, FileChangedCallback onFileChanged)43 private FileChangeNotifier(string virtualPath, FileChangedCallback onFileChanged) { 44 _onFileChanged = onFileChanged; 45 RegisterForNextNotification(virtualPath); 46 } 47 RegisterForNextNotification(string virtualPath)48 private void RegisterForNextNotification(string virtualPath) { 49 // Get a CacheDependency from the BuildProvider, so that we know anytime something changes 50 var virtualPathDependencies = new List<string>(); 51 virtualPathDependencies.Add(virtualPath); 52 CacheDependency cacheDependency = VirtualPathProvider.GetCacheDependency( 53 virtualPath, virtualPathDependencies, DateTime.UtcNow); 54 55 // Rely on the ASP.NET cache for file change notifications, since FileSystemWatcher 56 // doesn't work in medium trust 57 HttpRuntime.Cache.Insert(virtualPath /*key*/, virtualPath /*value*/, cacheDependency, 58 Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, 59 CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(OnCacheItemRemoved)); 60 } 61 OnCacheItemRemoved(string key, object value, CacheItemRemovedReason reason)62 private void OnCacheItemRemoved(string key, object value, CacheItemRemovedReason reason) { 63 64 // We only care about dependency changes 65 if (reason != CacheItemRemovedReason.DependencyChanged) 66 return; 67 68 _onFileChanged(key); 69 70 // We need to register again to get the next notification 71 RegisterForNextNotification(key); 72 } 73 } 74 } 75 76