Skip to content

Instantly share code, notes, and snippets.

@jacobjones
Last active December 5, 2022 15:01
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacobjones/8dac5371d15430e980cfd1496a1d63ef to your computer and use it in GitHub Desktop.
Save jacobjones/8dac5371d15430e980cfd1496a1d63ef to your computer and use it in GitHub Desktop.
Missing Properties Plugin for Episerver
<%@ Page Language="c#" EnableViewState="true" CodeBehind="MissingProperties.aspx.cs" AutoEventWireup="False" Inherits="EPiServer.Reference.Commerce.Site.Plugins.MissingProperties" Title="Missing Properties" %>
<%@ Register TagPrefix="EPiServerUI" Namespace="EPiServer.UI.WebControls" Assembly="EPiServer.UI, Version=11.21.4.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7" %>
<asp:content contentplaceholderid="MainRegion" runat="server">
<div class="epi-formArea" ID="Pagetypes" runat="server">
<div class="epi-size25">
<div>
<asp:GridView ItemType="EPiServer.Reference.Commerce.Site.Plugins.MissingProperties.Result" ID="PropertiesViewControl" runat="server" AutoGenerateColumns="false" >
<Columns>
<asp:TemplateField HeaderText="Type" ItemStyle-Wrap="false">
<ItemTemplate>
<b><%# Item.Heading %></b>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="TypeName" ItemStyle-Wrap="false">
<ItemTemplate>
<%# Item.TypeName %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Property Name" ItemStyle-Wrap="false">
<ItemTemplate>
<%# Item.Name %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete" ItemStyle-Wrap="false">
<ItemTemplate>
<asp:CheckBox id="box" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete" ItemStyle-Wrap="false" visible="false">
<ItemTemplate>
<asp:Label id="typeid" Text="<%# Item.Id %>" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<div class="epi-buttonContainer">
<EPiServerUI:ToolButton id="Save" DisablePageLeaveCheck="true" OnClick="Delete" runat="server" SkinID="Delete" text="Delete" ToolTip="Delete" />
</div>
</div>
</div>
</asp:content>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.UI.WebControls;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.PlugIn;
using EPiServer.Security;
using EPiServer.ServiceLocation;
using EPiServer.Shell.WebForms;
namespace EPiServer.Reference.Commerce.Site.Plugins
{
[GuiPlugIn(
DisplayName = "Missing Properties",
Description = "Missing Properties",
Area = PlugInArea.AdminMenu,
RequiredAccess = AccessLevel.Administer,
Url = "~/Plugins/MissingProperties.aspx")]
public partial class MissingProperties : WebFormsBase
{
private readonly Injected<ContentTypeModelRepository> _contentTypeModelRepository = default(Injected<ContentTypeModelRepository>);
private readonly Injected<IContentTypeRepository> _contentTypeRepository = default(Injected<IContentTypeRepository>);
private readonly Injected<IPropertyDefinitionRepository> _propertyDefinitionRepository = default(Injected<IPropertyDefinitionRepository>);
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
MasterPageFile = UriSupport.ResolveUrlFromUIBySettings("MasterPages/EPiServerUI.master");
SystemMessageContainer.Heading = "Missing properties";
SystemMessageContainer.Description =
"Lists all missing properties on page and block types and allows them to be deleted.";
}
protected override void OnLoad(EventArgs e)
{
if (!PrincipalInfo.CurrentPrincipal.IsInRole("CmsAdmins"))
{
Response.Clear();
Response.StatusCode = (int) HttpStatusCode.Unauthorized;
return;
}
base.OnLoad(e);
if (!IsPostBack)
{
Setup();
}
}
private void Setup()
{
var results = new List<Result>();
results.AddRange(GetResults<PageData>("Page types"));
results.AddRange(GetResults<BlockData>("Block types"));
results.AddRange(GetResults<MediaData>("Media types"));
PropertiesViewControl.DataSource = results;
PropertiesViewControl.DataBind();
}
/// <summary>
/// Gets result models for a specified content data type.
/// </summary>
/// <typeparam name="TContentData">The content data type.</typeparam>
/// <param name="typeName">The (friendly) type name.</param>
/// <returns>Result models, if any.</returns>
private IEnumerable<Result> GetResults<TContentData>(string typeName) where TContentData : IContentData
{
ICollection<Result> results = new List<Result>();
var pos = 0;
foreach (var type in _contentTypeRepository.Service.List()
.Where(x => typeof(TContentData).IsAssignableFrom(x.ModelType)))
{
foreach (var property in type.PropertyDefinitions)
{
if (!IsMissingModelProperty(property))
{
continue;
}
pos++;
results.Add(new Result(pos == 1 ? typeName : null, type.Name, property.Name, property.ID));
}
}
return results;
}
private bool IsMissingModelProperty(PropertyDefinition propertyDefinition)
{
return propertyDefinition != null && propertyDefinition.ExistsOnModel &&
_contentTypeModelRepository.Service.GetPropertyModel(propertyDefinition.ContentTypeID, propertyDefinition) ==
null;
}
protected void Delete(object sender, EventArgs e)
{
foreach (GridViewRow row in PropertiesViewControl.Rows)
{
var delete = ((CheckBox)row.FindControl("box")).Checked;
var typeId = ((Label)row.FindControl("typeid")).Text;
if (delete)
{
_propertyDefinitionRepository.Service.Delete(_propertyDefinitionRepository.Service
.Load(int.Parse(typeId)).CreateWritableClone());
}
}
Setup();
}
protected class Result
{
public Result(string heading, string typeName, string name, int id)
{
Heading = heading;
TypeName = typeName;
Name = name;
Id = id;
}
public string Heading { get; set; }
public string TypeName { get; set; }
public string Name { get; set; }
public int Id { get; set; }
}
}
}
//------------------------------------------------------------------------------
// <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 EPiServer.Reference.Commerce.Site.Plugins
{
public partial class MissingProperties
{
/// <summary>
/// Pagetypes control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlGenericControl Pagetypes;
/// <summary>
/// PropertiesViewControl 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.GridView PropertiesViewControl;
/// <summary>
/// Save control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::EPiServer.UI.WebControls.ToolButton Save;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment