Category Archives: EPiServer

Does your edit mode show up blank after upgrade?

I’ve seen quite a few users who ended up with just the top bar in edit mode after upgrading EPiServer lately. Most of them seems to have to do with the Visual Studio Web Accessibility Checker, or with Browser Link.

For me, however, none of them solved the issue, and it took me a while to figure out the reason. I had similar errors as the above, with the console full of dojo script errors so my first action was to enable client resource debug ny adding this to the episerver.framework section:

<clientResources debug="true" />

I ended up with a slightly more readable error cause:

Error: "scriptError"
makeErrorhttp://xxxxxxxxx/EPiServer/Shell/11.4.4/ClientResources/dojo/dojo.js:119:15errorDisconnectorhttp://xxxxxxxxx/EPiServer/Shell/11.4.4/ClientResources/dojo/dojo.js:1669:21 dojo.js:1834:4
src: dojoLoader dojo.js:1837:6
info: 
Array [ "/EPiServer/Shell/11.4.4/ClientResources/epi-cms.component.Media.js", error ]

The reference to epi-cms.component.Media.js got my attention. I know for sure i have i component on my site that make use of that component. A quick look later the component was found:

[Component]
public class CustomMediaMainNavigationComponent : ComponentDefinitionBase
{
    public CustomMediaMainNavigationComponent()
            : base("epi-cms.component.Media")
    ......
    ......
}

Once found, the solution was only 2 characters away. A while ago EPiServer changed the dot-notation to slash-notaion. So all i had to do was to change the code above to:

[Component] 
public class CustomMediaMainNavigationComponent : ComponentDefinitionBase 
{ 
    public CustomMediaMainNavigationComponent() 
            : base("epi-cms/component/Media") 
    ...... 
    ...... 
}

And the edit mode came back!

Recycle bin won’t empty when using EPiServer Relate

A few days ago i found i strange behaviour on our intranet site. The waste basket didn’t empty! The scheduled job ran just fine, but the log always contained the same message: 0 content items were deleted from recycle bin

Thats a new one! So where to look? The logs are, off course, a great place to start looking for errors. The first line that cought my attention was this one: ERROR EPiServer.Util.EmptyWastebasketJob: 17.3.1 Error when trying to delete content from recycle bin

At first, i thought it was some kind of permission issue. The site runs Windows authentication, and that has some side effects, but than i found another line in the log: EPiServer.Core.TypeMismatchException: Content with id ‘<xxxxx>’ is of type ‘Castle.Proxies.FormContainerBlockProxy’ which does not inherit required type ‘EPiServer.Core.PageData’

and than another similar line: EPiServer.Core.TypeMismatchException: Content with id ‘29990’ is of type ‘EPiServer.Core.ContentFolder’ which does not inherit required type ‘EPiServer.Core.PageData’

I couldn’t believe there’s still code in EPiServer that requires PageData!! And, off couse, there wasn’t. BUT! EPiServer Relate is another story. The CmsIntegrationModule had a few fingers in that cookie jar!

To be specific, the method RemovePageEntity, which deletes corresponding page entities when a page is deleted:

        /// <summary>
        /// Deletes the correspoinding <see cref="CMSPageEntity"/> when a page is deleted
        /// </summary>
        /// <param name="e">The <see cref="EPiServer.PageEventArgs"/> instance containing the event data.</param>
        private static void RemovePageEntity(PageEventArgs e)
        {
            if (e == null || PageReference.IsNullOrEmpty(e.PageLink))
            {
                return;
            }
            
            CMSPageEntity pagedataEntity = CMSPageEntityHandler.Instance.GetEntity(e.Page.PageGuid, e.Page.LanguageBranch, 0);

            if (pagedataEntity == null)
            {
                return;
            }

            CMSPageEntityHandler.Instance.RemoveEntity(pagedataEntity);
        }

It first, it looks like the code really do try to avoid null references by checking if PageEventArgs are null and than if PageEventArgs.PageLink is null, but: when you have a ContentFolder or FormContiner in the recycle bin, both of them are set. The problem is that PageEventArgs.Page is null.

So, just throw in one more null check for e.Page, like this:

        /// <summary>
        /// Deletes the correspoinding <see cref="CMSPageEntity"/> when a page is deleted
        /// </summary>
        /// <param name="e">The <see cref="EPiServer.PageEventArgs"/> instance containing the event data.</param>
        private static void RemovePageEntity(PageEventArgs e)
        {
            if (e == null || e.Page == null || PageReference.IsNullOrEmpty(e.PageLink))
            {
                return;
            }
            
            CMSPageEntity pagedataEntity = CMSPageEntityHandler.Instance.GetEntity(e.Page.PageGuid, e.Page.LanguageBranch, 0);

            if (pagedataEntity == null)
            {
                return;
            }

            CMSPageEntityHandler.Instance.RemoveEntity(pagedataEntity);
        }

And you also need to handle errors in GetClubId. I took the easy way and put a try around the code.

        private static int GetClubId(PageReference pageReference)
        {
            try
            {
                if (PageReference.IsNullOrEmpty(pageReference))
                {
                    return -1;
                }

                // Get the page
                PageData page = DataFactory.Instance.GetPage(pageReference);

                // Check if it is an article page, if not return
                if (page is ArticlePage && ((ArticlePage)page).ClubAssociation > 0)
                {
                    return ((ArticlePage)page).ClubAssociation;
                }
                return -1;
            }
            catch { }

            return -1;
        }

Now the recycle bin should empty just fine!

Resolving links in XhtmlStrings, EPiServer 7.16.1

Did you ever try to store a XhtmlString in a variable and use it in your code? Maybe you noticed that some stuff, like links, isn’t very useful because they are internal.

I noticed this when i upgraded a site from CMS6, and on that site i had a working code that rendered dynamic content so the code i passed to my variable actually was useful, but it broke when i upgraded the site. What i did find than, was that XhtmlStrings are made up of Fragments. And that’s really useful!

One thing you can do with these fragments is resolving internal links, and this is because links are stored as a UrlFragment. A typical XhtmlString could look like:

As you can see, we have regular content, UrlFragments and a ContentFragment. So now, we can write some code to do stuff with different fragements:

StringBuilder sBuilder = new StringBuilder();
foreach (IStringFragment sFragment in Xhtml.Fragments)
{
  if (sFragment is ContentFragment)
  {
  }
  if (sFragment is UrlFragment)
  {
  }
  sBuilder.Append(sFragment.GetViewFormat());
}

Maybe you would like to do something with a block?

if (sFragment is ContentFragment)
{
  ContentFragment cFragment = sFragment as ContentFragment;
  var Content = Repository.Get<ContentData>(cFragment.ContentLink);
}

Or, if you would like to resolve links in your XhtmlString:

if(sFragment is UrlFragment) 
{
  UrlFragment uFragment = sFragment as UrlFragment;
  UrlBuilder uBuilder = new UrlBuilder(uFragment.InternalFormat);
  Global.UrlRewriteProvider.ConvertToExternal(uBuilder, null, Encoding.UTF8);
  sBuilder.Append(uBuilder.Uri);
  continue;
}

The complete code i use to resolve links before passing the content to a javascript:

public static string ParseXhtmlString(XhtmlString Xhtml)
{
    StringBuilder sBuilder = new StringBuilder();
    if (!(Xhtml == null || Xhtml.IsEmpty))
    {
        foreach (IStringFragment sFragment in Xhtml.Fragments)
        {
            UrlFragment uFragment = sFragment as UrlFragment;
            if(uFragment != null) 
            {
                try
                {
                    UrlBuilder uBuilder = new UrlBuilder(uFragment.InternalFormat);
                    Global.UrlRewriteProvider.ConvertToExternal(uBuilder, null, Encoding.UTF8);
                    sBuilder.Append(uBuilder.Uri);
                    continue;
                }
                catch (Exception)
                { }
            }
            sBuilder.Append(sFragment.GetViewFormat());
        }
    }
    return sBuilder.ToString();
}

 

EPiServer CMS 6: Exporting lots and lots of files

Exporting lots of files from EPiServer CMS 6 can be a pain. Picking the files, one at a time, can take ages and when your done and press “Export”-button, session has probably times out and you have to do it all over again.

On top of that, if you upload-folder are huge (this one is 21Gb), for some reason the file browser dialog won’t open at all. (I’m not absolutely sure the size is the issue, but i think it is). So what to do?

You could create i job that reads all links from tblPageSoftLink, resolve their names, save the file and so on. That’s a nice solution off course, but i wanted i quick solution. So what to do?

I decided to take trick EPiServer, using FireBug, to work around the file browser dialog. this is what i did:

First, i created a list of the files i needed to export. Using your favorite editor it should be easy to generate a list of options with the file names and paths

<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/annotations.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/ast_alert.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/ast_loader.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/ast_navicons.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/ast_notes.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/ast_remote.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/ast_vidpresenter.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/attach.html">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/blank.html">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/button.gif">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/flashcommand.js">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/mod_colorizer.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/mod_engage.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/mod_exit.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/mod_quiz.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/null.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/PassVar.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/playershell.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/slidegroup.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/stealthray.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/utils.js">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/VideoPlayer.html">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/VideoPlayer.swf">
<option value="/Upload/Forebyggande/Informationssakerhet/Utbildning_kryptering/player/zoom.html">

I then went to the admin-mode, “Export data”, checked the “Export files”-option. Now, instead of pressing “Add files”, start FireBug and use the inspect element-tool and select the listbox:

inspectelement

Right-click the selected HTML-code, and choose edit html:

edithtml

Paste your list between <select> and </select>, when done press the “edit”-button in the top left to close the edit.

pastelist

Using the inspect element-tool again, you can see there’s a lot of files in the listbox. You could off course add the file names again, after the option tag to make them visible in the list.

inspectfiles

Press export and save the file. Locate the file on the disk, rename ExportedFile.episerverdata to ExportedFile.zip and open it. Inside the ZIP, there’s a folder with the same name as your upload, in my case it’s called SiteUpload.

exportedfile

In that folder there’s a folder structure similar to the one on the site. Just navigate through the folders and there’s your files!

files

EPiServer 7.5 – List icons for blocks

OK, maybe this is obvious for everyone else, but it wasn’t to me. So this is part sharing and part to remember my self. 🙂

And for the record, this may not be the most correct way, but it’s the way i figured out.

What i wanted to do

What i wanted to do, was to make some fancy icons that shows up in the block listing. That means the listing that shows your created blocks.

Block icons

Since i had nice icons showing up when i create a new block, i really wanted this to work.

The easy part is to figure out you have to create a descriptor class. There’s tons of examples showing that. But most of them refers to internal css-classes, like epi-iconFacebook that grabs the icon from a sprite already existing in Epi UI. What if i want to make my own class and sprite?

Create a descriptor

The first thing i figured out was i had to create i descriptor class. Theese can be handy for a lot of things, but in this case there’s not much to it.

[UIDescriptorRegistration]
public class ServiceDeskBlockDescriptor : UIDescriptor<ServiceDeskBlock>
{
  public ServiceDeskBlockDescriptor()
    : base("epi-iconServicedesk")
  {
    DefaultView = CmsViewNames.AllPropertiesView;
  }
}

The only important thing here is epi-iconServicedesk which is the class name used to show the correct icon.  If you substitute that name with epi-iconFacebook you will instantly get a working icon for your block, the facebook icon.

Create sprite

You don’t have to create a sprite, it works fine with a 16×16 image of any supported format, but i needed a lot of icons so i made a sprite in a 16×16 grid.

Icon sprite

Create CSS

Using firebug it was easy to figure out how the existing classes were made. It’s all just a background. I saved my css classes in a separate file called blockicons.css.

.Sleek .epi-iconServicedesk {
    background:url('/Static/images/Alla_ikoner_16x16.png') -64px -16px no-repeat;
    height: 16px;
    width: 16px;
}

Module.config

This is the part that wasn’t obvious at all for me. I didn’t really find any thing about this at all, but i did find a few articles on how to create a dojo widget. Theese got me in right direction.

In your websites root folder, create (or modify) the file module.config, and add your css file.

<?xml version="1.0" encoding="utf-8"?>
<module>
  <clientResources>
    <add name="epi-cms.widgets.base" path="/Static/css/blockicons.css" resourceType="Style"/>
  </clientResources>
</module>

If i got this right, the name epi-cms.widgets.base make EpiServer load your client resources when it start itself. If you choose another name, it loads when needed by your home made dojo widget (which does not exist in this case).

Finishing up…

Compile your project and restart your web server. Go to your sites edit UI and you should end up seeing something like the first image in this post.

EPiServer really cache theese things well, so modifications to icons and css files may need a restart. So don’t get to upset if you make changes that doesn’t seem to apply.