The following post shows functionality on mapping a Kentico CMS TreeNode object to a strong type .NET model class. These functions use reflection to map a property in a class to a Kentico document type field.
The examples below assumes your Document Types in Kentico have a corresponding .NET model class.
Below is the base class BaseModel that all model classes inherit from:
using CMS.PortalControls; using CMS.DocumentEngine; using CMS.CMSHelper; using CMS.SettingsProvider; public abstract class BaseModel { // define document id public int id { get { return Document == null ? 0 : Document.DocumentID; } } // define node id public int NodeId { get { return Document != null ? Document.NodeID : 0; } } // define name public string DocumentName { get { return Document != null ? Document.DocumentName : ""; } } // define url public string URL { get { return Document == null ? "" : Document.RelativeURL.Replace("~",""); } } // define url with extension public string URLWithExtension { get { return URL + (Document == null ? "" : Document.DocumentExtensions); } } // external url public string ExternalURL { get { return Document == null ? "" : Document.AbsoluteURL; } } // path for searching public string Path { get { return Document == null ? "" : URL + (!URL.EndsWith("/") ? "/" : "") + "%"; } } // define document public TreeNode Document { get; set; } // define function that maps extra properties public abstract void MapExtras(); }
The following are helper types to define an Image and a Generic Document:
public class Image { // fields public string Guid { get; set; } // function that checks if an image public bool HasImage { get { return !String.IsNullOrEmpty(Guid); } } // define path for the image public string Path { get { return String.Format("/getfile/{0}/img/", Guid); } } // function that returns the html tag for this image public string ToHtml(string alt) { // check if no guid if (String.IsNullOrEmpty(Guid)) return ""; // return the html tag for this image return String.Format("", Path, alt); } }
public class GenericDocument : BaseModel { public override void MapExtras() { } }
Below is a generic mapper function to map a given TreeNode and return the requested type:
public static T MapTo(TreeNode document) where T : BaseModel, new() { // init item T item = new T(); // check if a document passed if (document != null) { // set the document item.Document = document; // go through each of this model's properties foreach (var p in item.GetType().GetProperties()) { // check if a writeable property if (p.CanWrite) { // check primitive types if (p.PropertyType == typeof(string)) { p.SetValue(item, document.GetStringValue(p.Name, ""), null); } else if (p.PropertyType == typeof(int)) { p.SetValue(item, document.GetIntegerValue(p.Name, 0), null); } else if (p.PropertyType == typeof(bool)) { p.SetValue(item, document.GetBooleanValue(p.Name, false), null); } else if (p.PropertyType == typeof(double)) { p.SetValue(item, document.GetDoubleValue(p.Name, 0), null); } else if (p.PropertyType == typeof(Guid)) { p.SetValue(item, document.GetGuidValue(p.Name, new Guid()), null); } else if (p.PropertyType == typeof(DateTime)) { p.SetValue(item, document.GetDateTimeValue(p.Name, DateTime.Parse("1/1/1900").Date), null); } // check complex types else if (p.PropertyType == typeof(Image)) { p.SetValue(item, new Image { Guid = document.GetStringValue(p.Name, "") }, null); } else if (p.PropertyType == typeof(GenericDocument)) { p.SetValue(item, MapTo(GetDocumentFromGUID(document.GetStringValue(p.Name, ""))), null); } } } // map extras item.MapExtras(); } // return the item return item; }
Below is a generic mapper function to map a given TreeNodeDataSet and return a list of the requested type:
public static List MapToList(TreeNodeDataSet documentList) where T : BaseModel, new() { // define return list List list = new List(); // check if a document list if (documentList != null) { // go through each foreach (var n in documentList) { list.Add(MapTo(n)); } } // return return list; }
Below are helper functions needed for mapping:
// function that gets a tree node from guid public static TreeNode GetDocumentFromGUID(string guidStr) { // check if no guid Guid guid; if (Guid.TryParse(guidStr, out guid)) { // get a tree provider var th = new TreeProvider(); // find the node var n = th.SelectSingleNode(guid, CultureCode, CMSContext.CurrentSiteName); // check if a node if (n != null) { return DocumentHelper.GetDocument(n, th); } } // if here, return nothing return null; } // function that gets a tree node from id public static TreeNode GetDocumentFromID(int id) { // check if no id if (id > 0) { // get a tree provider var th = new TreeProvider(); return DocumentHelper.GetDocument(id, th); } // if here, return nothing return null; } // function that trys to find the current culture, falls back to default public static string CultureCode { get { // return nothing if blank return CMSContext.CurrentDocumentCulture == null ? "en-US" : CMSContext.CurrentDocumentCulture.CultureCode; } }
Below is an example on using this functionality:
// blog post model public class BlogPost : BaseModel { // fields public int BlogPostID { get; set; } public string Title { get; set; } public DateTime PostDate { get; set; } public string PostURL { get; set; } public Image Photo { get; set; } public string Author { get; set; } public string AuthorURL { get; set; } public string ReadMoreText { get; set; } public override void MapExtras() { } } // example public class Example { public static void GetSinglePost() { // get a single post from the current document BlogPost post = Mapper.MapTo(CurrentDocument); } public static void GetPostList() { // get a list of blog posts in the path var th = new TreeProvider(); // find the nodes var nodes = th.SelectNodes( CMSContext.CurrentSiteName, "/%", Globals.CultureCode, false, "EXAMPLE.BlogPost", "", "NodeOrder", -1, true, -1); // get the list List posts = Mapper.MapToList(nodes).OrderBy(x => x.Document.NodeOrder).ToList(); } }