How can I add the result of an ASP.NET MVC controller action to a Bundle?

后端 未结 3 1620
南方客
南方客 2021-02-04 12:26

I have a controller action that returns Javascript file. I can reference this file from my view and it works fine. I\'d like to put it in a System.Web.Optimization.Bundle with t

3条回答
  •  孤街浪徒
    2021-02-04 13:01

    Here is what I did for this scenario. I defined a "Bundle Result" and then in my Controller method, just returned a Bundle by name. I am using ETags (If-None-Match Header) as an optimization for client caching.

    eg:

    public ActionResult ReturnFooBundle()
    {
        return new BundleResult("foo", TimeSpan.FromDays(7));
    }
    

    Here is the BundleResult implementation:

    public class BundleResult
        : ActionResult
    {
        private class BundleInfo
        {
            public string BundleETag;
            public DateTime LastModified;
            public Bundle TheBundle;
            public BundleResponse Response;
        }
    
        private static Dictionary _bundleCache = new Dictionary();
    
        public string BundleName { get; private set; }
        public TimeSpan CacheExpiry { get; private set; }
    
        public BundleResult(string bundleName, TimeSpan cacheExpiry)
        {
            BundleName = bundleName;
            CacheExpiry = cacheExpiry;
        }
        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.Clear();
            BundleInfo bundleInfo = GetBundle(context.HttpContext);
    
            string requestETag = context.HttpContext.Request.Headers["If-None-Match"];
            if (!string.IsNullOrEmpty(requestETag) && (requestETag == bundleInfo.BundleETag))
            {
                context.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified;
                context.HttpContext.Response.StatusDescription = "Not Modified";
                return;
            }
            else
            {
                BundleResponse bundleResponse = bundleInfo.Response;
                HttpResponseBase response = context.HttpContext.Response;
                response.Write(bundleResponse.Content);
                response.ContentType = bundleResponse.ContentType;
    
                HttpCachePolicyBase cache = response.Cache;
                cache.SetCacheability(HttpCacheability.ServerAndPrivate);
                cache.SetLastModified(bundleInfo.LastModified);
                cache.SetETag(bundleInfo.BundleETag);
            }
        }
    
        private BundleInfo GetBundle(HttpContextBase context)
        {
            // lookup the BundleResponse
            BundleInfo retVal;
            lock (_bundleCache)
            {
                _bundleCache.TryGetValue(BundleName, out retVal);
            }
            if(retVal != null)
            {
    #if DEBUG
                // see if the contents have been modified.
                BundleContext bundleContext = new BundleContext(context, BundleTable.Bundles, BundleName);
                DateTime lastModified = retVal.TheBundle.EnumerateFiles(bundleContext).Select(fi => fi.LastWriteTimeUtc).Max();
                if (lastModified > retVal.LastModified)
                {
                    // regenerate the bundleInfo
                    retVal = null;
                }
    #endif
            }
            if (retVal == null)
            {
                string rawBundleName = BundleTable.Bundles.ResolveBundleUrl(BundleName);
                string hash = rawBundleName.Substring(rawBundleName.IndexOf("?v=") + 3);
                Bundle bundle = BundleTable.Bundles.GetBundleFor(BundleName);
                BundleContext bundleContext = new BundleContext(context, BundleTable.Bundles, BundleName);
                BundleResponse bundleResponse = bundle.GenerateBundleResponse(bundleContext);
                DateTime lastModified = bundle.EnumerateFiles(bundleContext).Select(fi => fi.LastWriteTimeUtc).Max();
                retVal = new BundleInfo
                {
                    BundleETag = hash,
                    Response = bundleResponse,
                    TheBundle = bundle,
                    LastModified = lastModified,
                };
                lock (_bundleCache)
                {
                    _bundleCache[BundleName] = retVal;
                }
            }
            return retVal;
        }
    }
    

提交回复
热议问题