Пример #1
0
 public ActionResult tag_cloud(string id)
 {
     ElmcityApp.logger.LogHttpRequest(this.ControllerContext);
     var url = BlobStorage.MakeAzureBlobUri(id, "tags.json", false);
     var base_key = Utils.MakeBaseZonelessUrl(id);
     MaybeCacheDependentObject(url.ToString(), base_key);
     // var page = HttpUtils.FetchUrlNoCache(url).DataAsString();
     var cache = new AspNetCache(this.HttpContext.Cache);
     var bytes = GetObjectFromCacheOrWeb(cache, url.ToString(), url.ToString());
     var page = Content(Encoding.UTF8.GetString(bytes), "application/json", UTF8);
     return page;
     //return Content(page, "application/json");
 }
Пример #2
0
            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;
                }
            }
Пример #3
0
            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);
                }
            }
Пример #4
0
 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);
 }
Пример #5
0
 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);
     }
 }
Пример #6
0
 public byte[] GetObjectFromCacheOrWeb(AspNetCache cache, string key, string url)
 {
     byte[] data;
     try
     {
         var object_is_cached = cache[key] != null;
         if (object_is_cached)
             data = (byte[])cache[key];
         else
         {
             var request = (HttpWebRequest)WebRequest.Create(new Uri(url));
             var response = HttpUtils.RetryHttpRequestExpectingStatus(request, HttpStatusCode.OK, data: null, wait_secs: 3, max_tries: 3, timeout_secs: TimeSpan.FromSeconds(10));
             if (response.status != HttpStatusCode.OK)
                 GenUtils.PriorityLogMsg("exception", "GetObjectFromCacheOrWeb: " + url, response.status.ToString());
             data = CacheUtils.MaybeSuppressResponseBodyForView(this.ControllerContext, response.bytes);
         }
     }
     catch (Exception e)
     {
         GenUtils.PriorityLogMsg("exception", "GetObjectFromCacheOrWeb: " + key + ", " + url, e.Message + e.StackTrace);
         data = Encoding.UTF8.GetBytes(e.Message);
     }
     return data;
 }
Пример #7
0
        public static void _ReloadSettingsAndRoutes()
        {
            GenUtils.LogMsg("status", "webrole _ReloadRoutes", null);

            bool new_routes = false;

            try
            {
                var settings = GenUtils.GetSettingsFromAzureTable();
                if (settings.Keys.Count == 0)
                    GenUtils.PriorityLogMsg("exception", "ReloadSettings: no settings!", null);
                else
                    ElmcityController.settings = settings;
            }
            catch (Exception e0)
            {
                var msg = "_ReloadSettingsAndRoutes: settings";
                GenUtils.PriorityLogMsg("exception", msg, e0.Message);
            }

            try
            {
                var themes = Utils.GetThemesDict();
                if (ObjectUtils.DictOfDictStrEqualsDictOfDictStr(themes, ElmcityController.themes) == false)
                {
                    GenUtils.LogMsg("status", "_ReloadSettingsAndRoutes", "reloading themes");
                    lock (ElmcityController.themes)
                    {
                        ElmcityController.themes = themes;
                    }
                }
            }
            catch (Exception e2)
            {
                var msg = "_ReloadSettingsAndRoutes: themes";
                GenUtils.PriorityLogMsg("exception", msg, e2.Message);
            }

            return;

            try
            {
                var new_wrd = WebRoleData.GetWrd();
                if (new_wrd == null || wrd.IsConsistent() == false)
                {
                    GenUtils.PriorityLogMsg("warning", "null or inconsistent WebRoleData!", null);
                    return;
                }

                if (new_wrd.ready_ids.Count != ElmcityApp.wrd.ready_ids.Count)  // did # of hubs change? either on initial load or subsequently
                {
                    new_routes = true;                                       // force rebuild of route map
                    GenUtils.LogMsg("status", "Reload: found a new hub", null);
                    WebRoleData.SaveTimestampedWrd(ElmcityApp.wrd);
                    lock (ElmcityApp.wrd)
                    {
                        ElmcityApp.wrd = new_wrd;                               // update WebRoleData (todo: rewarm caches affected)
                    }
                }

                foreach (var id in ElmcityApp.wrd.ready_ids)                  // did any hub's renderer change?
                {
                    var cached_renderer = ElmcityApp.wrd.renderers[id];
                    var current_renderer = Utils.AcquireRenderer(id);

                    if (cached_renderer.timestamp != current_renderer.timestamp) // timestamp changed
                    {
                        if (! Utils.RenderersAreEqual(cached_renderer, current_renderer, except_keys: new List<string>() { "timestamp" }) )
                        {
                            GenUtils.LogMsg("status", "Reload: new renderer for " + id, null);
                            lock (ElmcityApp.wrd)
                            {
                                ElmcityApp.wrd.renderers[id] = current_renderer;                  // update the renderer
                                if (ElmcityApp.home_controller != null)                               // skip this if we found a change on startup, controller not ready
                                {
                                    var cache = new AspNetCache(ElmcityApp.home_controller.HttpContext.Cache);
                                    var url = Utils.MakeBaseZonelessUrl(id);
                                    cache.Remove(url);                                               // flush cached objects for id
                                    var obj = HttpUtils.FetchUrl(new Uri(url));						// rewarm cache
                                }
                            }

                        }
                    }
                }

                }

            catch (Exception e1)
            {
                GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: cannot check/update wrd", e1.Message + e1.StackTrace);
            }

            if (new_routes)
            {
                var existing_routes = RouteTable.Routes;
                var route_count = existing_routes.Count;
                try
                {
                    GenUtils.LogMsg("status", "_ReloadSettingsAndRoutes: registering " + route_count + " routes", null);

                    lock (RouteTable.Routes)
                    {
                        var route_count_old = RouteTable.Routes.Count;
                        GenUtils.PriorityLogMsg("info", RouteTable.Routes.Count + " routes before reload", null);
                        RouteTable.Routes.Clear();
                        ElmcityApp.RegisterRoutes(RouteTable.Routes, ElmcityApp.wrd);
                        GenUtils.PriorityLogMsg("info", RouteTable.Routes.Count + " routes registered", null);
                        var route_count_new = RouteTable.Routes.Count;
                        if (route_count_new < route_count_old)
                            GenUtils.PriorityLogMsg("warning", "route count was " + route_count_old + ", is " + route_count_new, null);
                    }
                }
                catch (Exception e3)
                {
                    GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: registering " + route_count + " routes", e3.Message + e3.StackTrace);
                    ElmcityApp.RegisterRoutes(existing_routes, ElmcityApp.wrd);
                }
            }
        }
Пример #8
0
 public static void PurgeCache(Object o, ElapsedEventArgs e)
 {
     try
     {
         var cache = new AspNetCache(ElmcityApp.home_controller.HttpContext.Cache);
         ElmcityUtils.CacheUtils.MaybePurgeCache(cache);
     }
     catch (Exception ex)
     {
         GenUtils.PriorityLogMsg("exception", "PurgeCache", ex.Message);
     }
 }
Пример #9
0
        public static void _ReloadSettingsAndRoutes()
        {
            GenUtils.LogMsg("info", "webrole _ReloadRoutes", null);

            bool new_routes = false;

            try
            {
                ElmcityController.settings = GenUtils.GetSettingsFromAzureTable();
            }
            catch (Exception e0)
            {
                var msg = "_ReloadSettingsAndRoutes: settings";
                GenUtils.PriorityLogMsg("exception", msg, e0.Message);
            }

            try
            {
                var _wrd = WebRoleData.GetWrd();
                if (_wrd.ready_ids.Count != ElmcityApp.wrd.ready_ids.Count)  // did # of hubs change?
                {
                    new_routes = true;                                       // force rebuild of route map
                    GenUtils.LogMsg("info", "Reload: found a new hub", null);
                    lock (ElmcityApp.wrd)
                    {
                        ElmcityApp.wrd = _wrd;                               // update WebRoleData
                    }
                }
                foreach (var id in ElmcityApp.wrd.ready_ids)                  // did any hub's CalendarRenderer.Calinfo change?
                {
                    var cached_calinfo = ElmcityApp.wrd.renderers[id].calinfo;
                    var current_calinfo = Utils.AcquireCalinfo(id);
                    var cached_dict = ObjectUtils.ObjToDictStr(cached_calinfo);
                    var current_dict = ObjectUtils.ObjToDictStr(current_calinfo);
                    if (ObjectUtils.DictStrEqualsDictStr(cached_dict, current_dict) == false)  // calinfo.obj on blob store is different
                    {
                        GenUtils.LogMsg("info", "Reload: new calinfo+renderer for " + id, null);
                        lock (ElmcityApp.wrd)
                        {
                            var renderer = Utils.AcquireRenderer(id);                         // load new renderer, maybe custom for this hub
                            GenUtils.LogMsg("info", "renderer.calinfo.version_description: " + renderer.calinfo.version_description, null);
                            ElmcityApp.wrd.renderers[id] = renderer;                          // update the renderer (and its calinfo)
                            var cache = new AspNetCache(ElmcityApp.home_controller.HttpContext.Cache);
                            var url = Utils.MakeBaseZonelessUrl(id);
                            cache.Remove(url);                                               // flush cached objects for id
                            var obj = HttpUtils.FetchUrl(new Uri(url));						// rewarm cache
                        }
                    }
                }
            }
            catch (Exception e1)
            {
                GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: cannot check/update wrd", e1.Message);
                try
                {
                    var __wrd = ElmcityApp.wrd = WebRoleData.MakeWebRoleData();
                    lock (ElmcityApp.wrd)
                    {
                        ElmcityApp.wrd = __wrd;
                    }
                }
                catch (Exception e2)
                {
                    GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: cannot remake wrd", e2.Message);
                }
            }

            try
            {
                var themes = Utils.GetThemesDict();
                if (ObjectUtils.DictOfDictStrEqualsDictOfDictStr(themes, ElmcityController.themes) == false)
                {
                    lock (ElmcityController.themes)
                    {
                        ElmcityController.themes = themes;
                    }
                }
            }
            catch (Exception e2)
            {
                var msg = "_ReloadSettingsAndRoutes: themes";
                GenUtils.PriorityLogMsg("exception", msg, e2.Message);
            }

            if (new_routes)
            {
                try
                {
                    lock (RouteTable.Routes)
                    {
                        RouteTable.Routes.Clear();
                        ElmcityApp.RegisterRoutes(RouteTable.Routes, ElmcityApp.wrd);
                        // RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
                    }
                }
                catch (Exception e3)
                {
                    GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: registering routes", e3.Message);
                }
            }
        }
Пример #10
0
            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;
                }
            }