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

Johan Björnfot
Aug 17, 2012
  35336
(4 votes)

EPiServer7: Working with IContentRepository/DataFactory

Introduction

In previous versions of EPiServer the main API to work with pages is EPiServer.DataFactory. In EPiServer7 the main API to work with content (now pages is not the only supported content type) is the interface EPiServer.IContentRepository. The interface instance is exposed through property Locate that is exposed on many base classes (e.g. PageBase, UserControlBase, PropertyData). You can also get it from IOC container through call:

var repository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>();

For those who prefer to work with a concrete class it is still possible to work directly with EPiServer.DataFactory which has a property Instance that gives access to the singleton instance of the repository. Through the repository you could do CRUD (Create, Read, Update, Delete) operations as well as other operations like listings, move etc. on content instances (that is instances implementing EPiServer.Core.IContent). Below are examples of some of the most common operations.

Loading an instance

The method to load a single content instance is to call the method: Get<T> where T : IContentData (corresponds to GetPage in previous versions). The type parameter T specifies which type you want. So if there is a type representing a page as:

[ContentType]
   public class TextPage : PageData
   {
       public virtual string MainBody { get; set; }
   }

and you know which .NET type a given reference refers to then you could load the page in a typed way as:

TextPage page = Locate.ContentRepository().Get<TextPage>(pageLink);

In case the content item is not assignable to the type given as type argument a TypeMismatchException will be thrown. If you do not know the .NET type of an item you can safely load it with IContent as type argument.

var content = Locate.ContentRepository().Get<IContent>(pageLink);

And if you want to load it as a given type but do not want an exception to be thrown in case type is not correct you could load it as:

TextPage page = Locate.ContentRepository().Get<IContent>(pageLink) as TextPage;

And suppose there is a block type defined as:

[ContentType]
public class TeaserBlock : BlockData
{
    public virtual string Heading { get; set; }
    public virtual string MainBody { get; set; }
}

Given that we have created a shared instance of the block and know it’s reference then we can load it in a typed way as:

var contentLink = new ContentReference(12);
TeaserBlock sharedTeaser = Locate.ContentRepository().Get<TeaserBlock>(contentLink);

The type constraint is IContentData in Get<T> to be able to load a shared block in a typed way (as above). However at runtime each instance loadable from repository will implement IContent (a shared block instance will be an instance of a mixin type that will be a new type inheriting TeaserBlock but add some additional interface implementations such as IContent) meaning we can also load the shared block as:

var teaserAsIContent = Locate.ContentRepository().Get<IContent>(contentLink);

You can specify which language version of a content you want by using an overload that takes an ILanguageSelector. If no language selector is specified the content will be retrieved in the same language that the current request specifies (given by ContentLanguage.PreferredCulture). Below is an example on how to get the swedish version of a page.

page = Locate.ContentRepository().Get<TextPage>(pageLink, new LanguageSelector("sv"));

Loading multiple instances

It is also possible to load several content instances at the same time by calling GetItems<T> where T : IContentData (corresponds to GetPages in previous versions). Below is an example on GetItems:

IEnumerable<ContentReference> references = GetSomeReferences();
IEnumerable<IContent> items = Locate.ContentRepository().GetItems<IContent>(references, LanguageSelector.AutoDetect());

Listing children

Content in EPiServer CMS are stored in a tree hierarchy. You can get the children to a content instance by calling GetChildren<T> where T : IContentData. When loading children TypeMismatchException is not thrown if a type is not matching. Instead the result is filtered for types that are assignable to type argument. Below is an example on GetChildren:

IEnumerable<IContent> children = Locate.ContentRepository().GetChildren<IContent>(pageLink);

And if you want to get all children that are pages to a content instance (that means that all other children that are not pages are filtered away) you would call like:

IEnumerable<PageData> pages = Locate.ContentRepository().GetChildren<PageData>(pageLink);

There is also an overload to GetChildren that supports paging. Below is an example where we retrieve the first five children to a page:

children = Locate.ContentRepository().GetChildren<IContent>(pageLink, LanguageSelector.AutoDetect(), 0, 5);

Updating an instance

To persist an IContent instance you call the Save method. In case the IContent instance implements IReadOnly you need to call CreateWritableClone before you can modify the instance. The save method have a SaveAction flag parameter that controls which action that should be done during save for example if the page should be published. Below is an example how to programmatically update a property of a page:

var writablePage = Locate.ContentRepository().Get<TextPage>(pageLink).CreateWritableClone() as TextPage;
writablePage.MainBody = "something";
Locate.ContentRepository().Save(writablePage, SaveAction.Publish);

Creating a new instance

To get a new instance of a content type you call GetDefault<T> where T : IContentData (corresponds to GetDefaultPage in previous versions). When creating a new instance you do not need to call CreateWritableClone since GetDefault returns a writable instance. Below is an example how to programmatically create a new page:

var newPage = Locate.ContentRepository().GetDefault<TextPage>(pageLink);
newPage.MainBody = "something";
Locate.ContentRepository().Save(newPage, SaveAction.Save);

Roundup

in this post we have seen some example on some of the operations that can be done when programmatically working with content. IContentRepository offers more methods such as Delete, Move, Copy and working with language branches etc.

Aug 17, 2012

Comments

Petter Klang
Petter Klang Aug 17, 2012 11:18 AM

Great walkthrough!

Eric
Eric Feb 15, 2013 03:45 PM

If you are creating pages and the "MainBody" you are using in these examples is a string of type XhtmlString you can not set the property with just newPage.MainBody ="something".

You need to create a new string of typ XhtmlString first.

var yourstring = new XhtmlString("something);

Most of the time we user XhtmlString and call it MainBody, in these examples it is only string therefore this is working. :)

Alexander Helsinghof
Alexander Helsinghof Sep 11, 2013 11:23 AM

Any Ideas on why I can't find the Locate?

Eric
Eric Sep 19, 2013 01:52 PM

At the top of the blog post Johan describe how you do it. Either you inherit from PageBase UserControlBase... Or you can load you own with: var repository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance();

Please login to comment.
Latest blogs
Optimizely SaaS CMS + Coveo Search Page

Short on time but need a listing feature with filters, pagination, and sorting? Create a fully functional Coveo-powered search page driven by data...

Damian Smutek | Nov 21, 2024 | Syndicated blog

Optimizely SaaS CMS DAM Picker (Interim)

Simplify your Optimizely SaaS CMS workflow with the Interim DAM Picker Chrome extension. Seamlessly integrate your DAM system, streamlining asset...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Optimizely CMS Roadmap

Explore Optimizely CMS's latest roadmap, packed with developer-focused updates. From SaaS speed to Visual Builder enhancements, developer tooling...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Set Default Culture in Optimizely CMS 12

Take control over culture-specific operations like date and time formatting.

Tomas Hensrud Gulla | Nov 15, 2024 | Syndicated blog

I'm running Optimizely CMS on .NET 9!

It works 🎉

Tomas Hensrud Gulla | Nov 12, 2024 | Syndicated blog

Recraft's image generation with AI-Assistant for Optimizely

Recraft V3 model is outperforming all other models in the image generation space and we are happy to share: Recraft's new model is now available fo...

Luc Gosso (MVP) | Nov 8, 2024 | Syndicated blog