The past couple of days I’ve been working on migrating my blog from the Orchard CMS to MiniBlog. The main reason for me to migrate to a different system is because I don’t work a lot with Orchard anymore. There were also some crashes from time to time which I couldn’t explain.

I’m currently hosting my websites on Azure Websites, because of that I didn’t feel much for using a database system. SQL Azure is very nice of course, but it can also be quite expensive, especially if you don’t really need the features. The alternative is SQL Compact, but I’m not very keen on using this as well.

While searching for a database-less blogging system, I came across several solutions like Ghost, Jekyll and MiniBlog. All of these systems are slightly different and work with different techniques. The main reason I’m using MiniBlog as my new blogging engine is because it’s based on .NET. I could list all the cool features which are included, but as it’s already stated on the GitHub page, I won’t repeat it over here.

MiniBlog is a system which saves it’s posts in XML files. Therefore, I had to migrate all of my posts from the Orchard database to the files which MiniBlog understands. There’s already a project on GitHub called MiniBlogFormatter. This tool is able to export posts from DasBlog, BlogEngine.NET and WordPress to the MiniBlog format. I’ve used the code from this project as a basis for exporting my own Orchard posts.

It would have been cool if I was able to extend the MiniBlogFormatter project with my Orchard exporting code. There was however one caveat for this, I don’t know how to access the Orchard API from a remote application. I do know how to create modules, therefore I’ve created a module which was able to export the posts in the necessary format. If you want to know how to create an Orchard module yourself, there’s a post on this blog where I elaborate more on this.

The module itself isn’t fool-proof and user friendly (yet). It’s available on GitHub, so you can use it if you want or use it as inspiration for your own solution.

You can see I’ve created a new route so my own controller will be triggered.

new RouteDescriptor {
    Priority = 5,
    Route = new Route(
        "Migrate",
        new RouteValueDictionary {
                                    {"area", "JanVNL.Migrate"},
                                    {"controller", "Migrate"},
                                    {"action", "index"}
                                },
        null,
        new RouteValueDictionary {
                                    {"area", "JanVNL.Migrate"}
                                },
        new MvcRouteHandler())
}

The MigrateController will eventually hit the Initialize-method in the GetBlogPost class, which looks like this:

internal ICollection Initialize(bool redirect)
{
	var blog = Retriever.GetBlog(_blogService);
	var blogPosts = _blogPostService.Get(blog, VersionOptions.Published);
	_allBlogPosts = new List();
	string redirects = string.Empty;
	foreach (var blogPostPart in blogPosts)
	{
		if (redirect) 
		{
			string currentSlug = GetUrl(blogPostPart);
			string redirectRule = "<location path=\"{0}\"><system.webServer><httpRedirect enabled=\"true\" destination=\"http://jan-v.nl/post/{0}\" httpResponseStatus=\"Permanent\" /></system.webServer></location>";
			redirects = redirects + string.Format(redirectRule, currentSlug);
		}
		else {

			var blogPost = new BlogPost();
			blogPost.Title = blogPostPart.Title;
			blogPost.Content = blogPostPart.Text;
			blogPost.PubDate = blogPostPart.PublishedUtc.Value;
			blogPost.LastModified = blogPostPart.PublishedUtc.Value;
			//blogPost.Categories = blogPostPart.;
			blogPost.Slug = GetUrl(blogPostPart);
			blogPost.Author = blogPostPart.Creator.UserName;
			blogPost.IsPublished = true;

			_allBlogPosts.Add(blogPost);
			Storage.Save(blogPost, string.Format("C:\\BlogPosts\\{0}.xml", blogPost.Slug));
		}
				
	}
	return _allBlogPosts;
}

In this piece of code I’m iterating through all blog posts, converting them one by one to a BlogPost object and storing them using the Storage class. The BlogPost and Storage class are copied from the MiniBlogFormatter repository.

You probably also noticed the if-statement with the redirect variable. I’m using this variable to switch between saving the blog posts and generating a web.config block for adding the redirect rules. To retrieve the redirect rules, you have to set a breakpoint in the code and copy the contents of the redirects variable to the web.config. Not very user friendly, indeed.

This code worked for Orchard 1.7.2. I’m fairly sure it will also work on Orchard 1.5.x. and above. You can try it on other versions of course, most of the time you’ll get decent warnings or errors if something doesn’t work properly.

Note:

Going through my blogpost draftfolder I noticed this post which I wrote about a year ago. Seeing a lot of time has gone into it I decided to post it anyway. It’s based on Orchard version 1.2, so things might have changed, but the basics are probably the same. Now for the real post.

I’ve got a new job where I was needed to create a new CMS website and add some client specific features on it. As Orchard is my preferred choice at the moment, it didn’t take me long to choose which CMS I was going to use.

To create some new, custom, features to the website I had to create new Modules and wanted to let them act as a Widget. A Widget in Orchard is much like a SharePoint webpart or an old-fashioned ASP.NET usercontrol.

Lucky for me the Orchard team has documented their work quite good, so I could use a lot of code from the ‘Writing a Content Part’ and ‘Writing a Widget’ tutorials.

One of the things I was asked to create is a widget which implements the SlideShowPro viewer. This widget is what I’ll use in this blogpost as an example.

First thing you need to do, if you want to create a Widget, is to create a new Content Part. A Content Part can be implemented as a new module in your Orchard website. You can use the code generation module for this, but if you prefer to do this manual, that’s also possible. If you choose to do this manually you need to create a lot of folders and files yourself as you need to start off with a new ASP.NET MVC 3 Web Application.

image

Easiest way to create a module is by starting up the orchard command prompt (hides in the bin directory of the Orchard project) and run the following command:

codegen module NewModule /IncludeInSolution:true

The parameter IncludeInSolution makes sure the new project is added to the Orchard solution, however, it doesn’t work on my machine, so I added it manually to the Modules folder in the solution.

Inside the newly added module you’ll see some files added by default. One of them is the Module.txt file. This file contains some information about the module, like the name, description and author. I first made a mistake by typing some of the properties in lowercase, this resulted in a non-deployable module. Of course, that could also be because of some non-functional code. My final Module text file looks like this:

Name: Vinit.SlideShowPro
AntiForgery: enabled
Author: Vinit
Website: http://vinit.nl
Version: 1.0
OrchardVersion: 1.0
Description: Adds a SlideShow Pro module to the site so slides can be shown.
Features:
    Vinit.SlideShowPro:
        Description: Adds a SlideShow Pro module to the site so slides can be shown.
		Category: Vinit

After setting this up I had to figure out what the model should look like. All content will get uploaded to the site, so I need to specify an URL. This will result in a rather simple and small model with only 1 property, but it’ll do the work.
Just add a new class in the Models folder with a proper name and specify the properties you need. If you read the tutorial about writing a content part already, you know you need to add some stuff in the model.

For each model you want to use you need to have a class which inherits from the ContentPart<T> class and one which inherits from the ContentPartRecord class. The class which inherits from the ContentPartRecord is somewhat a representation of the table where the information will get stored, sort of a model. The class which inherits the ContentPart<T> class will be used in the views and throughout the code, something like a viewmodel.
My model class resulted in looking like this:

public class SlideShowProRecord : ContentPartRecord
{
	public virtual string SlideShowUrl { get; set; }
}
public class SlideShowProPart : ContentPart
{
	public string SlideUrl
	{
		get { return Record.SlideShowUrl; }
		set { Record.SlideShowUrl = value; }
	}
}

As you can see I’ll only store 1 string, SlideShowUrl, in the database. This property will have to correspond to the column in the database. In the SlideShowProPart class I’ve defined the SlideUrl to be Requiredso I know it will be available when requested. The SlideUrl retrieves and sets the property of the record which we have specified in the <T>.

Now we need to add some stuff which makes Orchard use our code and modify the database. First off, a Migration.cs file. You can do this by adding it via de Orchard prompt by typing:

codegen datamigration NewModule

Or you can just add a new class and call it Migration. I prefer this as you don’t need the extra context switch and it’s faster.

The Migration class makes sure the Orchard database is updated after an install or update of a new module. In here you can specify what needs to be created, altered or deleted. First off we need to tell Orchard it has to create a new table with a column named SlideShowUrl and tell it we can attach the content part to any content type.
This is the necessary code for those steps:

public int Create()
{
	SchemaBuilder.CreateTable("SlideShowProRecord", table => table
																.ContentPartRecord()
																.Column("SlideShowUrl", DbType.String));

	ContentDefinitionManager.AlterPartDefinition(typeof(SlideShowProPart).Name, cfg => cfg.Attachable());

	return 1;
}

As you can see, an int value needs to be returned. This return value acts as a ‘version’ of your module. If you add a new method which returns a higher number, Orchard will automatically see there’s an update for the module and tell the administrator in the dashboard. Once the module is updated, it stores the new ‘version’ number and knows the module is up-to-date. Can’t really tell if this is a best-practice, but hey, it works!

After having created the Migration class we also need to add a Handler to the project. The handler handles events of the content part or is able to manipulate the data model, before rendering the content part. Just as the example in the Orchard tutorial, I don’t need advanced stuff happening here, so I didn’t change the code here.

public SlideShowProHandler(IRepository repository)
{
    Filters.Add(StorageFilter.For(repository));
}

Next up are the views of the content part. Specifying the views is done in something called a Driver. In this driver you can specify which view will be shown for display, edit, summary, etc. All very nice, once you know how this works.
A fairly default implementation is this one:

public class Drivers : ContentPartDriver
{
    protected override DriverResult Display(SlideShowProPart part, string displayType, dynamic shapeHelper)
    {
        return ContentShape("Parts_SlideShowPro", () => shapeHelper.Parts_SlideShowPro(SlideUrl: part.SlideUrl));
    }

    //GET
    protected override DriverResult Editor(SlideShowProPart part, dynamic shapeHelper)
    {
        return ContentShape("Parts_SlideShowPro_Edit",
                            () =>
                            shapeHelper.EditorTemplate(TemplateName: "Parts/SlideShowPro",
                                                        Model: part,
                                                        Prefix: Prefix));
    }

    //POST
    protected override DriverResult Editor(SlideShowProPart part, Orchard.ContentManagement.IUpdateModel updater, dynamic shapeHelper)
    {
        updater.TryUpdateModel(part, Prefix, null, null);
        return Editor(part, shapeHelper);
    }
}

The Display and Editor methods are overridden with some new functionality. The shapeHelper parameter is a dynamic type, which means you don’t get IntelliSense from it. I don’t know how the properties are defined on the project, but they work. Maybe I’ll check it out when I’ve got some extra spare time (read: never!).
In here you define where the views are located of the content part, “Parts/SlideShowPro” and which model will be used.

Fixing the views is rather easy, just add a new view with the name SlideShowPro.cshtml in Views/Parts and in Views/EditorTemplates/Parts and you are done. If you’ve created a MVC site already, you are probably familiar on how to create the views. The Orchard tutorial has a nice example and this is a small snippet of my EditorPart:

@model Vinit.SlideShowPro.Models.SlideShowProPart
<fieldset>
    <legend>SlideShowPro Fields</legend>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.SlideUrl)
        @*Html.ValidationMessageFor(model => model.SlideUrl)*@
    </div>
</fieldset>

And the DisplayPart:

@if ( Model.SlideUrl != null && !string.IsNullOrWhiteSpace(Model.SlideUrl) && Model.SlideUrl.Length > 3) { 
<script type="text/javascript" src="@String.Format("{0}js/slideshowpro.js", Model.SlideUrl)"></script> 

<div id="slideshow"></div>

The last step for successfully creating a content part is adding the placement.info file at the root of the project. This file contains some information on where to locate the views in a larger view.

<Placement>
    <Place Parts_SlideShowPro="Content:2"/>
    <Place Parts_SlideShowPro_Edit="Content:7"/>
</Placement>

The above example specifies I want the views in the Content block at the 10th position, or in the editor modus at the 7th position.

Now, build, deploy, activate and check out of the content part is working.

Once you’ve enabled the new module, you can add the content part to a random content type to check if everything is working.

image

Navigate to the Content Types list and edit one of them, maybe Page.

image

Check the Slide Show Pro box in the list and click Save.
When creating a new page you should see a new block on the screen, the same block as you have specified in the editor view of your module. When viewing the new page you should see the display view on the page.

So far for the hard part. Once you’ve got a working content part, creating a Widget from this is a piece of cake.

Just add the following code to the Migration class, deploy and you’re happy to go.

public int UpdateFrom1()
{
	// Create a new widget content type with our map
	ContentDefinitionManager.AlterTypeDefinition("SlideShowProWidget", cfg => cfg
		.WithPart("SlideShowProPart")
		.WithPart("WidgetPart")
		.WithPart("CommonPart")
		.WithSetting("Stereotype", "Widget"));

	return 2;
}

In this piece of code you tell Orchard you want to create a SlideShowProWidget which consists of the SlideShowProPart, WidgetPart and CommonPart.
Deploy and update the module! If everything is installed correct you should also see a notification in the Dashboard.

After that you can add the widget to a content block:

image

So far for my small tutorial on how to add a new widget to Orchard. Lucky for me most of the stuff was already explained in the Orchard tutorials. I added some comments here which I had to find out myself or didn’t quite get from the original.
And as always, it’s always good to try things by yourself. That way you’ll get more experience on the matter.

As I’m busy designing and developing my new weblog I noticed a minor Orchard version was released. Because I’m in the starting phase of the development cycle, I decided to upgrade to the latest version.

This is rather easy, as you can just download the latest sources from CodePlex, extract and copy them over the old codebase (well, I deleted the original 1.3 files and copied the 1.4 files to a ‘clean’ folder).

Upgrading the Orchard sources broke several of my new modules, so I had to fix the broken code. After resolving those issues I pressed [Ctrl]+[F5] to see if everything was still working. It wasn’t…

Starting the site, I received a 404 error, because the pages couldn’t be found. Logs weren’t very helpful, aside from telling me some queries couldn’t run correctly. Deleting the /Sites/-folder in the App_Data did help me a bit, because now it showed me the normal ‘Orchard set up new site’ form.
Because I was starting to get a bit frustrated I decided to create a new website and have the connectionstring map to my old Orchard weblog database. This didn’t work either. Now there was an error the Recipes modules couldn’t be found or instantiated.

After having spent several hours searching for a solution by myself I finally stumbled upon a post of David Hayden telling something about an UpgradeTo14 module. Apparently you need to activate a module to do a successful upgrade.

In my search for the problem I had already learned there are some issues with the blog titles not showing anymore if you didn’t had the Title module enabled while migrating. The recipes error was also something still fresh in my mind, so I decided to follow this upgrade path:

  • Navigate to the admin area of your site http://localhost:30320/YourSite/Admin/
  • Enable the Title module
  • Enable the Recipes module
  • Enable the UpgradeTo14 module
  • Click on the Migrate to 1.4 link
  • In the Migrate Routes tab, check all options and click Migrate
  • In the Migrate Fields tab, check all options and click Migrate

As I didn’t had any other 3rd party modules installed, this all worked out like a charm. If you’ve got modules installed which aren’t compatible with 1.4, you’re probably have a problem migrating and are better off staying at 1.3 for now.

Now that I’ve got the new version installed I can’t wait to play with the Projector module, which looks really awesome. For now I’ll stick with getting my new weblog online as soon as possible, so playing around will just have to wait.

If you create a theme for Orchard, it’s only a matter of time before you stumble across a yellow screen of death. I know this, because it happened multiple times to me. One of the reasons for these errors are the dynamic objects, which are used a lot in Orchard.

You won’t get compile-time errors with these objects, so they need to be handled with care.

Now, when a theme causes a yellow screen you are kind of screwed as you can’t do anything anymore on the website, like logging in to the admin area.

Lucky for us developers, the database isn’t obfuscated and we can make rapid changes to it. You can use this script to update your current Orchard theme and set it back to the default Theme Machine theme.

UPDATE [OrchardDatabaseName].[dbo].[default_Orchard_Themes_ThemeSiteSettingsPartRecord]
   SET [Id] = 1
      ,[CurrentThemeName] = 'TheThemeMachine'
GO

Run the above script on your Orchard database and you will be able to start developing again.

If the above script doesn’t work, check the [default_Orchard_Themes_ThemeSiteSettingsPartRecord] table entries. You possibly need to change the Id parameter of the script to the one which is the same as in the database

A few months ago I decided to migrate my weblog from SharePoint to Orchard, because it’s more lightweight and better suited as a simple blog. I also started to develop some custom modules and themes for this CMS and have to say I like it!

One thing though, which has bothered me from the beginning, was the empty Archive block at the right side of my blog. I had done so much work to import the SharePoint blog entries to Orchard (a manual copy-paste action), so I knew the posts were there, I could even browse to them.
Why was it my posts weren’t visible in the archive block?

Today, I found the answer to my problem. It’s a small bug in Orchard when you set the blog to be the homepage of the site. Somehow the records in the [Orchard_Blogs_BlogArchivesPartRecord] table aren’t updated properly. The BlogSlug column should be changed to NULL and not contain the name of your weblog.

Once I knew this I changed the entries so they would contain the value NULL:

image

Note: You probably have got 1 record, but apparently I’ve done some adding and deleting of blogs, so I’ve got multiple. I can probably delete 3 of them, but just to be sure I didn’t.

Now, after checking the frontpage again I indeed saw a filled out Archive block. It wasn’t showing the correct/expected data, but at least it had some data in it.

In order to retrieve the Archive data, Orchard has a table called [Orchard_Blogs_BlogPartArchiveRecord], which is filled with a summary of posts made in a specific year and month.

image

A nice feature performance wise, but somehow it didn’t had the correct information of my blog. That’s probably because I imported the SharePoint blog entries manual to Orchard and only changed the Created date in the [Common_CommonPartRecord] table of the database.

The Archive block probably uses some other columns and maybe even the [Common_CommonPartVersionRecord] table, so I had to change the dates of the other columns in these tables also.

Lucky for me, I’ve done some pretty big SQL queries in the past, so this didn’t pose as a big challenge. The correct dates were stored in the [Common_CommonPartRecord].[CreatedUtc] column, so updating the [Common_CommonPartRecord] table was fairly easy, I used this script:

update Common_CommonPartRecord
set
	PublishedUtc = CreatedUtc,
	ModifiedUtc = CreatedUtc

To update the [Common_CommonPartVersionRecord] I had to use a cursor in order to update the columns the way I wanted. Still a fairly easy script, if you know cursors exist in SQL Server.

DECLARE @Id INT
DECLARE @CreatedUtc DATETIME

DECLARE blogCursor CURSOR FOR 
	select Id, CreatedUtc
	from Common_CommonPartRecord
	where Id < 236
	
open blogCursor;

fetch next from blogCursor
INTO @Id, @CreatedUtc

WHILE @@FETCH_STATUS = 0
BEGIN
	PRINT @Id
	PRINT @CreatedUtc
	
	UPDATE Common_CommonPartVersionRecord
	SET
		CreatedUtc = @CreatedUtc,
		ModifiedUtc = @CreatedUtc,
		PublishedUtc = @CreatedUtc
	WHERE Common_CommonPartVersionRecord.ContentItemRecord_id = @Id
	
	FETCH NEXT FROM blogCursor INTO @Id, @CreatedUtc
END
		
CLOSE blogCursor

DEALLOCATE blogCursor

The site still displayed the wrong number of posts per year or month. This didn’t came as a surprise as the numbers within the [Orchard_Blogs_BlogPartArchiveRecord] table were still the same. I thought a search update might help. After rebuilding the search index the Archive posts were still all wrong.
Checking out the Orchard source code on this subject told me something I didn’t guessed:

public BlogPartArchiveHandler(IRepository blogArchiveRepository, IBlogPostService blogPostService) {
            OnPublished((context, bp) => RecalculateBlogArchive(blogArchiveRepository, blogPostService, bp));
            OnUnpublished((context, bp) => RecalculateBlogArchive(blogArchiveRepository, blogPostService, bp));
            OnRemoved((context, bp) => RecalculateBlogArchive(blogArchiveRepository, blogPostService, bp));
        }

Because of the nicely worded methods I was able to figure out I just needed to publish, unpublish or delete a blogpost. After re-publishing one of my posts the Archive block was updated with the correct numbers.

And now, the Archives are shown correct. Still the current year doesn’t contain any elements, I’ll need to check out what’s the matter with that. The numbers in the tables are all correct, so it’s probably some other bug.