private void MaybeCacheView(string view_key, CalendarRenderer.ViewRenderer view_renderer, ElmcityCacheDependency dependency, Dictionary<string,object> render_args) { if (this.test) return; if (this.cr.cache[view_key] == null) { var view_str = this.cr.RenderDynamicViewWithoutCaching(this.controller.ControllerContext, view_renderer, this.view, this.count, this.from, this.to, render_args); byte[] view_bytes = Encoding.UTF8.GetBytes(view_str); var cache = new AspNetCache(this.controller.HttpContext.Cache); this.controller.InsertIntoCache(cache, view_bytes, dependency, view_key); } }
public override void ExecuteResult(ControllerContext context) { // for dynamic views derived from the static file // which is the base object for this id, e.g.: // http://elmcity.blob.core.windows.net/a2cal/a2cal.zoneless.obj // cache the base object if uncached var base_key = Utils.MakeBaseZonelessUrl(this.id); if (this.cr.cache[base_key] == null) { var bytes = HttpUtils.FetchUrl(new Uri(base_key)).bytes; //InsertIntoCache(bytes, ElmcityUtils.Configurator.cache_sliding_expiration, dependency: null, key: base_key); var cache = new AspNetCache(this.controller.HttpContext.Cache); this.controller.InsertIntoCache( cache, bytes, dependency: null, key: base_key); } // uri for static content, e.g.: // http://elmcity.blob.core.windows.net/a2cal/a2cal.stats.html // http://elmcity.blob.core.windows.net/a2cal/a2cal.search.html // these generated files could be served using their blob urls, but // here are repackaged into the /services namespace, e.g.: // http://elmcity.cloudapp.net/services/a2cal/stats // http://elmcity.cloudapp.net/services/a2cal/search var blob_uri = BlobStorage.MakeAzureBlobUri(this.id, this.id + "." + this.type, false); // cache static content var blob_key = blob_uri.ToString(); if (cacheable_types.Exists(t => t == this.type) && this.cr.cache[blob_key] == null) { var bytes = HttpUtils.FetchUrl(blob_uri).bytes; var dependency = new ElmcityCacheDependency(base_key); var cache = new AspNetCache(this.controller.HttpContext.Cache); this.controller.InsertIntoCache(cache, bytes, dependency, base_key); } var fmt = "{0:yyyyMMddTHHmm}"; var from_str = string.Format(fmt, this.from); var to_str = string.Format(fmt, this.to); var test_arg = this.test ? "yes" : ""; var raw_arg = this.raw ? "yes" : ""; var view_key = Utils.MakeViewKey(this.id, this.type, this.view, this.count.ToString(), from_str, to_str, this.eventsonly, this.mobile, test:test_arg, raw:raw_arg, style:this.style, theme:this.theme); var render_args = new Dictionary<string, object>(); switch (this.type) { case "html": render_args["view"] = this.view; render_args["test"] = this.test; render_args["style"] = this.style; render_args["theme"] = this.theme; render_args["mobile"] = false; render_args["ua"] = ""; render_args["css"] = this.cr.calinfo.css; // need to extract and pass along the default theme name render_args["taglist"] = String.IsNullOrEmpty(this.taglist) ? true : this.taglist.ToLower().StartsWith("n"); bool mobile_declared = this.mobile.ToLower().StartsWith("y"); bool is_mobile; if (settings["use_mobile_detection"] == "yes") // detect or use declaration { bool smartphone_detected = TryDetectSmartPhone(render_args); is_mobile = smartphone_detected || mobile_declared; } else is_mobile = mobile_declared; // use declaration only if ( this.mobile.ToLower().StartsWith("n") ) // maybe override with refusal is_mobile = false; if (is_mobile) { //this.count = Convert.ToInt32(settings["mobile_event_count"]); // no, let the renderer reduce the list render_args["mobile_event_count"] = Convert.ToInt32(settings["mobile_event_count"]); render_args["mobile"] = true; this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtmlForMobile); view_key = Utils.MakeViewKey(this.id, this.type, this.view, this.count.ToString(), from_str, to_str, eventsonly: "yes", mobile: "yes", test:test_arg, raw:raw_arg, style:this.style, theme:this.theme); } /* for dynamic event paging, not used now else if (this.raw) { this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtmlEventsOnlyRaw); render_args["raw_sentinel"] = this.raw_sentinel; view_key = Utils.MakeViewKey(this.id, this.type, this.view, this.count.ToString(), from_str, to_str, eventsonly: null, mobile: null, test:test_arg, raw: raw_arg, style:this.style, theme:this.theme); }*/ else if (this.eventsonly == "yes") { this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtmlEventsOnly); view_key = Utils.MakeViewKey(this.id, this.type, this.view, this.count.ToString(), from_str, to_str, eventsonly: "yes", mobile: "", test:test_arg, raw:raw_arg, style:this.style, theme:this.theme); } else this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtml); //if (is_mobile) // GenUtils.LogMsg("info", "EventsResult", JsonConvert.SerializeObject(render_args)); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), render_args); this.response_body = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, render_args); new ContentResult { ContentType = "text/html", Content = this.response_body, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "xml": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderXml); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); this.response_body = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, null); new ContentResult { ContentType = "text/xml", Content = this.response_body, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "rss": if (count == 0) count = CalendarAggregator.Configurator.rss_default_items; this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderRss); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); this.response_body = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, null); new ContentResult { ContentType = "text/xml", Content = response_body, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "json": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderJson); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); string jcontent = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, null); if (this.jsonp != null) jcontent = this.jsonp + "(" + jcontent + ")"; new ContentResult { ContentEncoding = UTF8, ContentType = "application/json", Content = jcontent }.ExecuteResult(context); break; case "tags_json": string tjcontent = cr.RenderTagCloudAsJson(); if (this.jsonp != null) tjcontent = this.jsonp + "(" + tjcontent + ")"; new ContentResult { ContentEncoding = UTF8, ContentType = "application/json", Content = tjcontent, }.ExecuteResult(context); break; case "tags_html": string thcontent = cr.RenderTagCloudAsHtml(); new ContentResult { ContentEncoding = UTF8, ContentType = "text/html", Content = thcontent, }.ExecuteResult(context); break; case "stats": blob_uri = BlobStorage.MakeAzureBlobUri(this.id, this.id + ".stats.html",false); //this.response_bytes = (byte[])CacheUtils.RetrieveBlobAndEtagFromServerCacheOrUri(this.cr.cache, blob_uri)["response_body"]; this.response_bytes = HttpUtils.FetchUrl(blob_uri).bytes; new ContentResult { ContentEncoding = UTF8, ContentType = "text/html", Content = Encoding.UTF8.GetString(this.response_bytes), }.ExecuteResult(context); break; case "ics": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderIcs); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); string ics_text = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, null); new ContentResult { ContentType = "text/calendar", Content = ics_text, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "jswidget": new ContentResult { ContentType = "text/html", Content = cr.RenderJsWidget(), ContentEncoding = UTF8 }.ExecuteResult(context); break; case "search": blob_uri = BlobStorage.MakeAzureBlobUri(this.id, this.id + ".search.html",false); this.response_bytes = (byte[])CacheUtils.RetrieveBlobAndEtagFromServerCacheOrUri(this.cr.cache, blob_uri)["response_body"]; new ContentResult { ContentType = "text/html", Content = Encoding.UTF8.GetString(this.response_bytes), ContentEncoding = UTF8 }.ExecuteResult(context); break; case "today_as_html": new ContentResult { ContentType = "text/html", Content = cr.RenderTodayAsHtml(), ContentEncoding = UTF8 }.ExecuteResult(context); break; } }
public void InsertIntoCache(AspNetCache cache, byte[] bytes, ElmcityCacheDependency dependency, string key) { var logger = new CacheItemRemovedCallback(AspNetCache.LogRemovedItemToAzure); var expiration_hours = ElmcityUtils.Configurator.cache_sliding_expiration.Hours; var sliding_expiration = new TimeSpan(expiration_hours, 0, 0); cache.Insert(key, bytes, dependency, Cache.NoAbsoluteExpiration, sliding_expiration, CacheItemPriority.Normal, logger); }
public void MaybeCacheDependentObject(string url, string base_key) { if (this.HttpContext.Cache[url] == null) { var bytes = HttpUtils.FetchUrlNoCache(new Uri(url)).bytes; var dependency = new ElmcityCacheDependency(base_key); var cache = new AspNetCache(this.HttpContext.Cache); InsertIntoCache(cache, bytes, dependency, url); } }
public override void ExecuteResult(ControllerContext context) { // for dynamic views derived from the static file // which is the base object for this id, e.g.: // http://elmcity.blob.core.windows.net/a2cal/a2cal.zoneless.obj // cache the base object if uncached var base_key = Utils.MakeBaseZonelessUrl(this.id); if (this.cr.cache[base_key] == null) { var bytes = HttpUtils.FetchUrl(new Uri(base_key)).bytes; //InsertIntoCache(bytes, ElmcityUtils.Configurator.cache_sliding_expiration, dependency: null, key: base_key); var cache = new AspNetCache(this.controller.HttpContext.Cache); this.controller.InsertIntoCache( cache, bytes, dependency: null, key: base_key); } // uri for static content, e.g.: // http://elmcity.blob.core.windows.net/a2cal/a2cal.stats.html // http://elmcity.blob.core.windows.net/a2cal/a2cal.search.html // these generated files could be served using their blob urls, but // here are repackaged into the /services namespace, e.g.: // http://elmcity.cloudapp.net/services/a2cal/stats // http://elmcity.cloudapp.net/services/a2cal/search var blob_uri = BlobStorage.MakeAzureBlobUri(this.id, this.id + "." + this.type, false); // cache static content var blob_key = blob_uri.ToString(); if (cacheable_types.Exists(t => t == this.type) && this.cr.cache[blob_key] == null) { var bytes = HttpUtils.FetchUrl(blob_uri).bytes; var dependency = new ElmcityCacheDependency(base_key); var cache = new AspNetCache(this.controller.HttpContext.Cache); this.controller.InsertIntoCache(cache, bytes, dependency, base_key); } var fmt = "{0:yyyyMMddTHHmm}"; var from_str = string.Format(fmt, this.from); var to_str = string.Format(fmt, this.to); var render_args = new Dictionary<string, object>(); var view_key = Utils.MakeViewKey(this.id, this.type, this.view, this.count.ToString(), from_str, to_str, eventsonly: this.eventsonly, mobile: this.mobile, test: this.test, raw: this.raw, style: this.style, theme: this.theme, taglist: this.taglist, tags: this.tags, template: this.template, jsurl: this.jsurl, days: this.days, bare_events: this.bare_events, hub: this.hub, source: this.source, first: this.first.ToString()); switch (this.type) { case "html": render_args["view"] = this.view; render_args["test"] = this.test; // obsolete? render_args["style"] = this.style; render_args["theme"] = this.theme; render_args["mobile_detected"] = false; // unused for now render_args["ua"] = ""; render_args["css"] = this.cr.calinfo.css; // need to extract and pass along the default theme name render_args["taglist"] = this.taglist; render_args["template"] = this.template; render_args["jsurl"] = this.jsurl; render_args["bare_events"] = this.bare_events; render_args["hub"] = this.hub; render_args["first"] = this.first; render_args["eventsonly"] = this.eventsonly; if (settings["use_mobile_detection"] == "yes") // detect or use declaration { this.mobile_detected = TryDetectSmartPhone(render_args); render_args["mobile_detected"] = this.mobile_detected; this.mobile = this.mobile_detected || this.mobile_declared; } else this.mobile = this.mobile_declared; // use declaration only if ( this.mobile_refused ) // maybe override with refusal this.mobile = false; if (this.mobile) { //this.count = Convert.ToInt32(settings["mobile_event_count"]); // no, let the renderer reduce the list render_args["mobile_event_count"] = Convert.ToInt32(settings["mobile_event_count"]); this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtmlForMobile); } else if (this.eventsonly) { this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtmlEventsOnly); } else { this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderHtml); } // update for mobile detection view_key = Utils.MakeViewKey(this.id, this.type, this.view, this.count.ToString(), from_str, to_str, eventsonly: this.eventsonly, mobile: this.mobile, test: this.test, raw: this.raw, style: this.style, theme: this.theme, taglist: this.taglist, tags: this.tags, template: this.template, jsurl: this.jsurl, days: this.days, bare_events: this.bare_events, hub: this.hub, source: this.source, first: this.first.ToString()); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), render_args); this.response_body = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, render_args); // let ajax pull events into pages directly this.controller.HttpContext.Response.Headers["Access-Control-Allow-Origin"] = "*"; new ContentResult { ContentType = "text/html", Content = this.response_body, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "xml": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderXml); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); this.response_body = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, null); new ContentResult { ContentType = "text/xml", Content = this.response_body, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "rss": if (count == 0) count = CalendarAggregator.Configurator.rss_default_items; this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderRss); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); this.response_body = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, null); new ContentResult { ContentType = "text/xml", Content = response_body, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "json": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderJson); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); string jcontent = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, null); if (this.jsonp != null) jcontent = this.jsonp + "(" + jcontent + ")"; new ContentResult { ContentEncoding = UTF8, ContentType = "application/json", Content = jcontent }.ExecuteResult(context); break; case "text": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderText); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); string tcontent = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, null); new ContentResult { ContentEncoding = UTF8, ContentType = "text/plain", Content = tcontent }.ExecuteResult(context); break; case "csv": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderCsv); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); string csv = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, null); new ContentResult { ContentEncoding = UTF8, ContentType = "text/plain", Content = csv }.ExecuteResult(context); break; case "tags_json": string tjcontent = cr.RenderTagCloudAsJson(); if (this.jsonp != null) tjcontent = this.jsonp + "(" + tjcontent + ")"; new ContentResult { ContentEncoding = UTF8, ContentType = "application/json", Content = tjcontent, }.ExecuteResult(context); break; case "tags_html": string thcontent = cr.RenderTagCloudAsHtml(); new ContentResult { ContentEncoding = UTF8, ContentType = "text/html", Content = thcontent, }.ExecuteResult(context); break; case "stats": blob_uri = BlobStorage.MakeAzureBlobUri(this.id, this.id + ".stats.html",false); //this.response_bytes = (byte[])CacheUtils.RetrieveBlobAndEtagFromServerCacheOrUri(this.cr.cache, blob_uri)["response_body"]; this.response_bytes = HttpUtils.FetchUrl(blob_uri).bytes; new ContentResult { ContentEncoding = UTF8, ContentType = "text/html", Content = Encoding.UTF8.GetString(this.response_bytes), }.ExecuteResult(context); break; case "ics": this.renderer = new CalendarRenderer.ViewRenderer(cr.RenderIcs); MaybeCacheView(view_key, this.renderer, new ElmcityCacheDependency(base_key), null); string ics_text = cr.RenderDynamicViewWithCaching(context, view_key, this.renderer, this.view, this.count, this.from, this.to, this.source, null); new ContentResult { ContentType = "text/calendar", Content = ics_text, ContentEncoding = UTF8 }.ExecuteResult(context); break; case "jswidget": new ContentResult { ContentType = "text/html", Content = cr.RenderJsWidget(), ContentEncoding = UTF8 }.ExecuteResult(context); break; case "today_as_html": new ContentResult { ContentType = "text/html", Content = cr.RenderTodayAsHtml(), ContentEncoding = UTF8 }.ExecuteResult(context); break; } }