Sitefinity dynamic modules support relating one module with another as shown in this blog post but when several content types are related to each other their management starts to be quite a daunting task. For instance, even in a simpler scenario where we have book stores, books, authors, to relate the books to their authors and the stores in which they are available the user has to first create a book, then go to the author and assign the book to it, and then go to the store and set that the book is in that store. Now imagine all that with 5, 7 or more related content types. Here I am going to suggest a simple way to relate your items using Sitefinity EventHub. That way when a book is published, it will automatically update store and author items.
To simplify the example I am going to use only two content types – a book and an author. Then when a book is added I will update the author item and add the book to it. Here is a short video displaying the end result: http://screencast.com/t/DAS0yLbbr
In our case when a book is published we will use the EventHub to update the authors. But first we need somehow to relate the authors to the books and the books to the authors. The recommended way is to use Sitefinity Thunder to create Item selectors in the books for authors and vice versa. There is an example in the blog post that I mentioned in the beginning. So, having this all set up, add the following code to your Global.asax file:
The event that will fire on creating a new book item is registered on Bootstrapper.Initialized event - it is called after all Sitefinity modules are initialized. If you simply call it in Application_Start it won't work. I have added comments to the method called from the event that explain the whole process.
To simplify the example I am going to use only two content types – a book and an author. Then when a book is added I will update the author item and add the book to it. Here is a short video displaying the end result: http://screencast.com/t/DAS0yLbbr
In our case when a book is published we will use the EventHub to update the authors. But first we need somehow to relate the authors to the books and the books to the authors. The recommended way is to use Sitefinity Thunder to create Item selectors in the books for authors and vice versa. There is an example in the blog post that I mentioned in the beginning. So, having this all set up, add the following code to your Global.asax file:
protected
void
Application_Start(
object
sender, EventArgs e)
{
Bootstrapper.Initialized += Bootstrapper_Initialized;
}
void
Bootstrapper_Initialized(
object
sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
{
EventHub.Subscribe<IDynamicContentCreatedEvent>(ItemCreatedhandler);
}
public
void
ItemCreatedhandler(IDynamicContentCreatedEvent eventInfo)
{
DynamicContent book = eventInfo.Item;
//The event is fired several times when an item is published though the backend so we need to get it exactly when it is being published
//And we also need only specific items - this time "Books"
if
(book.ApprovalWorkflowState ==
"Published"
&& book.GetType().ToString() ==
"Telerik.Sitefinity.DynamicTypes.Model.Library.Book"
)
{
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager();
Type authorType = TypeResolutionService.ResolveType(
"Telerik.Sitefinity.DynamicTypes.Model.Library.Author"
);
//Get ids of the related authors
var authors = book.GetValue<Guid[]>(
"Authors"
);
// This is how we get the authors DynamicContent items by their IDs
var authorItems = dynamicModuleManager.GetDataItems(authorType).Where(i => authors.Contains(i.Id));
// Now for every author item we update its books field with the new book if it is not present already
foreach
(var author
in
authorItems)
{
var books = author.GetValue<Guid[]>(
"Books"
).ToList();
if
(!books.Contains(book.OriginalContentId))
{
books.Add(book.OriginalContentId);
}
author.SetValue(
"Books"
, books.ToArray<Guid>());
// This is where changes are persisted to the database. If you are having performance problems SaveChanges can be called once per several items.
dynamicModuleManager.SaveChanges();
}
}
}
The event that will fire on creating a new book item is registered on Bootstrapper.Initialized event - it is called after all Sitefinity modules are initialized. If you simply call it in Application_Start it won't work. I have added comments to the method called from the event that explain the whole process.
Stoimen Stoimenov
Stoimen Stoimenov is Senior QA Engineer in Sitefinity Division. He is responsible for the overall quality of the product and leading various QA tasks in the team.