Items in Dynamicweb CMS is a wonderful thing. It allows you to create your own specialized content types and it makes it easy to create custom functionality. Normally, I have been used to creating simple items via the Item Manager in the administration area, and this works perfectly for simple projects where you e.g. need to enable the webmaster to create custom news or calendar elements – simple stuff.
However, in a new project we needed to use the code-first approach. In this project we have a lot of front end stuff going on, and therefore the regular ItemPublisher- and Itemcreator-module in Dynamicweb just didn’t cut it. We needed more than this, and therefore we decided to build our own publisher and creator functionality. In order to do that we needed to be able to create all items via .net.
Now, when you head out in such a project you don’t always see the obstacles right in front of you. One of the main obstacles is that the items-functionality in Dynamicweb CMS is quite new and it is evolving very quickly. If only the documentation was evolving just as quickly!
This is the reason why I’m documenting my experiences here in this blog. I’ve been spending quite a lot of time investigating different approaches – both via my colleagues but also via the Developer Forum. Luckily, the developers at Dynamicweb Software are very quick to provide answers for my questions. The Developer Forum has been my savior a lot of times(!).
The first blogpost here will sum up some of the learnings that I’ve made when creating items via code. This is primarily for my own sake, but I hope that others might be able to use this knowledge as well. Please notice that I will not describe the stuff that is already documented on the developer website right here: http://developer.dynamicweb.com/documentation/for-developers/item-based-structure/getting-started.aspx
Please be aware, that if you create items code-first and you need to modify items later on in the process, you will often need to delete the XML-file representing the item, and also the database table containing the item entries. Otherwise, you might risk that the changes doesn’t appear.
Creating my base item
I first needed to create a base item that other items would inherit from. This code looks like the following:
namespace Bleau.Custom.ItemSubscriber.Items
{
using Dynamicweb.Content.Items;
using Dynamicweb.Content.Items.Activation;
using Dynamicweb.Content.Items.Annotations;
[Item("Base", "Base"), Category("Custom")]
[AreaRule,
StructureRule(StructureContextType.Paragraphs),
ParentRule(ParentRestrictionRule.ParentType.RootOfWebsite, ParentRestrictionRule.ParentType.RegularPage),
TitlePattern("{{Title}}"),
TitleField("Title")]
[CustomizedURLs]
public class Base : ItemEntry
{
[Name("Title")]
[Required]
public string Title { get; set; }
[Field("Category", typeof(Dynamicweb.Content.Items.Editors.DropDownListEditor<>))]
[OptionItem("Category", "CategoryName", "Id", IncludeChilds = true, IncludeParagraphs = true, ItemSystemName = "Category", NameField = "CategoryName", SourceId = 32, SourceType = Dynamicweb.Content.Items.Metadata.FieldOptionItemSourceType.CurrentArea, ValueField = "Id")]
[Required]
public string Category { get; set; }
//private DateTime? activeFrom;
//[Field("Active From", typeof(Dynamicweb.Content.Items.Editors.DateTimeEditor))]
//[Required]
//[DefaultValue("Now")]
//public DateTime Active_From { get; set; }
//[Field("Active To", typeof(Dynamicweb.Content.Items.Editors.DateTimeEditor))]
//[Required]
//[DefaultValue("Now")]
//public DateTime Active_To { get; set; }
[Field("AccessUserID", typeof(Dynamicweb.Content.Items.Editors.HiddenFieldEditor))]
public string AccessUserID { get; set; }
[Field("Permission", typeof(Dynamicweb.Content.Items.Editors.HiddenFieldEditor))]
public string Permission { get; set; }
[Field("Allow Comments", typeof(Dynamicweb.Content.Items.Editors.CheckboxEditor))]
[DefaultValue(false)]
public bool AllowComments { get; set; }
[Field("Tags", typeof(Dynamicweb.Content.Items.Editors.CheckboxListEditor<>))]
[OptionItem("Tag", "TagName", "Id", IncludeChilds = true, IncludeParagraphs = true, ItemSystemName = "Tag", NameField = "TagName", SourceId = 82, SourceType = Dynamicweb.Content.Items.Metadata.FieldOptionItemSourceType.CurrentArea, ValueField = "Id")]
public string Tags { get; set; }
}
}
There are a couple of things going on here:
Decorating your item/class with relevant attributes
[Item("Base", "Base"), Category("Custom")]
[AreaRule,
StructureRule(StructureContextType.Paragraphs),
ParentRule(ParentRestrictionRule.ParentType.RootOfWebsite, ParentRestrictionRule.ParentType.RegularPage),
TitlePattern("{{Title}}"),
TitleField("Title")]
[CustomizedURLs]
The code repeated here adds the necessary attributes to your item. It will create a name, and put it into a category called “Custom”. It will enable the item for paragraphs only, and it will allow the item to be created in the root of the website and underneath a regular page. It will also instruct the item to use the field called “Title” as the name of the paragraph, and finally it will create customized URLs.
Instruct a DropDownListEditor to use data from another item
[Field("Category", typeof(Dynamicweb.Content.Items.Editors.DropDownListEditor<>))]
[OptionItem("Category", "CategoryName", "Id", IncludeChilds = true, IncludeParagraphs = true, ItemSystemName = "Category", NameField = "CategoryName", SourceId = 32, SourceType = Dynamicweb.Content.Items.Metadata.FieldOptionItemSourceType.CurrentArea, ValueField = "Id")]
[Required]
public string Category { get; set; }
Another thing that is not documented is the ability to populate a DropDownListEditor with data from another item. I had already created an item called category, and the code above allows you to use this item in your dropdowns or checkboxes. You just add the “OptionItem”-attribute, and instruct it to use the “Category”-item. You can even tell the field to use the categories placed on a particular page which is why I’m using the SourceId = 32 attribute. I should probably put that one into a setting – arh well….
Date fields
As you can see I have chosen to comment out the date fields. I’m still having trouble with this one. The problem is that Dynamicweb doesn’t create a real date field in the database when you use code-first, and hence it will crash when you try to add new dates to the item. This is probably me doing some oddball-thing, but I still haven’t figured out how to do this properly. When I create this via the Item Manager everything works perfectly, but just not from my code. I hope to have this fixed as soon as possible.
Inherit from another item
It is possible to let one item inherit fields from another item. In my case, I needed to create an article-item that would inherit from the base-item. This is done via regular C#-code like the following:
namespace Bleau.Custom.ItemSubscriber.Items
{
using Dynamicweb.Content.Items.Activation;
using Dynamicweb.Content.Items.Annotations;
[Item("Article", "Article"), Category("Custom")]
[AreaRule,
StructureRule(StructureContextType.Paragraphs),
ParentRule(ParentRestrictionRule.ParentType.RootOfWebsite, ParentRestrictionRule.ParentType.RegularPage),
TitlePattern("{{Title}}"),
TitleField("Title")]
[CustomizedURLs]
public class Article : Base
{
[Name("Teaser")]
public string Teaser { get; set; }
[Field("Text", typeof(Dynamicweb.Content.Items.Editors.LongTextEditor))]
public string Text { get; set; }
[Field("Files", typeof(Dynamicweb.Content.Items.Editors.LongTextEditor))]
public string Files { get; set; }
}
}
As you can see, you just inherit from the Base-class and this will be represented in Dynamicweb CMS automatically.
So this is it! I will update this blogpost when I get new information about the date fields. Hopefully, it is just me messing around….