Error when copy a page structure
If you experience that you get an error when trying to copy or export/import a page tree the reason could be that you are missing some files in the VPP (7.0) or Appdata(7.5).
What you then need is to find what files you are missing. I have made a small utility that loops thru all properties, checks the IReferenceMap, and finds all documents and check if the file actually exists on the disk.
The code is simple and is
[IFrameComponent(
Url = "~/Custom/Plugins/CheckFiles.aspx",
ReloadOnContextChange = true,
PlugInAreas = "/episerver/cms/assets",
Title = "Check files used",
Categories = "cms", MinHeight = 100, MaxHeight = 500)]
//Update: In EPiServer 7.5, the base class to use is: EPiServer.Shell.WebForms.ContentWebFormsBase
public partial class CheckFiles : ContentBaseWebForm
{
protected void Page_Load(object sender, EventArgs e)
{
PageName.InnerHtml = CurrentContent.Name;
PageName.Attributes["title"] = "" + CurrentContent.ContentLink;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (UrlRewriteProvider.Module != null)
{
UrlRewriteProvider.Module.FURLRewriteResponse = false;
}
}
protected void BtnClicked_Click(object sender, EventArgs e)
{
var statusDic = new Dictionary<Guid, GuidStatus>();
Check(CurrentContent, statusDic, "", DoChildren.Checked, CheckLinkedItems.Checked);// CheckContent(CurrentContent, statusDic, CurrentContent.Name + "[" + CurrentContent.ContentLink + "]", DoChildren.Checked);
var txt="";
var dontExists = statusDic.Values.Where(p => !p.Exists).ToList(); ;
txt+="Dont exists:"+dontExists.Count;
foreach (var item in dontExists)
{
txt+="<div>* "+item.UsedWhere+":<br />"+ item.Name+" <div>"+item.Debug+"</div></div>";
}
DebugLit.Text = txt;
}
GuidStatus CheckGuid(Guid guid)
{
var result = new GuidStatus();
result.Guid = guid;
var map = EPiServer.Web.PermanentLinkMapper.Instance.Find(guid);
if (map is EPiServer.Web.PermanentContentLinkMap)
{
result.TargetType = "PAGE";
try {
var p=EPiServer.DataFactory.Instance.Get<IContent>((map as EPiServer.Web.PermanentContentLinkMap).ContentReference);
result.Exists = true;
result.Content = p;
result.Name = p.Name + " [" + (map as EPiServer.Web.PermanentContentLinkMap).ContentReference + "]";
}
catch (System.Exception error)
{
result.Exists = false;
result.Debug = error.Message;
}
}
if (map is EPiServer.Web.PermanentFileLinkMap)
{
result.TargetType = "FILE";
var filMap = (map as EPiServer.Web.PermanentFileLinkMap);
if (filMap != null && filMap.MappedUrl != null)
{
var filPath = Uri.UnescapeDataString(filMap.MappedUrl.ToString());
result.Name = filPath;
if (System.Web.Hosting.HostingEnvironment.VirtualPathProvider.FileExists(filPath))
{
var fil = System.Web.Hosting.HostingEnvironment.VirtualPathProvider.GetFile(filPath);
try
{
result.Exists = false;
using (var stream = fil.Open())
{
if (stream.ReadByte() > -1)
{
result.Exists = true;
}
}
}
catch (System.Exception error)
{
result.Exists = false;
result.Debug = error.Message;
}
}
}
}
return result;
}
string IContentName(IContent content)
{
return content.Name + " [" + content.ContentLink + "]";
}
void Check(IContent content, Dictionary<Guid, GuidStatus> status, string path, bool addChildren,bool checkLinkedItems)
{
var contentName = IContentName(content);
if (!status.ContainsKey(content.ContentGuid))
{
status.Add(content.ContentGuid, new GuidStatus() { Exists = true, Name = contentName, UsedWhere = path });
}
Check(content as IContentData, status, path + contentName, addChildren);
if (checkLinkedItems)
{
var toDo = status.Values.Where(p => p.Parse).ToList();
foreach (var toDoItem in toDo)
{
toDoItem.Parse = false;
}
foreach (var toDoItem in toDo)
{
if (toDoItem.Content != null)
{
Check(toDoItem.Content, status, toDoItem.Name, false,false);
}
}
}
if (addChildren)
{
var children = EPiServer.DataFactory.Instance.GetChildren<IContent>(content.ContentLink);
foreach (var child in children)
{
Check(child, status, "", addChildren, checkLinkedItems);
}
}
}
void Check(IContentData content, Dictionary<Guid, GuidStatus> status, string path, bool addChildren)
{
foreach (var prop in content.Property)
{
Check(prop, status, path+"."+prop.Name, addChildren);
}
}
void Check(PropertyData prop, Dictionary<Guid, GuidStatus> status, string path, bool addChildren)
{
var refMap = prop as IReferenceMap;
if (refMap != null)
{
var guids = refMap.ReferencedPermanentLinkIds;
if (guids.Count > 0)
{
foreach (var filGuid in refMap.ReferencedPermanentLinkIds)
{
if (!status.ContainsKey(filGuid))
{
var check = CheckGuid(filGuid);
check.UsedWhere = path;
status.Add(filGuid, check); ;
if (check.Content != null)
{
check.Parse = true;
//Check(check.Content, status, path + " =>", false);
}
}
}
}
}
else if (prop is IContentData)
{
Check((prop as IContentData), status, path , false);
}
}
public class GuidStatus
{
public Guid Guid { get; set; }
public string Name { get; set; }
public string UsedWhere { get; set; }
public string TargetType { get; set; }
public bool Exists {get;set;}
public string Debug { get; set; }
public IContent Content { get; set; }
public bool Parse { get; set; }
}
}
And the front code is
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CheckFiles.aspx.cs" Inherits="Itera.Custom.PlugIns.CheckFiles" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2 id="PageName" runat="server" />
<asp:Button ID="BtnClicked" runat="server" Text="Check" OnClick="BtnClicked_Click" />
<asp:CheckBox ID="DoChildren" runat="server" Text="Check children also" />
<asp:CheckBox ID="CheckLinkedItems" runat="server" Text="Check linked items" />
<div>
<asp:Literal id="DebugLit" runat="server" />
</div>
</div>
</form>
</body>
</html>
Comments