November Happy Hour will be moved to Thursday December 5th.

Issue when programmatically creating the "For this page" folder

Vote:
 

We have a page type that when created should have some blocks already populated in its ContentArea. These blocks should be programmatically created and published in the "For this page" assets folder upon page creation. We have to check whether the page already has this folder or not. If it doesn't have the folder it must be programmatically created as well. The howto is explained here: http://world.episerver.com/Documentation/Items/Developers-Guide/EPiServer-CMS/75/Content/Assets-and-media/Content-assets-and-folders/. We have used a slightly different implementation:

public ContentAssetFolder GetAssetsFolder<T>(T content) where T : class, IResourceable, IReadOnly, IContent
{
    if (content.ContentAssetsID == Guid.Empty)
    {
        var contentResourceFolder = _repository.GetDefault<ContentAssetFolder>(content.ContentLink);

        //Create writable clone since attach will update content as well
        content = content.CreateWritableClone() as T;

        //Call Attach to set references between the content and resource folder
        contentResourceFolder.Attach(content);
        var contentAssetsFolderReference = _repository.Save(contentResourceFolder, SaveAction.Publish);

        //Need to save content as well to persist ContentResourceID
        //Get current state of content to get correct save action
        var saveAction = FilterPublished.CheckPublishedStatus(content, PagePublishedStatus.Published)
            ? SaveAction.Publish : SaveAction.Save;
        _repository.Save(content, SaveAction.ForceCurrentVersion | saveAction);

        return _repository.Get<ContentAssetFolder>(contentAssetsFolderReference);
    }

    return _repository.Get<ContentAssetFolder>(content.ContentAssetsID);
}

    

The problem is that this programmatically created assets folder differs from the default "For this page" assets folder in two key ways:

- The icon is a standard blue folder, just like any other global folder (unfortunate as it doesn't give the editor the well known visual clue that this is the local assets folder for the page)
- The folder has the same options available as a global folder, hence it can be deleted (unlike the default "For this page" assets folder).

Is there any way I can make this programmatically created folder look and behave similar to the default "For this page" folder?

#81106
Feb 10, 2014 13:51
Vote:
 

Hey Lars,

You can use ContentAssetHelper class to create 'For this page' folder like this:

var contentAssetHelper = ServiceLocator.Current.GetInstance<ContentAssetHelper>();
// get an existing content asset folder or create a new one
var assetsFolder = contentAssetHelper.GetOrCreateAssetFolder(myPage.ContentLink);

   

So first you must create the myPage and then save/publish it, and after that you can call contentAssetHelper.GetOrCreateAssetFolder. ContentAssetHelper will automatically attach that folder for you.

 

#81119
Feb 10, 2014 17:52
Vote:
 

Ah, brilliant :) Works like a charm. Thanks, Dejan!

#81154
Feb 11, 2014 9:21
Vote:
 

Can I use this contentAssetHelper also to create a content folder programmetically in the Media Panel and give it a specif name?

I found an article about this for EPiServer E-Commerce but this is not working for CMS unfortunality:
http://world.episerver.com/Documentation/Items/Developers-Guide/EPiServer-Commerce/75/Content/Assets-and-media/Legacy-Asset-Management/Legacy-asset-management/

#111964
Oct 21, 2014 14:14
Vote:
 

Johan Viklund has just wrote this neat function;

        /// <summary>
        /// Returns a <c>ContentFolder</c> folder 
        /// </summary> 
        /// <param name="parentFolder">The folder container.</param> 
        /// <param name="folderName">Identifier for folder.</param> 
        /// <param name="languageId">Identifier for language branch.</param> 
        /// <returns>Stored <c>ContentFolder</c> folder; otherwise created folder.</returns> 
        private ContentFolder GetOrCreateFolder(ContentReference parentFolder, string folderName, string languageId)
        {
            var languageSelector = new LanguageSelector(languageId);
            var storedFolder = _contentRepository.GetChildren<ContentFolder>(parentFolder, languageSelector)
             .FirstOrDefault(f => string.Compare(f.Name, folderName, StringComparison.OrdinalIgnoreCase) == 0);
            if (storedFolder != null)
            {
                return storedFolder;
            }

            var parent = _contentRepository.Get<ContentFolder>(parentFolder, languageSelector);
            var folder = _contentRepository.GetDefault<ContentFolder>(parent.ContentLink, languageSelector);
            folder.Name = folderName;

            var folderReference = _contentRepository.Save(folder, EPiServer.DataAccess.SaveAction.Publish, AccessLevel.NoAccess);

            return _contentRepository.Get<ContentFolder>(folderReference);
        }
#112617
Edited, Oct 31, 2014 18:59
Vote:
 

Thanks for sharing, Miriam! Here's a little tip to make it even better: Use GetBySegment to find any existing content, instead of iterating the children using GetChildren. This will greatly improve performance if there are lots of children. Something like this:

        private ContentFolder GetOrCreateFolder(ContentReference parentFolder, string folderName, string languageId)
        {
            var languageSelector = new LanguageSelector(languageId);
            var storedFolder =
                _contentRepository.GetBySegment(parentFolder, folderName, languageSelector) as ContentFolder;
            if (storedFolder != null)
            {
                return storedFolder;
            }
            storedFolder  =_contentRepository.GetDefault<ContentFolder>(parentFolder, languageSelector);
            storedFolder.Name = folderName;
            _contentRepository.Save(storedFolder, EPiServer.DataAccess.SaveAction.Publish, AccessLevel.NoAccess);
            return storedFolder;
        }




 

#112619
Edited, Oct 31, 2014 22:03
Vote:
 

Per, as per Episerver 9.0.3, the call of IContentRepository.GetDefaul<T> should be as follows:

storedFolder  =_contentRepository.GetDefault<ContentFolder>(parentFolder, languageSelector.Language);
#178056
Apr 28, 2017 10:08
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.