Exam Area: Content Area 5 – Content Models (25%)
Reference: https://docs.developers.optimizely.com/content-management-system/docs/projects
Projects allow editors to group multiple content items together and publish them simultaneously as a release. For example: campaign launches, product releases.
Project: "Summer Campaign 2024"
├── StartPage (updated hero banner)
├── ProductPage A (new content)
├── ProductPage B (updated pricing)
└── Article 1 (new blog post)
└── All published together → July 1, 2024 at 9AM
using EPiServer.Core.Internal;
using EPiServer.DataAbstraction;
public class ProjectService
{
private readonly IProjectRepository _projectRepository;
private readonly IContentRepository _contentRepository;
public ProjectService(
IProjectRepository projectRepository,
IContentRepository contentRepository)
{
_projectRepository = projectRepository;
_contentRepository = contentRepository;
}
// Create new project
public async Task<Project> CreateProjectAsync(string name)
{
var project = new Project
{
Name = name,
Description = "Summer Campaign 2024"
};
await _projectRepository.SaveAsync(project);
return project;
}
// Add content to project
public async Task AddContentToProjectAsync(int projectId, ContentReference contentLink)
{
var projectItem = new ProjectItem
{
ProjectId = projectId,
ContentLink = contentLink
};
await _projectRepository.AddItemAsync(projectItem);
}
// Get all projects
public async Task<IEnumerable<Project>> GetAllProjectsAsync()
{
return await _projectRepository.ListAsync(new ProjectQuery());
}
// Get project items
public async Task<IEnumerable<ProjectItem>> GetProjectItemsAsync(int projectId)
{
return await _projectRepository.GetItemsAsync(projectId);
}
}
public class ProjectPublishService
{
private readonly IProjectRepository _projectRepository;
public ProjectPublishService(IProjectRepository projectRepository)
{
_projectRepository = projectRepository;
}
// Publish entire project
public async Task PublishProjectAsync(int projectId)
{
await _projectRepository.PublishAsync(projectId);
}
// Schedule publish
public async Task SchedulePublishAsync(int projectId, DateTime publishAt)
{
var project = await _projectRepository.GetAsync(projectId);
project.ScheduledPublishDate = publishAt;
await _projectRepository.SaveAsync(project);
}
}
Edit View → Projects panel (left sidebar)
→ Create new project
→ Add current page to project
→ View all project items
→ Publish/Schedule project
CMS toolbar when editing:
→ Project selector dropdown
→ "Add to project" button
// Read content in project context (draft)
public class ProjectContextService
{
private readonly IContentRepository _contentRepository;
private readonly IProjectRepository _projectRepository;
public async Task<IContent> GetContentInProjectAsync(
ContentReference contentLink, int projectId)
{
// Content in project may be a draft version
var projectItems = await _projectRepository.GetItemsAsync(projectId);
var projectItem = projectItems
.FirstOrDefault(i => i.ContentLink.ID == contentLink.ID);
if (projectItem != null)
{
// Load project version
return _contentRepository.Get<IContent>(projectItem.ContentLink);
}
// Fallback to published
return _contentRepository.Get<IContent>(contentLink);
}
}
public interface IProjectRepository
{
// CRUD
Task<Project> GetAsync(int projectId);
Task<IEnumerable<Project>> ListAsync(ProjectQuery query);
Task SaveAsync(Project project);
Task DeleteAsync(int projectId);
// Items
Task<IEnumerable<ProjectItem>> GetItemsAsync(int projectId);
Task AddItemAsync(ProjectItem item);
Task RemoveItemAsync(int projectItemId);
// Publish
Task PublishAsync(int projectId);
Task<int> CountAsync(ProjectQuery query);
}
| Feature | Projects | Content Approvals |
|---|---|---|
| Purpose | Group & release together | Approval workflow |
| Who controls | Editors | Admins/Approvers |
| Schedule | Can schedule publish | No |
| Multi-content | Multiple content items | Per item |
| Workflow | No steps | Has approval steps |
// Query projects with filters
var query = new ProjectQuery
{
Status = ProjectStatus.Open, // Open/Archived
Page = 1,
PageSize = 10,
Search = "Summer" // Name search
};
var projects = await _projectRepository.ListAsync(query);
IProjectRepository provide? (CRUD for projects, add/remove items, publish)project.ScheduledPublishDate = publishAt; _projectRepository.SaveAsync(project))