Presenting: Find My Content

My main project is a multi website solution where 16 different websites is sharing the same source code.

Sometimes when we need to change specific Content Type and find a strategy on how to migrate the changes it’s good to know how much that Content Type is used, and in what way.

How do you do that?

A way to to find how much it is used is to perform a simple SQL Query:

SELECT c.pkID FROM tblContent c
INNER JOIN tblContentType ct ON c.fkContentTypeID = ct.pkID
WHERE ... = '...' -- various ways to identify your Content Type using pkID, ContentTypeGUID or Name

And go to Episerver Edit Mode to see how the editor has worked with each content.

But to be able to run the SQL query, you will need to have access to the production database which makes things a little more annoying. Specially if you need to use VPN connections or similar.

Therefore I have created an Admin Tool called “Find My Content” where you easily can find all content based on their Content Types.

Listing all Content Types

findmycontent.PNG

Here you see how many items of this Content Type is created by clicking the Name.

Details of a Content Type

findmycontent standardpage.PNG

In the details you can see all Content of this Content Type and which language they are created in. There is also a shortcut that will take you to Edit mode for that specific Content.

How do I get it?

I’m waiting for a NuGet package to be published on Episerver’s NuGet feed. Otherwise you can find the code on my GitHub.

Update: It is now available in the feed: https://nuget.episerver.com/en/OtherPages/Package/?packageId=Toders.FindMyContent

What’s next?

This was just something I threw together since I got tired connecting to my client’s environments using VPN and Remote Desktop.

I’ve got some ideas to add references between the different content, filtering on values for specific properties and so on.

Do you have any other ideas that would be nice to have in this tool? Just give me a shout in the comments below.

Episerver Event Helper v3.0

Years pass and hopefully you learn something and become better!

One thing that have been poking on my conscience for a while is the old EPiEventHelper that I blogged about a couple of years ago.

What’s wrong with it?

There are two things I don’t like with it.

1) Unclear usage

I have seen that it has been some confusion with how to best access the content – using the eventArgs.Content or using this.

public class StandardPage : PageData, IPublishingContent
{
    public void PublishingContent(object sender, ContentEventArgs e)
    {
        // this is how to access the already cast instance of the content.
        StandardPage standardPage = this;

        //This is the content from the argument, needs to be casted to your Content Type. But to me it feels more correct.
        IContent contentFromArgument = e.Content;
    }

}

A common question is if the e.Content and this are two different instances (they are the same) and which one should be used (honestly I don’t have a recommendation).

2) Single Responsibility Principle

The second thing is that this implementation violates the Single Responsibility Principle. The class representing your Content Type should been seen as a View Model or Data Model and therefore it should not contain any behavior or business logic.

I have seen some examples where the logic found in the event is really large, making the Content Type class very messy and hard to understand.

Presenting – EPiEventHelper 3.0

What? Why 3.0?

Pavel Nezhencev already created a NuGet package with EPiEventHelper and later upgraded it to use Episerver 10, calling it version 2.0. If I want to publish my version with new features to NuGet.org I need to bump the version even further.

What’s new?

First of all I have stopped checking if the current Content implements the event interface. Instead I’m using to use the IoC container in Episerver where you as a developer can add your own things.

This means that you will need to decorate your implementations of the interfaces with the ServiceConfiguration attribute.

[ServiceConfiguration(typeof(IPublishingContent))]
public class PublishingContentEvent : IPublishingContent
{
    public void PublishingContent(object sender, ContentEventArgs e)
    {
        IContent content = e.Content;
        var standardPage = content as StandardPage;
        if (standardPage == null)
            return;

        // Do something with your standard page
    }
}

Breaking change: This also means that if you are using the previous version of EPiEventHelper, you can no longer refer to the content using this!

public void PublishingContent(object
    sender, ContentEventArgs e)
{
    this.Name = "Hello World!";
}
public void PublishingContent(object
    sender, ContentEventArgs e)
{
        e.Content.Name = "Hello World!";
}

Breaking change: The interface does not know anything about the class representing your Content Type and therefore you will need to cast e.Content yourself!

public void PublishingContent(object
    sender, ContentEventArgs e)
{
    this.Title = "Hello World!";
}
public void PublishingContent(object sender,
    ContentEventArgs e)
{
        var content = e.Content as StandardPage;
        if (content == null)
            return;

        content.Title = "Hello World!";
}

Unless…

I have created a workaround for this where you can have the same pattern to bind the Episerver events, but only apply if to specific Content Types AND the Content will also be typed!

New functionality: Each interface have an abstract base class where you specify which Content Type class you want to use. As usual you use the ServiceConfiguration attribute to bind your implementation to the event.

[ServiceConfiguration(typeof(IPublishingContent))]
public class PublishingStandardPage : PublishingContentBase<StandardPage>
{
    protected override void PublishingContent(object sender, TypedContentEventArgs e)
    {
        // Here you can access the standard page
        StandardPage standardPage = e.Content;
    }
}

You can also specify if the Content that the event applies to needs to be the exact Content Type or that the class would inherit from it by overriding the boolean property AllowInheritance.

protected override bool AllowInheritance { get { return true; } }

Tests

I’m still learning how to best create tests with Episerver, so I have added a Test Project where I want to test if the events are bound and unbound properly.

I have also added some tests to make sure that I have not missed any interfaces or classes. The project is found in the same GitHub Repo.

You’re welcome!

I would really recommend that you take your time to extract the code for your events from the Content Types.
Just putting the ServiceConfiguration attribute on your Content Types would instantiate the class in a way that doesn’t always play well with Episerver.

I’m planning to update the NuGet feed with my new version! Keep your eyes open for updates in Visual Studio if you have used the previous version.

Removing all translations – Part I (understanding the Episerver Database)

Me and some colleagues had a project where we needed to remove all translations from an Episerver website except one.

For that we needed to know what the database structure looks like in Episerver and I will share this to all of you!

Now I’m trying out something new – a video post! I know it’s not the best quality but it’s a start.

In this video I will describe some of the most important tables in the strucuture and how they are related to each other.

I hope you like it! Please add some comments for questions or feedback.

Planning your Episerver project

You’re going to start working on a brand new Episerver project! Your solution is a brand new slate where you can add your best code ever and you just received the design specs and requirements!

xmBjXcm.gif

Now you need to sit down and get an idea how to build your solution. But where should you start?

In this blog post I’m trying to give some hints of how I use to plan building an Episerver website. Since the sales, concept and requirement phases can be very different from company to company (and sometimes even project to project) I will try to keep to a very fundamental level.

First of all I’m asking myself the following questions:

What do I want do to?

Get an idea of what the solution should solve and which functions that is needed.

giphy-1.gif
The answer to this could be “a website” – but what should it contain? News articles where the user can list and filter based on categories and date? Product presentation where you can rate each product? Logged on functionality with profile presentation?

Sometimes the requirements from earlier phases in the project already have this but I’ve seen lots of requirements which are still on a concept level rather than a functional spec.

Try to summarize a map of functions from an abstract perspective and leave out the details for now.

My example throughout this post have

  • Customer profiles.
  • Product presentation.
  • Authenticate to edit their profile.
  • A customer can also rate news. In the future maybe even products so let’s keep that function isolated.

scope.png

Using the SOLID principles, this could maybe become the start of your architectural design of functionality in the project as you want to separate the functions.

What areas are Content logic vs Business logic?

When I say Content Logic I refer to things you can do within your CMS’ API such as listing, filtering and reading content based on what is created by the editor while Business Logic would be connected to other data and functionality from systems or databases than your CMS.

Looking at the defined functions from the image above, I define what I can do in Episerver in terms of data structure, and what comes from other systems.

Example how to define: Your page displays a list of links but you don’t know where they are stored:

  • Should the editor just add links using the Link Item Collection, Content Area or the XHTML property in Episerver?
  • Should the list automatically be fetched from the content in Episerver (for example children to a specific page)?
  • Should the list be fetched from an external service such as Delicious, Pocket or similar?

The first options would be Content Logic while the second one is Business Logic.

Based on the functions in the image above and what I know so far I can start marking which sections are Content or Business.

business vs content.png

Also remember to start focus on the areas that are critical for the project, the other things can usually be decided later on (especially if you’re working agile).

From this I would start with the content logic to see how to structure these.

Content – because it’s a website!

What is the content structure?

When I have decided which areas comes from the CMS, I would try to define what parts I would need to create in Episerver based on the design specs and requirements.

Example how to define: The “normal page” and “news article page” are visually identical, except that the “news article page” also have images.

  • Should I create two separate page types?
  • Should I only create only one page type, but be able to add the image list as a block?
  • Should I only create one page type, as the normal page might also be able to have an image list?

 

How the editor would work with the content has a large role in my decisions as well as how it can be generalized and reused to minimize the headache for the developers in the future.

I try to make pages as generic as possible. To have many very similar content types will in the end become hard to maintain since they could have the same functionality.

Having a modular approach is quite nice for that, although it can get quite messy for the editor if there are hundreds of block types to choose from.

Another trick is to find a structure where you restrict enough for the editor, while still letting the editor be able to be creative and have freedom with their content. This is a very hard thing to find!

My suggestion is to have a simple data structure and look at how to simplify the editor experience using EditorDescriptors and maybe even Dojo. Sometimes you can even use the Edit mode to make a better Editor experience than the Properties mode.

So based on the “News” section in the image above I would structure the implementation like this.

content logic.png

Where the normal “Data Layer” in a three tier is the Episerver API. In the Content Logic I build functionality to filter and sort the content and the presentation is the usual Views and frontend resources.

Content – How should everything be rendered?

To start with, try to keep the rendering of your website as a normal “.net website” as much possible using Episerver as the data container.

I would recommend that you use the EPiServer:Property web control (WebForms) or PropertyFor HTML extension method (MVC) when rendering properties and content.
You’ll get tons of nice features with RenderSettings, Tags, Display Options, Display Channels and just to name a few.

When it comes to tweaking your rendering, the Alloy project has quite a lot of examples, however they are no documentation on why, how or exactly to use these and which code is related to which functionality. Don’t refer too much to Alloy templates as it would be overkill for a normal content website.

Business Logic – because I have lots of complex things to build!

Here is a nice part about building an Episerver website – basically it’s like building a normal .NET website where you’ll get a great API for your content (and an interface for your editors to work with that content).

For the other logic you can add tools like Entity Framework, IoC containers, external web services or other stuff you like to play with! Mostly I recommend using a 3 tier approach where you separate data from logic.

Once I have figured out the functionality that does not directly concern content, I look at how I can fit the presentation in Episerver.

There are three common approaches to present external data:

  • Import all data as content using a scheduled job or similar.
  • Create a content type for your data, but use keys in the context (QueryStrings or Routing) to identify which data item to display.
  • Use a Content Repository which is a built in tool in Episerver that handles content structure, routing, access rights and so on for programmatically.

Normally I would go for importing the data or using a Content Repository.

Based on the “Products” section in the image above, I would structure the implementation something like this.

business.png

Where I read and save from my own database or external sources in the Data Layer, creating business logic that handles the Data Layer in “Business Logic” and glue this together with Episerver in the Content Logic.

On top of that I would have the presentation layer as usual with Views and frontend resources.

There is one thing you should keep in mind though!

Don’t make your solution too dependent on external systems – have a fallback plan

closed.png

When your website loose connection to an external service that provides information make sure that it does not go down.

For example store the information locally so that it can be used when the connection is lost, or display a sign that tells the visitor that all areas of the website are not working at the moment.

Unfortunately I don’t have a silver bullet solution on how to present your data, but as long as you don’t start throwing lots of 500 (specially not on the start page) and that reading the external data does not make the website slow.

Logic finished – now what?

Normally I work in agile projects (based on how we can work with the client), at least we split most of our project into iterations or sprints.

i.chzbgr.gif

Most of the time, the customer wants to be up and running with the content work as soon as possible, so in the first iterations I try to plan the most common content types that they will work with.

Creating an MVP

In the example above I would have Henric Kniberg’s example of creating a MVP (minimum viable product) and start working with the basics that are less automated.

  • News
    The editor can create news articles but the listing would either be a very basic one or even be created manually by the editor.
    Automatic listing with filters would be created in a later sprint.
  • Products
    Say that I decided to go for the “import all products as pages” approach.
    I would prioritize building the product pages so that the editors can create some examples that they give feedback to.
    I would create the product import in a later sprint.
  • Profiles
    I will create the content types necessary, but after the first sprint the customers needs to contact support to change these.
    Authentication would come later, and then I can look at letting the customer update their profiles.

Ok I admit that this is a very simple priority! Pushing more complex sections such as product import and authentication to later sprints means there is a risk that they won’t make it to launch.

But this is a rough plan based on that the only priority for the customer is to start working with content.

However I want you to keep in mind that take small steps instead of building the entire project at the same time.

Summary

So! Thank you for following me through this article. These are some major thoughts I have on how to plan an Episerver project.

So a short recap

  • An Episerver website is simply a .NET solution where you get an API to fetch content (and an interface for the editor to work with the content).
  • Build your system integrations separately and integrate them using the Episerver API.
    • Make sure that your site does not crash because your integrations can’t integrate.
  • Start of simple and add the more complex parts later.

If you don’t agree of want to add to my list, please add a comment below.

bye.gif

How to NOT use properties on Content Types

I’ve seen more and more examples on how to NOT use properties on your Content Types – setting visit/Request specific information to them.

My example below is a very harmless, but I’ve seen examples where the price for an e-com site is set like this!

How do you mean?

The example would be to display the visitor’s IP, which is common to be different for each request.

First of all we have a Block Type:

[ContentType(GUID = "5597f215-f5cc-4fd0-bcff-eb06a44fc343")
public class MyPage : PageData
{
    public string MyProperty { get; set; }
}

And the controller set’s the value:

public class MyPageController : PageControllerBase<MyPage>
{
    public ActionResult Index(MyPage currentPage)
    {
        currentPage.MyProperty = Request.UserHostAddress;
        return View(currentPage);
    }
}

And a view displays it:

@model MyPage
Name: @Html.PropertyFor(m => m.Name)
IP: @Model.MyProperty

But what’s the problem?

The problem is that each instance of MyPage is cached and could basically be referred to as “static” – when a value is set to MyProperty, the value is set for all visitors.

For example when visitor A visits from IP address “192.168.0.10”, MyProperty is set with the IP. When visitor B visits from “192.168.0.11”, MyProperty will still have the value from visitor A until the controller sets the IP from visitor B.

Or even worse: When the the visitor A comes to the view and MyProperty is rendered there is a chance that visitor B comes to the controller and sets a new value to MyProperty – so that the view will render the IP from visitor B.

I’m sorry for the crappy GIF, but hope you get the point ;)

properties

So what should I do?

Make sure that you have a specific class that contains your information and create a new instance of this class for each Request. For my example I would have a viewmodel instead. In Episerver projects the ViewModel could also contain the Content itself:

[ContentType(GUID = "5597f215-f5cc-4fd0-bcff-eb06a44fc343")
public class MyPage : PageData
{
}

public class MyPageViewModel
{
    public string MyProperty { get; set; }
    public MyPage CurrentPage { get; set; }
}

With the Controller

public class MyPageController : PageControllerBase<MyPage>
{
    public ActionResult Index(MyPage currentPage)
    {
        var viewModel = new MyPageViewModel
        {
             MyProperty = Request.UserHostAddress,
             CurrentPage = currentPage
        };
        return View(viewModel);
    }
}

And with the View

@model MyPageViewModel
Name: @Html.PropertyFor(m => m.CurrentPage.Name)
IP: @Model.MyProperty

Again this a simple example, but say you’re having an e-com solution and want to display the price. You don’t want to display other visitor’s prices don’t you? ;)

Where to integrate with Episerver Forms

If you want to control what’s going on when a form created with Episerver Forms is submited, there are different areas you can implement your logic. The most usable ones (or the ones most people would go for) would be Controllers where the submitted form is posted, the implementation of DataSubmissionService, various Events and through Actors.

So which one should you use? It all depends on what you want to do and here are my thoughts on where to integrate depending on what you want to do.

So what are these?

First we’ll do a quick check on the different areas I mentioned.

lifecycle

Controllers

First of all, Episerver Forms use two Controllers that receive data from the posted forms.

DataSubmitController

This one is called with the out of the box Javascript-driven functionality that makes an AJAX request with the form data. This requires the visitor’s browser to be able to use Javascript.

To replace this controller, the easiest way would be to change the path with coreController configuration in \modules\_protected\EPiServer.Forms\Forms.config.

There are some other ways but that would require that you create your own Javascript-functionality for the form, which would require that you create your own rendering Controller for FormContainerBlock (see below) that does not output the OOTB Javascript references.

FormContainerBlockController

This is if you have turned off the Javascript-support using the workInNonJSMode configuration in \modules\_protected\EPiServer.Forms\Forms.config or if the visitor’s browser does not have Javascript support.

To replace this controller you’ll need to create your own rendering Controller and make sure that it is used instead of the original FormContainerBlockController.

DataSubmissionService

This class is used by the Controllers and takes care of the submitted data, validates and stores it. It is registered into Episerver’s IOC with the usage of EPiServer.Forms.Services.DataSubmissionService.

You can simply replace it by creating a ConfigurableModule. However as it handles quite alot of the nice stuff to interpret the submitted information from the forms, I would recommend to not play around too much here.

Events

As I mentioned in my previous post about Episerver Forms, there are some Events that you can hook up to:

  • FormsSubmitting
    Before each step, at least once
  • FormsStepSubmitted
    After each step, at least once
  • FormsSubmissionFinalized
    When final step is posted
  • FormsStructureChange
    When a Form Container Block is published

Events were the most common way in XForms to take care of the data that was submitted from the form, for example if you want to save or send it somewhere.

Actors

Actors are the ones that do the final actions when submitting the form. They implement the interface IPostSubmissionActor and the built in actors are SendEmailAfterSubmissionActor and CallWebHookAfterSubmissionActor.

The simplest way to create your own Actor is to create a class that inherits PostSubmissionActorBase.

As you’ve seen with the WebHook and E-mail actors, you can also create your own interface to customize the Actor from the editor interface but I don’t have any examples for that right now.

Thanks for the update, but I still don’t know which I should use?

Controllers

Given the various options I would rarely touch the Controllers since they manage both the initiation and rendering of your forms.

If you’re daring enough to replace the overall rendering, for example when it comes to the Javascript based submits, go ahead and create your own FormContainerBlockController.

From a rendering point of view the FormContainerBlock is nothing more than a block that has a Controller with a TemplateDescriptor attribute. These are stored as TemplateModels in the TemplateModelRepository and can be modified there using an InitializationModule.

DataSubmissionService

Here all the nice stuff to interpret the posted data, store files and so on, so I would try to keep this intact.

The only good reason I’ve heard where it would be necessary to replace the DataSubmissionService would be to override where uploaded files are stored.

Events

This is the classic way to read and do something extra with the posted information. It still works, but I would say that if you want to save or send the data at the end station of the cycle, this would not be here.

Here I would recommend that you read or modify the data if needed, but don’t perform any actions based on it.

Actors

This is where the train stops and all Actors that are interested in the data from the form do what they are supposed to do. If you’re going to send extra information to an external service I would suggest you do that here.

Summary

I haven’t worked with Episerver Forms in a live project yet, but at least these are the areas I would suggest you can use. If you have any ideas or more tips, feel free to add a comment below!

Episerver Forms: How to change where uploaded files are stored

During my session about Episerver Forms at the Øresund Episerver Developer meetup I received a question about how to change where uploaded files are stored

A quick look at how Episerver Forms manage the posted information I found that it is the DataSubmissionService that creates an Asset Folder and stores the file.

assetfolder

By replacing the original DataSubmissionService with a custom one that overrides the method StorePostedFile I could easily decide for myself where to store uploaded files.

Take a look at my example from GitHub.