Since a couple of weeks when I started with EPiServer I experimented a lot. Here is a quick summary of some code fragments that I found on the internet that can be very usefull in some cases. I am not going into detail about these code fragments because honestly I dont understand all of it (yet).
Creating a page that can be used as a block in a contentarea
Sometimes you want a page that can also be dragged in a contentarea and should display differently when inside such contentarea.
The same page also exists as a ‘real’ page. But it looks (renders) differently when viewed as a ‘real’ page:
The accomplish this behaviour we need to create two controllers, one for each rendering type.
1 2 3 4 5 6 7 8 9 10 |
public class BlogPageController : PageController<BlogPage> { public ActionResult Index(BlogPage currentPage) { /* Implementation of action. You can create your own view model class that you pass to the view or * you can pass the page type for simpler templates */ return View(currentPage); } } |
The controller above, which inherits from PageController, is the controller for the normal view of the page.There is nothing special about this controller.
1 2 3 4 5 6 7 8 9 10 |
public class BlogPagePartialController : PartialContentController<BlogPage> { public override ActionResult Index(BlogPage currentPage) { /* Implementation of action. You can create your own view model class that you pass to the view or * you can pass the page type for simpler templates */ return PartialView("~/Views/Shared/PagePartials/BlogPage.cshtml",currentPage); } } |
If the page is dragged into a contentarea and used as a block the controller BlogPagePartialController is used. Notice this controller inherits from PartialContentController and returns a PartialView.
So all you need are two different controllers and two different views.
If you dont create a page partial for your page and you drag your page into a contentarea you will see a message like “The ‘…Page’ cannot be displayed”
Using the ServiceLocator to get/load content pages
Sometimes you want to to read the content of a page that an editor has created in EPiServer. To get the content of a page you need to use the servicelocator from EPiServer.
1 2 |
var service = ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>(); var productdetails = service.Get<WebshopProductPage>(new ContentReference(pageContentID)); |
This example demonstrates how to access the property values of a webshop product page. Every page an editor creates in EPiServer has a unique pageContentID. This ID can be found in your view under:
1 |
@Model.CurrentPage.PageLink.ID |
Or from your controller:
1 |
var pageContentID = currentPage.PageLink.ID; |
Creating a new content page from code
In some cases you want to generate new content pages from your code. For example when you create a customer service page and customers can submit questions on that page that could end up in your FAQ. When a customer submits such question from a web form on your page your controller creates a new FAQPage content page. An editor can then see this content page in the CMS and answer the question and publish it to display the question with answer on the website.
1 2 3 4 5 6 7 8 9 10 11 |
var contentRepository = ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>(); // GetDefault means make a new page under currentPage.ContentLink FAQItem fi = contentRepository.GetDefault<FAQItem>(currentPage.ContentLink); // Add data fi.Question = question; fi.Name = question; // Save new page. It will be created under FAQPage contentRepository.Save(fi, SaveAction.Save, AccessLevel.Read); |
The above code uses the Servicelocator to access the content repository. This is where your content is stored. Then instead of using Get you use GetDefault. The difference is that Get loads an existing content page, like you did in the example above, and GetDefault creates a new content page for you of the type FAQItem and under node currentPage.ContentLink. The currentpage here is the FAQ startpage. So these pages will be created as a subpage of the FAQ startpage.
Next you fill this new empty page with content and then you save or publish the page. In this example we only want to save the page, not publish it because the editor needs to answer the question before it should appear on the website. Thats why we use SaveAction.Save here and not SaveAction.Publish.
After saving the page and editor can find the page under the FAQ startpage node in the content tree.
When you create pages you can choose any page to be his parent. The easiest way to access other pages is to put a PageReference property on your startpage and call it for example FAQContainer and then use it like this:
contentRepo.GetDefault<FAQItem>(PageReference.StartPage.FAQContainer)
Looping through all child pages of a parent page
We are now able to get a single page from a contentID and we can also save a new page under a parent page. Next I show you how to get those pages and display them. This could be useful on the FAQ startpage where we want to show all published questions.
The next example is for demonstration purpose only. Normally you dont put this info in the model but you put it in the ViewModel. But lets say you have a property FAQItems in your FAQPage model:
1 2 |
[Ignore] public virtual IList<FAQItem> FAQItems { get; set; } |
The [Ignore] attribute tells EPiServer this property should be ignored in the editor and is only used in code.
Next we set this property in our FAQPage controller.
1 2 3 4 5 6 7 8 9 10 |
public ActionResult Index(FAQPage currentPage) { var model = new PageViewModel<FAQPage>(currentPage); // Get FAQItems var contentRepository = ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>(); currentPage.FAQItems = contentRepository.GetChildren<FAQItem>(currentPage.ContentLink).ToList(); return View(model); } |
And now in our view its really easy to loop through all FAQ questions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@if (Model.CurrentPage.FAQItems != null) { <ul> @foreach (FAQItem item in Model.CurrentPage.FAQItems) { <li> <strong>@item.Question</strong><br/><br /> <i>@item.Answer</i> </li> } </ul> } else { <p>No questions found so far!</p> } |