public static CategoryTreeJson CategoryTree(string accountNameKey, List <CategoryTreeModel> categoryTreeIn, bool includeImages) { var categoryTreeObjectOut = new CategoryTreeJson(); categoryTreeObjectOut.categories = new List <CategoryTreeListItemJson>(); categoryTreeObjectOut.categoryDepth = 0; foreach (CategoryTreeModel categoryTreeModel in categoryTreeIn) { var categoryListItem = new CategoryTreeListItemJson { //id = categoryTreeModel.ID.ToString(), name = categoryTreeModel.Name, nameKey = categoryTreeModel.NameKey, fullyQualifiedName = categoryTreeModel.FullyQualifiedName }; if (includeImages) { categoryListItem.images = Dynamics.Images.BuildDynamicImagesListForJson(accountNameKey, "category", categoryTreeModel.ID.ToString(), true); } categoryListItem.subcategories = new List <SubcategoryTreeListItemJson>(); foreach (SubcategoryTreeModel subcategoryTreeModel in categoryTreeModel.Subcategories) { if (categoryTreeObjectOut.categoryDepth < 1) { categoryTreeObjectOut.categoryDepth = 1; } var subcategoryListItem = new SubcategoryTreeListItemJson { //id = subcategoryTreeModel.ID.ToString(), name = subcategoryTreeModel.Name, nameKey = subcategoryTreeModel.NameKey, fullyQualifiedName = subcategoryTreeModel.FullyQualifiedName }; if (includeImages) { subcategoryListItem.images = Dynamics.Images.BuildDynamicImagesListForJson(accountNameKey, "subcategory", subcategoryTreeModel.ID.ToString(), true); } subcategoryListItem.subsubcategories = new List <SubsubcategoryTreeListItemJson>(); foreach (SubsubcategoryTreeModel subsubcategoryTreeModel in subcategoryTreeModel.Subsubcategories) { if (categoryTreeObjectOut.categoryDepth < 2) { categoryTreeObjectOut.categoryDepth = 2; } var subsubcategoryListItem = new SubsubcategoryTreeListItemJson { //id = subsubcategoryTreeModel.ID.ToString(), name = subsubcategoryTreeModel.Name, nameKey = subsubcategoryTreeModel.NameKey, fullyQualifiedName = subsubcategoryTreeModel.FullyQualifiedName }; if (includeImages) { subsubcategoryListItem.images = Dynamics.Images.BuildDynamicImagesListForJson(accountNameKey, "subsubcategory", subsubcategoryTreeModel.ID.ToString(), true); } subsubcategoryListItem.subsubsubcategories = new List <SubsubsubcategoryTreeListItemJson>(); foreach (SubsubsubcategoryTreeModel subsubsubcategoryTreeModel in subsubcategoryTreeModel.Subsubsubcategories) { if (categoryTreeObjectOut.categoryDepth < 3) { categoryTreeObjectOut.categoryDepth = 3; } var subsubsubcategoryListItem = new SubsubsubcategoryTreeListItemJson { //id = subsubsubcategoryTreeModel.ID.ToString(), name = subsubsubcategoryTreeModel.Name, nameKey = subsubsubcategoryTreeModel.NameKey, fullyQualifiedName = subsubsubcategoryTreeModel.FullyQualifiedName }; if (includeImages) { subsubsubcategoryListItem.images = Dynamics.Images.BuildDynamicImagesListForJson(accountNameKey, "subsubsubcategory", subsubsubcategoryTreeModel.ID.ToString(), true); } subsubcategoryListItem.subsubsubcategories.Add(subsubsubcategoryListItem); } subcategoryListItem.subsubcategories.Add(subsubcategoryListItem); } categoryListItem.subcategories.Add(subcategoryListItem); } categoryTreeObjectOut.categories.Add(categoryListItem); } return(categoryTreeObjectOut); }
public JsonNetResult CategoryTree(bool includeHidden = false, bool includeImages = false) { ExecutionType executionType = ExecutionType.local; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); //Get the subdomain (if exists) for the api call string accountNameKey = Common.GetSubDomain(Request.Url); if (String.IsNullOrEmpty(accountNameKey)) { return(new JsonNetResult { Data = "Not found" }); //return Request.CreateResponse(HttpStatusCode.NotFound); } List <CategoryTreeModel> categoryTree = null; CategoryTreeJson categoryTreeJson = null; string localCacheKey = accountNameKey + ":categorytree:" + includeHidden + ":" + includeImages; #region (Plan A) Get json from local cache try { categoryTreeJson = (CategoryTreeJson)HttpRuntime.Cache[localCacheKey]; } catch (Exception e) { var error = e.Message; //TODO: Log: error message for local cache call } #endregion if (categoryTreeJson == null) { #region (Plan B) Get Public json from second layer of Redis Cache IDatabase cache = CoreServices.RedisConnectionMultiplexers.RedisMultiplexer.GetDatabase(); string pathAndQuery = Common.GetApiPathAndQuery(Request.Url); string hashApiKey = accountNameKey + ":apicache"; string hashApiField = pathAndQuery; try { var redisApiValue = cache.HashGet(hashApiKey, hashApiField); if (redisApiValue.HasValue) { categoryTreeJson = JsonConvert.DeserializeObject <CategoryTreeJson>(redisApiValue); executionType = ExecutionType.redis_secondary; } } catch { } #endregion if (categoryTreeJson == null) { #region (Plan C) Get category data from Redis Cache and rebuild try { //IDatabase cache = CoreServices.RedisConnectionMultiplexers.RedisMultiplexer.GetDatabase(); string hashMainKey = accountNameKey + ":categories"; string hashMainField = "tree:public"; if (includeHidden == true) { hashMainField = "tree:private"; } try { var redisValue = cache.HashGet(hashMainKey, hashMainField); if (redisValue.HasValue) { categoryTree = JsonConvert.DeserializeObject <List <ApplicationCategorizationService.CategoryTreeModel> >(redisValue); executionType = ExecutionType.redis_main; } } catch { } } catch (Exception e) { var error = e.Message; //TODO: Log: error message for Redis call } #endregion if (categoryTree == null) { #region (Plan D) Get data from WCF var applicationCategorizationServiceClient = new ApplicationCategorizationService.ApplicationCategorizationServiceClient(); try { applicationCategorizationServiceClient.Open(); categoryTree = applicationCategorizationServiceClient.GetCategoryTree(accountNameKey, includeHidden, Common.SharedClientKey).ToList(); executionType = ExecutionType.wcf; WCFManager.CloseConnection(applicationCategorizationServiceClient); } catch (Exception e) { #region Manage Exception string exceptionMessage = e.Message.ToString(); var currentMethod = System.Reflection.MethodBase.GetCurrentMethod(); string currentMethodString = currentMethod.DeclaringType.FullName + "." + currentMethod.Name; // Abort the connection & manage the exception WCFManager.CloseConnection(applicationCategorizationServiceClient, exceptionMessage, currentMethodString); #endregion } #endregion } } #region Transform into json object, add images & cache locally or locally and radisAPI layer if (categoryTreeJson != null) { //Just cache locally (we got json from the api redis layer) HttpRuntime.Cache.Insert(localCacheKey, categoryTreeJson, null, DateTime.Now.AddMinutes(Common.CategorizationCacheTimeInMinutes), TimeSpan.Zero); } else if (categoryTree != null) { //Transform categories into JSON and cache BOTH locally AND into redis categoryTreeJson = Transforms.Json.CategorizationTransforms.CategoryTree(accountNameKey, categoryTree, includeImages); HttpRuntime.Cache.Insert(localCacheKey, categoryTreeJson, null, DateTime.Now.AddMinutes(Common.CategorizationCacheTimeInMinutes), TimeSpan.Zero); try { cache.HashSet(hashApiKey, hashApiField, JsonConvert.SerializeObject(categoryTreeJson), When.Always, CommandFlags.FireAndForget); } catch { } } #endregion } if (categoryTreeJson != null) { //Add execution data stopWatch.Stop(); categoryTreeJson.executionType = "test"; categoryTreeJson.executionType = executionType.ToString(); categoryTreeJson.executionTime = stopWatch.Elapsed.TotalMilliseconds + "ms"; } JsonNetResult jsonNetResult = new JsonNetResult(); jsonNetResult.Formatting = Newtonsoft.Json.Formatting.Indented; jsonNetResult.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; //<-- Convert UTC times to LocalTime jsonNetResult.Data = categoryTreeJson; return(jsonNetResult); }