Is DiskCacheProvider in ASP.Net 4.0 really exist?

2019-06-10 09:45发布

I read many places said the new feature in ASP.net 4.0, and the code is:

    <caching>
        <outputCache defaultProvider="AspNetInternalProvider">
            <providers>
                <add name="DiskCache"
                    type="test.OutputCacheEx.DiskOutputCacheProvider, DiskCacheProvider"/>
            </providers>
        </outputCache>
    </caching>

Anyway, I cannot get it work, I change the code inside out, no use. I cannot only find 1 cache provider from Microsoft which shipping with asp.net is AspNetInternalProvider

So, Is DiskOutputCacheProvider really exist? If yes, how to use it.

Also, I need to use it in Azure, so I guess is here must have a place for disk cache to setup cache folder, right?

If anyone has a disk cache solution for azure (use LocalResources.LocalStorage or not), please share with me, free or paid. Thanks.

2条回答
该账号已被封号
2楼-- · 2019-06-10 10:14
// Based on code by 'Scott Mitchell' <mitchell@4guysfromrolla.com>
// http://www.4guysfromrolla.com/articles/061610-1.aspx

// Add the following to Web.config
// Use the cacheFolder attribute to specify the disk location for the cache
//
// <system.web>
//    <caching>
//       <outputCache enableOutputCache="true" defaultProvider="disk">
//          <providers>
//             <add name="disk" type="DiskOutputCache.DiskOutputCacheProvider, DiskOutputCache" cacheFolder="~/App_Data/OutputCache" />
//          </providers>
//       </outputCache>
//    </caching>
// </system.web> 

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Web;
using System.Web.Caching;

namespace DiskOutputCache {

   /// <summary>
   /// An <see cref="OutputCacheProvider"/> that uses the file system for storage.
   /// </summary>
   public class DiskOutputCacheProvider : OutputCacheProvider {

      readonly IDictionary<string, CacheItem> cacheItems = new ConcurrentDictionary<string, CacheItem>();
      string cacheFolder;

      public override void Initialize(string name, NameValueCollection config) {

         HttpServerUtility serverUtil = HttpContext.Current.Server;

         const string cacheFolderKey = "cacheFolder";
         string cacheFolderValue = config[cacheFolderKey];
         string folder;

         if (!String.IsNullOrEmpty(cacheFolderValue)) {

            folder = serverUtil.MapPath(cacheFolderValue);

            config.Remove(cacheFolderKey);

         } else {
            throw new ArgumentException(String.Format("The attribute '{0}' is missing in the configuration of the '{1}' provider.", cacheFolderKey, name));
         }

         if (folder[folder.Length - 1] != Path.DirectorySeparatorChar)
            folder += Path.DirectorySeparatorChar;

         if (!Directory.Exists(folder))
            Directory.CreateDirectory(folder);

         this.cacheFolder = folder;

         base.Initialize(name, config);
      }

      public override object Add(string key, object entry, DateTime utcExpiry) {

         // See if this key already exists in the cache. If so, we need to return it and NOT overwrite it!
         object results = Get(key);

         if (results != null)
            return results;

         // If the item is NOT in the cache, then save it!
         Set(key, entry, utcExpiry);

         return entry;
      }

      public override object Get(string key) {

         CacheItem item;

         if (!this.cacheItems.TryGetValue(key, out item))
            return null;

         if (item.UtcExpiry < DateTime.UtcNow) {

            // Item has expired
            Remove(key, item);

            return null;
         }

         return GetCacheData(item);
      }

      object GetCacheData(CacheItem item) {

         string fileToRetrieve = GetFilePath(item);

         BinaryFormatter formatter = new BinaryFormatter();
         Stream source = null;

         try {
            source = new FileStream(fileToRetrieve, FileMode.Open, FileAccess.Read, FileShare.Read);

            return formatter.Deserialize(source);

         } catch (IOException) {

         } finally {
            if (source != null)
               source.Dispose();
         }

         return null;
      }

      public override void Remove(string key) {

         CacheItem item;

         if (this.cacheItems.TryGetValue(key, out item)) 
            Remove(key, item);
      }

      void Remove(string key, CacheItem item) {

         RemoveCacheData(item);
         this.cacheItems.Remove(key);
      }

      void RemoveCacheData(CacheItem item) {

         string fileToDelete = GetFilePath(item);

         try {
            File.Delete(fileToDelete);
         } catch (IOException) { }
      }

      public override void Set(string key, object entry, DateTime utcExpiry) {

         // Create a DiskOutputCacheItem object
         CacheItem item = new CacheItem(key, utcExpiry);

         WriteCacheData(item, entry);

         // Add item to CacheItems, if needed, or update the existing key, if it already exists
         this.cacheItems[key] = item;
      }

      void WriteCacheData(CacheItem item, object entry) {

         string fileToWrite = GetFilePath(item);

         BinaryFormatter formatter = new BinaryFormatter();
         Stream destination = null;

         try {
            destination = new FileStream(fileToWrite, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            formatter.Serialize(destination, entry);

         } catch (IOException) {

         } finally {
            if (destination != null)
               destination.Dispose();
         }
      }

      string GetFilePath(CacheItem item) {
         return this.cacheFolder + item.FileName;
      }

      class CacheItem {

         static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars();

         public string FileName { get; private set; }
         public DateTime UtcExpiry { get; private set; }

         public CacheItem(string key, DateTime utcExpiry) {

            this.FileName = GetSafeFileName(key);
            this.UtcExpiry = utcExpiry;
         }

         string GetSafeFileName(string unsafeFileName) {

            char[] invalid = unsafeFileName.ToCharArray()
               .Where(c => invalidFileNameChars.Contains(c))
               .ToArray();

            if (invalid.Length > 0) {

               var sb = new StringBuilder(unsafeFileName, unsafeFileName.Length);

               for (int i = 0; i < invalid.Length; i++) 
                  sb.Replace(invalid[i], '_');

               return sb.ToString(); 
            }

            return unsafeFileName;
         }
      }
   }
}
查看更多
不美不萌又怎样
3楼-- · 2019-06-10 10:20

The DiskCacheOutputProvider is not include in .net 4.0 no. But you can extend .net 4.0 caching and create your own. There are some examples online of how this is done.

http://weblogs.asp.net/scottgu/archive/2010/01/27/extensible-output-caching-with-asp-net-4-vs-2010-and-net-4-0-series.aspx

The implementation you are looking for can be found here

** http://aspnet.4guysfromrolla.com/code/ExtensibleOutputCachingDemo.zip ** Sourced from http://www.4guysfromrolla.com/articles/061610-1.aspx

It is just sample code and not ready for prime time so beware of using this. You have to wire it all up in the web.config.

查看更多
登录 后发表回答