Today I was given the slightly unusual requirement that my page must behave differently depending on whether it is being viewed normally, or through the IFrame in EPiServer's Edit Mode. It was a little tricky finding the answer so I thought I would explain it...
Obviously the only way that the Edit Mode view can be detected is if there is something in the IFrame source URL used to request the page which gives it away. Fortunately there is. The page is requested using the unfriendly URL. The ID in the query-string contains both the page ID and the work page ID. Usually, when the page is loading after a rewrite from the friendly url, the work page ID is not included. Also, there is another querystring parameter called "idkeep" which apparently is not present except in this IFrame source. These are what we can look for to determine whether we are in Edit Mode or not.
Having figured out the solution it wasn't long before I realised that the best way to code this, had already been written by Kalle Hoppe as a reply on this blog post by Jacob Khan (which is confusingly named and is actually about a different topic - detecting if a control is being used on an Admin mode plugin).
All of the comments on that post miss the point of that blog post entirely, but are all valid methods to solve my problem. Of all of them I would recommend Kalle's method, since it uses the EPiServer API to parse the ID, and it is a parameter which is less likely to be changed by EPiServer in the future. It also doesn't require changing the EPiServer.UI.WebContols.SystemIFrame control.
Here's the code:
public bool IsPageInEditMode
{
PageReference pageVersionReference = PageReference.Parse(Request.QueryString["id"]);
if (pageVersionReference.WorkID > 0)
return true;
return false;
}