Domain Driven Development with DD4T and XPM

What a title that is 🙂

DD4T stands for Dynamic Delivery For Tridion and is a leightweight ASP.NET MVC framework build on top of the SDL Tridion stack. It’s opensource and you can find more about it here

XPM is the WYSIWYG editor (and much more!) that ships with SDL Tridion.

Domain Driven Development is… well, Wikipedia explains it better than I can, so check it out!

I am a big fan of the MVC framework from Microsoft. No wonder I also love the DD4T framework as it makes building MVC websites with SDL Tridion a LOT easier.
One of the shining features of SDL Tridion is its recently upgraded WYSIWYG editor (Or Experience Manager) that allows editors to edit the content of the website in the context of the website itself, in the browser.
This is a great feature and makes it very easy to adjust content in a natural way.

Of course, before content editors can use the Experience Manager (XPM from now on) the SDL Tridion consultant has to pull some triggers to make this possible. All relatively easy to do.

But with DD4T it’s not so straight-forward as one would want. And especially if you are doing (a form of) Domain Driven Development, and thus are using (domain)ViewModels.

Before you read on, I highly recommend that you read Kah Tang’s article on ViewModels in DD4T first. This is how I usually implement DD4T and helps you understand the problem we are trying to solve in this post.

I’ve see a few DD4T implementations, and most of them use the OOTB DD4T models as their ViewModels. (Don’t know what ViewModels are? See: http://stackoverflow.com/a/11064362/1221887)

For example, consider the following razor View (which also renders the XPM markup):


@model DD4T.ContentModel.IComponent
@foreach (IFieldSet fieldset in Model.Fields["RelatedLinks"].EmbeddedValues)
{
<div class="cd-list">@if (fieldset.ContainsKey("Link") || fieldset.ContainsKey("ExternalLink"))
{
<a class="cd-link-ext" title="" href="@fieldset[" target="_blank">
@Html.SiteEditField(Model, fieldset["Image"])
@fieldset["Image"].GetImage("img")
</a>
}
</div>
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

As you can see this View uses the DD4T ‘IComponent’ as it’s ViewModel. And it is using the OOTB DD4T ‘SiteEditField’ HtmlHelper to generate the XPM markup.
While using the IComponent as a ViewModel is valid, it’s not as nice and clean as it could be. Also, the developer has to know the name of the field in Tridion and there’s no compile time checking. While it’s a valid approach, it doesn’t leverage all the advantages of the MVC framework (for example: no strongly typed views).

I always use (domain) specific ViewModel’s. Using your own, domain specific ViewModels has many advantages from which ‘separation of concerns’ and intellisense are just two of them (IMHO).
ViewModels only purpose is to display the Model in a certain way. Sometimes they are (almost) identical to your Domain Model, but a ViewModel can/must have extra properties to make displaying it possible. It results in much clear views.

Consider the following example (not rendering the XPM markup):


@model ArticleViewModel
@foreach(var relatedLink in Model.RelatedLinks)
{
<div class="cd-list">
<a class="cd-link-ext" title="@relatedLink.Title" href="@relatedLink.Url" target="_blank">
@Html.RenderImage(relatedLink)
</a>
</div>
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

As you can see it’s much cleaner and easier to read then the previous View and there is also no logic (checking, etc) involved. (I also could have used an HtmlHelper to write out the tag. It’s up to you.)

But what if your customer asked you to implement XPM? You cannot use the OOTB Html helper since your ViewModel doesn’t have the properties this helper expects.
Well, there are a few options.

1. Add the ‘IComponent’ as a complex property to your ViewModel.
This would look something like this:


@model ArticleViewModel
@{
int counter = 0;
}
@foreach(var relatedLink in Model.RelatedLinks)
{
<div class="cd-list">
@Html.SiteEditField(Model.TridionComponent.Fields["hyperlinks"][counter])
<a href="@relatedLink.Url" title="@relatedLink.Title" class="cd-link-ext" target="_blank">
@Html.SiteEditField(Model.TridionComponent.Fields["Image"][0])
@Html.RenderImage(relatedLink)
</a>
</div>
couner++;
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

It still requires the developer to know the names in Tridion and it’s lacking the strongly typed advantages. (Intellisense)

2. Add the XMP MarkUp as separate properties to your ViewModel:


@model ArticleViewModel
@foreach(var relatedLink in Model.RelatedLinks)
{
<div class="cd-list">
@relatedLink.XPMMarkUp
<a href="@relatedLink.Url" title="@relatedLink.Title" class="cd-link-ext" target="_blank">
@relatedLink.Image.XPMMarkUp
@Html.RenderImage(relatedLink)
</a>
</div>
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

This already looks cleaner and has intellisense. But I don’t like the added properties to the ViewModel. It clutters the ViewModel.

I struggled with this issue for quite some time. But after trying the above mentioned approaches I wasn’t happy with the result. Although it works, it isn’t as nice, clean and intuitive (for a programmer) as it could be.

After spending much time on it I came up with an approach. This approach involved quite some coding, but it’s for a good cause right? And I liked doing it, because I’ve learned a lot of new stuff.

I wanted it to be a generic solution, so everyone using DD4T could use it. This is how it looks like:
(It’s still a work in progress!)

1. Create your ViewModel and decorate it with attributes.
Example:


[InlineEditable]
public class Article : IArticle
{
[InlineEditableField(FieldName="title")]
public string Title {get;set;}
[InlineEditableField(FieldName="short_intro")]
public string Summary {get;set;}
private IList<string> _relatedLinks = new List<string>();
[InlineEditableField(FieldName="related_links")]
public IList<string> RelatedLinks
{
get
{
return _relatedLinks;
}
set
{
_relatedLinks = value;
}
}
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

As you can see there are 2 new Attributes involved.

  • InlineEditable
  • InlineEditableField

The first attribute ‘InlineEditable’ marks the class (ViewModel) as inline-editable with XPM. The second attribute marks a single field as inline-editable with XPM.

Of course this is not everything. Once you created your ViewModel, you have to make a call to a method to do the magic. Since all my ViewModel’s by default are created inside a ModelFactory (a subject for a different post), I made this functionality part of a base-class, but you can implement it any way.
This is how my (simplified) ViewModel builder looks like:


public class ArticleBuilder : BuilderBase
{
private ComponentPresentation TridionComponentPresentation { get; set; }
public ArticleBuilder(ComponentPresentation componentPresentation)
{
TridionComponentPresentation = componentPresentation;
}
public Article Build()
{
var tridionComponent = TridionComponentPresentation.Component;
var articleViewModel = new Article
{
Title = tridionComponent.Fields["title"].Value,
Summary = ResolveRichText(tridionComponent.Fields["short_intro"].Value),
RelatedLinks = tridionComponent.Fields["related_links"].Values.ToList()
//Etc
}
//Work magic for XPM
MakeInlineEditable(articleViewModel);
return articleViewModel;
}
}

view raw

gistfile1.cs

hosted with ❤ by GitHub

That’s all. The article is now ready for XPM. It’s not yet inline editable, but the information from Tridion is added to the class, so we can use it in our View.

Let see how our View would look like if we would make this ViewModel (inline)editable with XPM:


@model ArticleViewModel
<div class="middleContent">
@XPM.StartInlineEditingZone()
<h2>@XPM.Editable(m => m.Title)</h2>
<div class="intro">
@XPM.Editable(m => m.Summary)
</div>
<ul>
@foreach(var relatedLink in Model.RelatedLinks)
{
<li>
@XPM.Editable(m => m.RelatedLinks, relatedLink)
</li>
}
</ul>
</div>

view raw

gistfile1.cs

hosted with ❤ by GitHub

As you can see we have full intellisense and a nice and clean View. Of course, I simplified the example a little, but it proves a point.

The XPM Helper and it’s ‘Editable’ method write out the actual value of the property and its corresponding XPM MarkUp.
There’s also a ‘MarkUp’ method that just write’s out the XPM MarkUp. This becomes handy when you want to make an image or hyperlink inline-editable:


<div>
@XPM.MarkUp(m => m.ImageUrl)
<img src="@Model.ImageUrl" />
</div>

view raw

gistfile1.cs

hosted with ❤ by GitHub

All this is not yet part of DD4T, but I am planning on integrating it in the framework, as I see it as a valuable addition. (If not: let me know).
It encourages the use of (domain)ViewModel’s and results in a cleaner solution.

If you want to the XPM helper in you project now, drop me an email and I will send you the source-code and the instructions on how to set it up. In the end there’s really not much to it, but isn’t that the case with all challenges?

4 thoughts on “Domain Driven Development with DD4T and XPM

  1. Hi,
    great article 🙂
    I have a question – where I can find InlineEditable and InlineEditableField attributes?

  2. Hi Albert,

    This article is very nice,After working with C# and DWT I was thinking how we can separate code from CS HTML in DD4T, Then your article gave me the answer

    I would like to implement this, Can you please share me the code and Instructions to implement into the project.

    Thanks,
    Prasanna

  3. Hi Albert,

    Could you please help me in building view models.
    Can you please share the sample code and instructions how to implement will be help full.

    Thank you,
    Prasanna

Leave a comment