-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #36 from jaytem/LocalObjectCache
Local object cache viewer
- Loading branch information
Showing
8 changed files
with
292 additions
and
4 deletions.
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
DeveloperTools/Controllers/LocalObjectCacheController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.Serialization.Formatters.Binary; | ||
using System.Web.Mvc; | ||
using System.Web.Routing; | ||
using DeveloperTools.Core; | ||
using DeveloperTools.Models; | ||
using EPiServer.Core; | ||
using EPiServer.Framework.Cache; | ||
|
||
namespace DeveloperTools.Controllers | ||
{ | ||
public class LocalObjectCacheController : DeveloperToolsController | ||
{ | ||
private readonly ISynchronizedObjectInstanceCache _cache; | ||
|
||
public LocalObjectCacheController(ISynchronizedObjectInstanceCache cache) | ||
{ | ||
_cache = cache; | ||
} | ||
|
||
public ActionResult Index(string FilteredBy, bool os = false) | ||
{ | ||
return View(PrepareViewModel(FilteredBy, os)); | ||
} | ||
|
||
[HttpParamAction] | ||
public ActionResult RemoveLocalCache(string[] cacheKeys, bool os) | ||
{ | ||
if(cacheKeys != null) | ||
{ | ||
foreach (string key in cacheKeys) | ||
{ | ||
_cache.RemoveLocal(key); | ||
} | ||
} | ||
|
||
return RedirectToAction("Index", new RouteValueDictionary(new { os })); | ||
} | ||
|
||
[HttpParamAction] | ||
public ActionResult RemoveLocalRemoteCache(string[] cacheKeys, bool os) | ||
{ | ||
if(cacheKeys != null) | ||
{ | ||
foreach (string key in cacheKeys) | ||
{ | ||
_cache.RemoveLocal(key); | ||
_cache.RemoveRemote(key); | ||
} | ||
} | ||
|
||
return RedirectToAction("Index", new RouteValueDictionary(new { os })); | ||
} | ||
|
||
[HttpParamAction] | ||
public ActionResult ViewObjectSize() | ||
{ | ||
return RedirectToAction("Index", new RouteValueDictionary(new { os = true })); | ||
} | ||
|
||
private LocalObjectCache PrepareViewModel(string FilteredBy, bool viewObjectSize) | ||
{ | ||
var model = new LocalObjectCache(); | ||
|
||
var cachedEntries = HttpContext.Cache.Cast<DictionaryEntry>().Take(10_000); | ||
|
||
switch (FilteredBy) | ||
{ | ||
case "pages": | ||
model.CachedItems = ConvertToListItem(cachedEntries.Where(item => item.Value is PageData), viewObjectSize); | ||
break; | ||
case "content": | ||
model.CachedItems = ConvertToListItem(cachedEntries.Where(item => item.Value is IContent), viewObjectSize); | ||
break; | ||
default: | ||
model.CachedItems = ConvertToListItem(cachedEntries, viewObjectSize); | ||
break; | ||
} | ||
|
||
model.FilteredBy = FilteredBy; | ||
model.Choices = new[] | ||
{ | ||
new SelectListItem { Text = "All Cached Objects", Value = "all" }, | ||
new SelectListItem { Text = "Any Content", Value = "content" }, | ||
new SelectListItem { Text = "Pages Only", Value = "pages" } | ||
}; | ||
|
||
model.ViewObjectSize = viewObjectSize; | ||
return model; | ||
} | ||
|
||
private IEnumerable<LocalObjectCacheItem> ConvertToListItem(IEnumerable<DictionaryEntry> cachedEntries, bool viewObjectSize) => | ||
cachedEntries.Select(e => new LocalObjectCacheItem | ||
{ | ||
Key = e.Key.ToString(), | ||
Value = e.Value, | ||
Size = viewObjectSize ? GetObjectSize(e.Value) : 0 | ||
}).ToList(); | ||
|
||
private static long GetObjectSize(object obj) | ||
{ | ||
if(obj == null) | ||
return 0; | ||
|
||
try | ||
{ | ||
using (Stream s = new MemoryStream()) | ||
{ | ||
var formatter = new BinaryFormatter(); | ||
formatter.Serialize(s, obj); | ||
|
||
return s.Length; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
return -1; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using System.Reflection; | ||
using System.Web.Mvc; | ||
|
||
namespace DeveloperTools.Core | ||
{ | ||
public class HttpParamActionAttribute : ActionNameSelectorAttribute | ||
{ | ||
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) | ||
{ | ||
if(actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase)) | ||
return true; | ||
|
||
if(!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase)) | ||
return false; | ||
|
||
var request = controllerContext.RequestContext.HttpContext.Request; | ||
return request[methodInfo.Name] != null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System.Collections.Generic; | ||
using System.Web.Mvc; | ||
|
||
namespace DeveloperTools.Models | ||
{ | ||
public class LocalObjectCache | ||
{ | ||
public IEnumerable<LocalObjectCacheItem> CachedItems { get; set; } | ||
|
||
public string FilteredBy { get; set; } | ||
|
||
public IEnumerable<SelectListItem> Choices { get; set; } | ||
|
||
public bool ViewObjectSize { get; set; } | ||
} | ||
|
||
public class LocalObjectCacheItem | ||
{ | ||
public string Key { get; set; } | ||
|
||
public object Value { get; set; } | ||
|
||
public long Size { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
DeveloperTools/modules/_protected/EPiServer.DeveloperTools/Views/LocalObjectCache/Index.aspx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<DeveloperTools.Models.LocalObjectCache>" MasterPageFile="../Shared/DeveloperTools.Master" %> | ||
|
||
<asp:Content ID="Styles" runat="server" ContentPlaceHolderID="HeaderStyles"> | ||
<style type="text/css"> | ||
.table-column-width { | ||
width: 30%; | ||
} | ||
.stripe tbody tr:nth-child(even) { | ||
background-color: #f0f2f2; | ||
} | ||
</style> | ||
</asp:Content> | ||
|
||
<asp:Content ID="Content" runat="server" ContentPlaceHolderID="MainRegion"> | ||
<link rel="stylesheet" type="text/css" href="//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/css/jquery.dataTables.css" /> | ||
<script type="text/javascript" language="javascript" src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script> | ||
<script src="//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.0/jquery.dataTables.min.js" type="text/javascript"></script> | ||
|
||
<div class="epi-contentContainer epi-padding"> | ||
<div class="epi-contentArea"> | ||
<h1>Local Object Cache</h1> | ||
<p class="EP-systemInfo">This tool shows all of the current items in the local object cache, and allows the deletion of one or more cached items.</p> | ||
</div> | ||
|
||
<div class="epi-contentArea epi-formArea"> | ||
<%using (Html.BeginForm("Index", "LocalObjectCache", FormMethod.Post)) | ||
{ %> | ||
<%= Html.AntiForgeryToken() %> | ||
|
||
<table class="table"> | ||
<tr> | ||
<td>Filter By</td> | ||
<td><%= Html.DropDownListFor(m => m.FilteredBy, Model.Choices) %></td> | ||
<td> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Refresh" type="submit" name="filter" id="filter" value="Filter" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
</td> | ||
</tr> | ||
</table> | ||
<% } %> | ||
|
||
<% using (Html.BeginForm("Action", "LocalObjectCache", FormMethod.Post)) | ||
{ %> | ||
<div class="epi-contentArea"> | ||
<p class="EP-systemInfo">Total count of cached items: <%= Model.CachedItems.Count() %></p> | ||
</div> | ||
<div class="epi-buttonDefault"> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="RemoveLocalCache" id="RemoveLocalCache" value="Remove Local Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="removeLocalRemoteCache" id="removeLocalRemoteCache" value="Remove Local and Remote Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-ViewMode" type="submit" name="ViewObjectSize" id="ViewObjectSize" value="View Object Size" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
</div> | ||
|
||
<table class="table table-condensed table-bordered table-condensed stripe"> | ||
<thead> | ||
<tr> | ||
<th><input type="checkbox" id="clearAll" name="clearAll" onClick="toggle(this)" value="true" /></th> | ||
<th class="table-column-width">Key</th> | ||
<th class="table-column-width">Type</th> | ||
<th>Size</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% foreach (var item in Model.CachedItems) | ||
{ %> | ||
<tr> | ||
<td class="center"><input type="checkbox" id="<%= item.Key %>" name="cacheKeys" value="<%= item.Key %>" /></td> | ||
<td><%= item.Key %></td> | ||
<td><%= item.Value.GetType() %></td> | ||
<td><%= item.Size %></td> | ||
</tr> | ||
<% } %> | ||
</tbody> | ||
</table> | ||
|
||
<div class="epi-buttonDefault"> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="RemoveLocalCache" id="RemoveLocalCacheBottom" value="Remove Local Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Delete" type="submit" name="removeLocalRemoteCache" id="removeLocalRemoteCacheBottom" value="Remove Local and Remote Cache Items" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
<span class="epi-cmsButton"> | ||
<input class="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-ViewMode" type="submit" name="ViewObjectSize" id="ViewObjectSize" value="View Object Size" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" /> | ||
</span> | ||
</div> | ||
|
||
<input type="hidden" id="os" name="os" value="<%= Model.ViewObjectSize %>"/> | ||
<% } %> | ||
</div> | ||
</div> | ||
|
||
<script language="JavaScript"> | ||
function toggle(source) { | ||
checkboxes = document.getElementsByName('cacheKeys'); | ||
for (var i = 0, n = checkboxes.length; i < n; i++) { | ||
checkboxes[i].checked = source.checked; | ||
} | ||
} | ||
</script> | ||
</asp:Content> |