Skip to content

Instantly share code, notes, and snippets.

@PNergard
Last active Jun 7, 2016
Embed
What would you like to do?
Plugin for getting an overview of content types that have changes made in admin mode and there for isn't fully syncronized. Possibilites for easy reset. Read blog post over at http://world.episerver.com/blogs/Per-Nergard/Dates/2016/6/overview-of-content-type-syncronization-status/ for more information.
<%@ Page Language="C#" AutoEventWireup="false" CodeBehind="Resetter.aspx.cs" Inherits="AlloyDemoKit.modules.Nergard.TypeReset.Resetter" %>
<asp:content contentplaceholderid="MainRegion" runat="server">
<asp:HiddenField runat="server" id="ValuesToProcess" ClientIDMode="static" />
<script type="text/javascript">
function SelectedModels ()
{
var ids = [];
$('#modelTable tr').not(':first').each(function () {
if ($(this).find("td.chkbox input:checked").length > 0) {
var value = $(this).find("td.typeid").html();
ids.push(value);
}
});
$('#ValuesToProcess').val(ids);
}
</script>
<asp:Repeater id="rptModels" runat="server">
<HeaderTemplate>
<table id="modelTable" class="epi-default" cellspacing="0" id="TabTable" style="border-style:None;border-collapse:collapse;">
<tbody id="modelTableContainer">
<tr>
<th>Model</th><th>Name</th><th>State</th><th>Page / Block</th><th>TypeID</th><th>Reset</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr data-id="<%#ResultItem.TypeId %>">
<td><%#ResultItem.Model %></td>
<td><%#ResultItem.Name %></td>
<td><%#ResultItem.State %></td>
<td><%#ResultItem.BlockOrPage %></td>
<td class="typeid"><%#ResultItem.TypeId %></td>
<td class="chkbox"><input type="checkbox" /></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody></table>
</FooterTemplate>
</asp:Repeater>
<div class="epi-buttonContainer">
<span class="epi-cmsButton">
<asp:Button OnClick="SaveAndReset_Click" OnClientClick="SelectedModels()" ClientIDMode="Static" Text="Save and reset" ToolTip="Save and restart of web" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Save" id="savereset" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" runat="server" />
</span>
<span class="epi-cmsButton">
<asp:Button OnClick="Save_Click" OnClientClick="SelectedModels()" Text="Save" ToolTip="Save only" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Save" id="save" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" runat="server" />
</span>
<span class="epi-cmsButton">
<asp:Button OnClick="Reset_Click" Text="Reset" ToolTip="Restart of web" CssClass="epi-cmsButton-text epi-cmsButton-tools epi-cmsButton-Save" id="reset" onmouseover="EPi.ToolButton.MouseDownHandler(this)" onmouseout="EPi.ToolButton.ResetMouseDownHandler(this)" runat="server" />
</span>
</div>
</asp:content>
using EPiServer;
using EPiServer.DataAbstraction;
using EPiServer.DataAbstraction.RuntimeModel;
using EPiServer.PlugIn;
using EPiServer.ServiceLocation;
using EPiServer.Shell.WebForms;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace AlloyDemoKit.modules.Nergard.TypeReset
{
[GuiPlugIn(DisplayName = "Type state overview", Area = PlugInArea.AdminMenu, Url = ("~/modules/Nergard.TypeReset/Resetter.aspx"))]
public partial class Resetter : WebFormsBase
{
private ContentTypeModelRepository typeModelRepository = ServiceLocator.Current.GetInstance<ContentTypeModelRepository>();
protected List<PresentationItem> results = new List<PresentationItem>();
protected PresentationItem ResultItem { get { return Page.GetDataItem() as PresentationItem; } }
protected class PresentationItem
{
public string Model = "";
public string Name = "";
public string State = "";
public string BlockOrPage = "";
public string TypeId = "";
}
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
MasterPageFile = UriSupport.ResolveUrlFromUIBySettings("MasterPages/EPiServerUI.master");
SystemMessageContainer.Heading = "Type state overview";
SystemMessageContainer.Description = "A plugin that gives you overview of any content type conflicts in the solutuion (between model and changes made via admin mode). Easy reset of specific or all types. A reset may need a reset of the web";
}
protected override void OnLoad(EventArgs e)
{
var pageTypes = PageTypesList();
var blockTypes = BlockTypesList();
foreach (var pt in pageTypes)
{
var runtimeModel = typeModelRepository.GetContentTypeModel(pt.ModelType);
if (runtimeModel != null && runtimeModel.State == SynchronizationStatus.Conflict)
{
var item = new PresentationItem();
item.Model = runtimeModel.Name;
item.Name = runtimeModel.DisplayName;
item.State = runtimeModel.State.ToString();
item.TypeId = pt.ID.ToString();
item.BlockOrPage = "Page";
results.Add(item);
}
}
foreach (var pt in blockTypes)
{
var runtimeModel = typeModelRepository.GetContentTypeModel(pt.ModelType);
if (runtimeModel != null && runtimeModel.State == SynchronizationStatus.Conflict)
{
var item = new PresentationItem();
item.Model = runtimeModel.Name;
item.Name = runtimeModel.DisplayName;
item.TypeId = pt.ID.ToString();
item.State = runtimeModel.State.ToString();
item.BlockOrPage = "Block";
results.Add(item);
}
}
rptModels.DataSource = results;
rptModels.DataBind();
}
private IEnumerable<PageType> PageTypesList()
{
return ServiceLocator.Current.GetInstance<PageTypeRepository>().List().OrderBy(p => p.Name);
}
private IEnumerable<BlockType> BlockTypesList()
{
return ServiceLocator.Current.GetInstance<BlockTypeRepository>().List().OrderBy(p => p.Name);
}
protected void SaveAndReset_Click(object sender, EventArgs e)
{
Save(ValuesToProcess.Value);
RestartWebApplication();
}
protected void Save_Click(object sender, EventArgs e)
{
Save(ValuesToProcess.Value);
}
protected void Reset_Click(object sender, EventArgs e)
{
RestartWebApplication();
}
private void Save(string Values)
{
var typeIdsArray = Values.Split(',');
var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
foreach (var typeId in typeIdsArray)
{
ContentType type = contentTypeRepository.Load(Int32.Parse(typeId));
var writableType = type.CreateWritableClone();
((ContentType)writableType).ResetContentType();
contentTypeRepository.Save(((ContentType)writableType));
}
}
/// <summary>
/// Restarts the Web Application
/// Requires either Full Trust (HttpRuntime.UnloadAppDomain)
/// or Write access to web.config.
///
/// </summary>
private void RestartWebApplication()
{
bool Error = false;
try
{
// *** This requires full trust so this will fail
// *** in many scenarios
HttpRuntime.UnloadAppDomain();
}
catch
{
Error = true;
}
if (Error)
{
// *** Couldn't unload with Runtime - let's try modifying web.config
string ConfigPath = HttpContext.Current.Request.PhysicalApplicationPath + "\\web.config";
try
{
File.SetLastWriteTimeUtc(ConfigPath, DateTime.UtcNow);
}
catch
{
}
}
base.Response.Redirect("Resetter.aspx");
}
} //class
} //namespace
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AlloyDemoKit.modules.Nergard.TypeReset {
public partial class Resetter {
/// <summary>
/// ValuesToProcess control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.HiddenField ValuesToProcess;
/// <summary>
/// rptModels control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Repeater rptModels;
/// <summary>
/// savereset control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button savereset;
/// <summary>
/// save control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button save;
/// <summary>
/// reset control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Button reset;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment