Continuing my series on Migrating from WordPress to MVC4 (Part 1 and Part 2). Today I worked on getting the right hand side bar and importing Tags from the export mentioned in Part 1. Where did I begin? Based on the original import I made last Friday night, I created a Stored Procedure to create the right hand side "Archives List", for those curious here is the SQL: [sql] SELECT DATEPART(YEAR, dbo.Posts.Created) AS 'PostYear', DATENAME(MONTH, dbo.Posts.Created) AS 'PostMonth', (SELECT COUNT(*) FROM dbo.Posts postsCount WHERE DATENAME(MONTH, postsCount.Created) = DATENAME(MONTH, dbo.Posts.Created) AND DATEPART(YEAR, postsCount.Created) = DATEPART(YEAR, dbo.Posts.Created) AND postsCount.Active = 1) AS 'NumPosts' FROM dbo.Posts WHERE dbo.Posts.Active = 1 GROUP BY DATENAME(MONTH, dbo.Posts.Created), DATEPART(YEAR, dbo.Posts.Created) ORDER BY DATEPART(YEAR, dbo.Posts.Created) DESC, DATENAME(MONTH, dbo.Posts.Created) [/sql] And then in the UI: [csharp] <div class="Widget"> <div class="Title"> <h3>Archives</h3> </div> <div class="Content"> @foreach (var item in @Model.ArchiveItems) { var baseURL = "" + @item.Year + "/" + @item.Month + "/"; <div class="ArchiveItem"> <a href="@baseURL">@item.Month @item.Year (@item.PostCount)</a> </div> } </div> </div> [/csharp] After all is said and done (also included are the SQL stored Links): [caption id="attachment_2004" align="aligncenter" width="100"]Archived List and Links List Archived List and Links List[/caption] At this point I needed to do a re-import of the data as I had only imported the Posts. In addition I added support to import the Categories for Posts while I was at it. If you're referencing the code in this series I added the following block immediately after the Post row is added. This block parses and imports the Tags and Categories: [csharp] foreach (var tag in item.GetcategoryRows()) { if (tag.domain == "post_tag") { var existingTag = eFactory.Tags.FirstOrDefault(a => a.Description == tag.category_Text); if (existingTag == null) { existingTag = eFactory.Tags.Create(); existingTag.Active = true; existingTag.Created = DateTime.Now; existingTag.Description = tag.category_Text; existingTag.Modified = DateTime.Now; eFactory.Tags.Add(existingTag); eFactory.SaveChanges(); } var relationalRow = eFactory.Posts2Tags.Create(); relationalRow.Active = true; relationalRow.Created = post.Created; relationalRow.Modified = post.Created; relationalRow.PostID = post.ID; relationalRow.TagID = existingTag.ID; eFactory.Posts2Tags.Add(relationalRow); eFactory.SaveChanges(); } else if (tag.domain == "category") { var existingCategory = eFactory.PostCategories.FirstOrDefault(a => a.Description == tag.category_Text); if (existingCategory == null) { existingCategory = eFactory.PostCategories.Create(); existingCategory.Active = true; existingCategory.Created = DateTime.Now; existingCategory.Description = tag.category_Text; existingCategory.Modified = DateTime.Now; eFactory.PostCategories.Add(existingCategory); eFactory.SaveChanges(); } var relationalRow = eFactory.Posts2Categories.Create(); relationalRow.Active = true; relationalRow.Created = post.Created; relationalRow.Modified = post.Created; relationalRow.PostID = post.ID; relationalRow.PostCategoryID = existingCategory.ID; eFactory.Posts2Categories.Add(relationalRow); eFactory.SaveChanges(); } } [/csharp] Now that the Tags and Categories are imported into the SQL Server, I wanted to recreate the Tag Cloud feature that WordPress offers and Telerik offers in their ASP.NET WebForms Suite. At a base level all a Tag Cloud really does is based on the highest count of items, create a larger link of the Tag and get decreasingly smaller as the occurrences decrease. So for those only here to check out how I accomplished it, let's dive in. First I created a Stored Procedure to get the Top 50 used Tags: [sql] SELECT TOP 50 (SELECT COUNT(*) FROM dbo.Posts2Tags WHERE dbo.Posts2Tags.TagID = dbo.Tags.ID) AS 'NumTags', dbo.Tags.Description FROM dbo.Tags WHERE dbo.Tags.Active = 1 ORDER BY (SELECT COUNT(*) FROM dbo.Posts2Tags WHERE dbo.Posts2Tags.TagID = dbo.Tags.ID) DESC, dbo.Tags.Description ASC [/sql] And then in my Controller in the MVC 4 App: [csharp] private List<lib.Objects.TagCloudItem> processTagCloud(List<lib.Objects.TagCloudItem> tagItems) { var startingLevel = 10; for (var x = 0; x < tagItems.Count; x++) { tagItems[x].CSSClassName = "TagItem" + startingLevel; if (startingLevel > 1) { startingLevel--; } } return tagItems.OrderBy(a => a.Name).ToList(); } [/csharp] Basically I created 10 "Levels" of different Tag Cloud sizes and based on the top 9 I use the larger sizes. And the associated CSS: [css] /* Tag Cloud Items */ .sideBar .Widget .Content .TagItem1 { font-size: 8pt; } .sideBar .Widget .Content .TagItem2 { font-size: 9pt; } .sideBar .Widget .Content .TagItem3 { font-size: 10pt; } .sideBar .Widget .Content .TagItem4 { font-size: 11pt; } .sideBar .Widget .Content .TagItem5 { font-size: 12pt; } .sideBar .Widget .Content .TagItem6 { font-size: 16pt; } .sideBar .Widget .Content .TagItem7 { font-size: 20pt; } .sideBar .Widget .Content .TagItem8 { font-size: 24pt; } .sideBar .Widget .Content .TagItem9 { font-size: 28pt; } .sideBar .Widget .Content .TagItem10 { font-size: 32pt; } [/css] And the Razor View: [csharp] <div class="Widget"> <div class="Title"> <h3>Tags</h3> </div> <div class="Content"> @foreach (bbxp.lib.Objects.TagCloudItem tag in @Model.TagCloudItems) { var url = "" + @tag.Name + "/"; <a href="@url" class="@tag.CSSClassName">@tag.Name</a> } </div> </div> [/csharp] After implementing the SQL, CSS and HTML I got it working just as I wanted: [caption id="attachment_2008" align="aligncenter" width="116"]bbxp TagCloud bbxp TagCloud[/caption] Next up on the list is to import the comments, display them and create a comments form.