Main contents

How to Save XAML as an Image

2 September 2008

Here’s a quick note to self that you may enjoy. I suck at art. Didn’t use to always, but it requires too much brain power. But I’m not bad at getting WPF to draw what I want. I had a logo in mind for this site and used WPF to generate it after unsuccessfully getting Paint.NET to do the same.

I recently needed to use this code again, but forgot how I solved it. So, rather than hunt it down on Google again, I came home and loaded up ye olde Windows Live Writer to write this post.

To save the XAML you want as an image, put the elements you want to save into a canvas element called canvas. Then run the following code.

private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
   Rect rect = new Rect(canvas.RenderSize);
   RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
     (int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
   rtb.Render(canvas);
   //endcode as PNG
   BitmapEncoder pngEncoder = new PngBitmapEncoder();
   pngEncoder.Frames.Add(BitmapFrame.Create(rtb));

   //save to memory stream
   System.IO.MemoryStream ms = new System.IO.MemoryStream();

   pngEncoder.Save(ms);
   ms.Close();
   System.IO.File.WriteAllBytes("logo.png", ms.ToArray());
   Console.WriteLine("Done");
}

I hooked up a key binding to a command to execute this code, but you could use a button click too. It’ll save the elements in canvas to a file in the same folder as the executable, called logo.png, but you can change that if you want. You can also you a different encoder if you like. They’re in System.Windows.Media.Imaging.

Enjoy!

Posted in .NET, Note to self... | No Comments »

The .NET framework is huge, but not so huge that it does everything for everyone; there are things that they in Redmond miss or don’t do for whatever reason but is still generally applicable to many developers. So, dear reader, I present to you a series of posts on stuff I find missing in .NET, typically where even the Google fails to find the answer. It could be a useful class, a technique, a good practice or documentation that should be in the framework but isn’t or isn’t widely publicized. Click here for a complete list of Missing .NET entries.


I’m ambivalent towards enums. They are a succinct way of providing a list of choices that don’t change that much. But, I think they are overused, often in situations that don’t lend themselves well to enums. For example, the HttpStatusCode enum in System.Net. It should probably explicitly be a list of constant integers, because that’s the way the status code is thought of to HTTP programmers, well, at least one. Consider the two code snippets below. Which one is more readable?

void ProcessResponse(WebResponse r)
{
    if (r.StatusCode >= HttpStatusCode.BadRequest)
    {
        // handle response
    }
}

void ProcessResponse(WebResponse r)
{
    if (r.StatusCode >= 400)
    {
    // handle request
    }
}

Yeah, yeah: you’re not supposed to use magic numbers, but it’s not like HTTPbis is going to redo all the status codes. It’s a safe bet that the status code with the value 400 will always mean “Bad Request”.

Anyway, Enums are here to stay and we have to deal with them in various ways; displaying them to the user is one way they have to be dealt with. I’ll give a treatment of how to display an enum in WPF in this post. You’ll see that displaying them in all situations is non-trivial.

So, let’s say you want to display a list of the values for your custom enum in a ComboBox in WPF; how do you do it? Well,  you could mess around yourself and test your WPF databinding knowledge, but no one has any patience for that nowadays. Let’s Google it! The goal of most WPF code is to do it all in XAML. So a possible solution to the problem is the following XAML snippet (copied from this post from the WPF SDK blog):

<Window
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  SizeToContent="WidthAndHeight"
  Title="Show Enums in a ListBox using Binding">
  <Window.Resources>
    <ObjectDataProvider MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}"
                        x:Key="AlignmentValues">
      <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="HorizontalAlignment" />
      </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
  </Window.Resources>
  <Border Margin="10" BorderBrush="Aqua"
          BorderThickness="3" Padding="8">
    <StackPanel Width="300">
      <TextBlock>Choose the HorizontalAlignment
                 value of the Button:</TextBlock>
      <ListBox Name="myComboBox" SelectedIndex="0" Margin="8"
               ItemsSource="{Binding Source={StaticResource
                                             AlignmentValues}}"/>
      <Button Content="Click Me!"
              HorizontalAlignment="{Binding ElementName=myComboBox,
                                            Path=SelectedItem}"/>
    </StackPanel>
  </Border>
</Window>

The real magic happens in the bolded text above, the ObjectDataProvider. It calls the GetValues() method on the Enum type. The MethodParameters element contains the actual enum type to display. This is the common sample that you’ll see throughout the web. A couple problems no one seems to address with this solution, though.

The first is the what actually gets shown to the user. For simple one-word values, like the HorizontalAlignment enum used in the XAML sample above (Center, Justify, Left, Right), it’s not a problem — if you’re only coding for the English language. But what about the HttpStatusCode enum? It’ll show up with the Pascal casing BadRequest or RequestedRangeNotSatisfiable rather than “Bad Request” or “Requested Range Not Satisfiable”. That’s acceptable if your audience is a bunch of nerdy programmers (”I actually prefer no spaces, it makes 2.4321% more efficient so I can devote more time to WoW!” Nerd.), but if you’re doing this for real people, you’re going to want a nice grammatically- correct string to show up. You might want even more detail in the string: “Bad Request (400)”, say.

Second, this solution ignores localization. If you just show the name of the enum value, you get whatever language the programmer speaks. That’s fine if you only plan on shipping your product to your country, but what if you are big in Japan? You’re going to want to translate that bad boy to Japanese!

Japan's calling. Are you going to answer?

Japan’s calling. Are you going to answer?

Let’s solve that problem.

Let’s first assume that we own the enum type. We have a web product and a WPF product; we use our custom enum type in both products. We want to display the same thing for the enum values in both places. If that’s the case, we want the display strings to move around with the enum. How are we going to do that? Well, we have extra data that we want to move around with a type, perfect for … Attributes!

The simplest attribute class that will work takes a string that will be displayed in place of the enum value. But we don’t want the simplest class that will work. We want one that will also support localization. Still pretty simple and it looks like this:

[AttributeUsage(AttributeTargets.Field)]
public sealed class DisplayStringAttribute : Attribute
{
   private readonly string value;
   public string Value
   {
      get { return value; }
   }

   public string ResourceKey { get; set; }

   public DisplayStringAttribute(string v)
   {
      this.value = v;
   }

   public DisplayStringAttribute()
   {
   }
}

We can apply this to the values of our custom enum, like so:

public enum MyEnum
{
   [DisplayString("My Value")]
    Value,
   [DisplayString("This means On")]
    On,
   [DisplayString("Off means not On")]
    Off,
   [DisplayString("The great unknown")]
    Unknown,
   [DisplayString("I ain't got none")]
    None
}

Doesn’t look as pretty as an unadorned enum, but commercial quality code often looks less attractive than you’re typical code snippet on MSDN. If we want to internationalize our app, we can have different display strings for different languages by setting the ResourceKey property instead of the value constructor:

public enum MyEnum
{
   [DisplayString(ResourceKey="MyEnum_Value")] Value,
   [DisplayString(ResourceKey="MyEnum_On")] On,
   [DisplayString(ResourceKey="MyEnum_Off")] Off,
   [DisplayString(ResourceKey="MyEnum_Unknown")] Unknown,
   [DisplayString(ResourceKey="MyEnum_None")] None
}
 
Don’t forget to add the strings to your resx file for each language!
 
So we have our strings established, now we need a class that will read that data, and convert it to something that can be displayed. I’ll solve that problem for WPF specifically, but there is no reason you can’t do it for Winforms or the Web also, dear reader. It’s a good lesson in learning how to support UI frameworks and reflection
 
If you’re designing for WPF, a huge consideration is the ability to express your code in XAML. With my solution below, you’ll be able to declare these enum displayers in XAML; but as you’ll see, it makes the code a little less elegant.
 
Here are the requirements that my EnumDisplayer class must fulfill:
  • read the DisplayStringAttribute values applied to our enum class; or
  • load the resource string based on the ResourceKey in the DisplayStringAttribute; and
  • be expressible in XAML, both declaring one and as a databinding source.

Let’s take care of the third item first, since it will shape the public API more than the other two.

It is an enum’s nature to be static and constant, hence a class that aids in displaying it to the user is also likely to be static. We’ll also be using the EnumDisplayer to convert enum values and as a datasource. Before we can do anything though, we need to know the enum type we’ll be displaying. Ideally, this would mean passing the enum type in the constructor; because of the XAML requirement, however we need a property of type Type. We’ll add a constructor that takes a Type parameter as a convenience for those that like to write everything in code. So our initial public API looks thus:

public class EnumDisplayer : IValueConverter
{
  private Type type;
  private IDictionary displayValues;
  private IDictionary reverseValues;

  public EnumDisplayer()
  {
  }

  public EnumDisplayer(Type type)
  {
     this.Type = type;
  }

  public Type Type
  {
     get { return type; }
     set
     {
        if (!value.IsEnum)
           throw new ArgumentException("parameter is not an Enumermated type", "value");
        this.type = value;
     }
  }

  public ReadOnlyCollection<string> DisplayNames
  {
     get
     {
        this.displayValues =...
        return new List<string>((IEnumerable<string>)displayValues.Values).AsReadOnly();
     }
  }

  object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
     return displayValues[value];
  }

  object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
     return reverseValues[value];
  }
}

Pretty straightforward public API: two properties, one being the type to generate strings for, and the other, the strings that we generated. The IValueConverter interface is implemented explicitly. The reverseValues dictionary maps the reverse of displayValues: displayValues goes from enum type to string, reverseValues goes from string to enum. This means that each enum value must have a unique display string; hardly unreasonable, since they have to have a unique name within the enum anyway.

The above public API allows us to declare an EnumDisplayer in XAML like so:

<Application.Resources>
        <sm:EnumDisplayer Type="{x:Type FlickrNet:ContentType}" x:Key="contentTypes">
</Application.Resources>

And use it as a data source and value converter:

<ComboBox ItemsSource="{Binding Source={StaticResource contentTypes},Path=DisplayNames}"
          SelectedValue="{Binding Path=Batch.Photos/ContentType,
                          Converter={StaticResource contentTypes}}" />

Well, that’s just awesome!

Let’s go back a bit and expand on that ‘…’ in the code for EnumDisplayer. That’s where all the real work happens. Since I don’t know the type at compile time, I use reflection to generate my two IDictionary instances when the DisplayValues property is first accessed. I also inspect the enum type provided for DisplayString attributes. All that code is below. It’s nothing special: most of it I found on the internet if I didn’t already know how to do it.

public ReadOnlyCollection<string> DisplayNames
{
 get
 {
    Type displayValuesType = typeof(Dictionary<,>)
                                .GetGenericTypeDefinition().MakeGenericType(typeof(string),type);
    this.displayValues = (IDictionary) Activator.CreateInstance(displayValuesType);

    this.reverseValues =
       (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>)
                .GetGenericTypeDefinition()
                .MakeGenericType(type, typeof(string)));

    var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
    foreach (var field in fields)
    {
       DisplayStringAttribute[] a = (DisplayStringAttribute[])
                                   field.GetCustomAttributes(typeof(DisplayStringAttribute), false);

       string displayString = GetDisplayStringValue(a);
       object enumValue = field.GetValue(null);

       if (displayString == null)
       {
          displayString = GetBackupDisplayStringValue(enumValue);
       }
       if (displayString != null)
       {
          displayValues.Add(enumValue, displayString);
          reverseValues.Add(displayString, enumValue);
       }
    }
    return new List<string>((IEnumerable<string>)displayValues.Values).AsReadOnly();
 }
}

private string GetDisplayStringValue(DisplayStringAttribute[] a)
{
     if (a == null || a.Length == 0) return null;
     DisplayStringAttribute dsa = a[0];
     if (!string.IsNullOrEmpty(dsa.ResourceKey))
     {
        ResourceManager rm = new ResourceManager(type);
        return rm.GetString(dsa.ResourceKey);
     }
     return dsa.Value;
}

Reflection code is always so ugly. I warned you it wasn’t pretty! See what framework developers have to go through to make code usable? So what’s happening here?

First, I dynamically create the two dictionaries as generic types. That begs the question: “Jason, why didn’t you use generics, wouldn’t that have been way easier? You’re such a pedantic loser!”

Good question. I couldn’t use them because of that third requirement that I imposed upon myself: XAML. There’s no easy way to declare a generic type in XAML, so I couldn’t use them.

Moving along: Next I grab the custom attributes, look for my DisplayStringAttribute and get the value from it in the helper method GetDisplayStringValue(). Notice I prefer the ResourceKey property before the Value property.

Then I add them to the dictionary and the reverseDictionary.

Astute readers should be asking this question by now: what about that call to GetBackupDisplayStringValue?

Right you are, Dear Reader! You’re so smart.

Alright, let’s go way back to the top of the article and address one of my assumptions: I assumed that I owned the enum type. That’s a great assumption to make when you’re coming up with trivial code examples for a blog post, but what about the real world? I got a mortgage! And WoW bills! And a flight to Japan to pay for!

It’s not an assumption that holds up under scrutiny. In fact, the chances you’ll be using an enum you own is probably slimmer than not owning the type. We all know everyone will be using the awesome DisplayStringAttribute once this blog post is published, but what about enums that were created B. DSA. (Before DisplayStringAttribute). Don’t worry, I got you covered.

To do that, and make it accessible in XAML, we need two things: a collection of enum display overrides and a way to tell the XAML parser that children of the EnumDisplayer get added to that collection. Here’s the rest of the implementation.

[ContentProperty("OverriddenDisplayEntries")]
public class EnumDisplayer : IValueConverter
{
   private Type type;
   private IDictionary displayValues;
   private IDictionary reverseValues;
   private List<EnumDisplayEntry> overriddenDisplayEntries;

    ...

   private string GetBackupDisplayStringValue(object enumValue)
   {
      if (overriddenDisplayEntries != null && overriddenDisplayEntries.Count > 0)
      {
         EnumDisplayEntry foundEntry = overriddenDisplayEntries.Find(delegate(EnumDisplayEntry entry)
                                          {
                                             object e = Enum.Parse(type, entry.EnumValue);
                                             return enumValue.Equals(e);
                                          });
         if (foundEntry != null)
         {
            if (foundEntry.ExcludeFromDisplay) return null;
            return foundEntry.DisplayString;

         }
      }
      return Enum.GetName(type, enumValue);
   }

   public List<EnumDisplayEntry> OverriddenDisplayEntries
   {
      get
      {
         if (overriddenDisplayEntries == null)
            overriddenDisplayEntries = new List<EnumDisplayEntry>();
         return overriddenDisplayEntries;
      }
   }
}

public class EnumDisplayEntry
{
   public string EnumValue { get; set; }
   public string DisplayString {  get; set; }
   public bool ExcludeFromDisplay { get; set; }
}

We decorate our EnumDisplayer class with the ContentProperty attribute that tells the XAML parser that anything contained in an EnumDisplayer element gets added to that property. Then we also need the property which is a List<EnumDisplayEntry>. The EnumDisplayEntry is a way to map an enum value to a new display string. The GetBackupDisplayStringValue() method is pretty straightforward: query the list for the given enum value to return the string or not if you want to exclude from being displayed. I suppose I should prefer the overridden value to the one provided in the DisplayStringAttribute but I’m jonesing for Guitar Hero, so I’m going to wrap up.

The above code enables you to provide your own strings for enum values, which we can express in XAML:

<sm:EnumDisplayer Type="{x:Type FlickrNet:ContentType}" x:Key="contentTypes">
    <sm:EnumDisplayEntry EnumValue="Photo" DisplayString="Photo (Default)"/>
    <sm:EnumDisplayEntry EnumValue="Screenshot" DisplayString="Screenshot"/>
    <sm:EnumDisplayEntry EnumValue="Other" DisplayString="Other"/>
</sm:EnumDisplayer>

Admittedly, these aren’t the most imaginative strings for these enum values, but that’s an actual snippet of XAML from an actual app.

There are still some things to address: WinForms and ASP.NET should be supported. Also, what about Flags enums? How should those be handled? Enums are surprising in their difficultly to show in UI properly. With the enum displayer class we have a good starting point for making a non-trivial problem of displaying enum values somewhat easier in XAML.

Posted in .NET, Missing .NET | 1 Comment »

Suppose you’re using Visual Studio 2008 and you’ve just found out that Microsoft added unit test support for the Compact Framework on devices and emulators. Neat-o!

So you add one to your project thinking, this’ll be fantastic.

Then it doesn’t work.

You get the following cryptic error:

Unable to set TestContext property for the class {class}. Error:  System.ArgumentException: Object of type 'Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapterContext' cannot be converted to type 'Microsoft.VisualStudio.TestTools.UnitTesting.TestContext'

“So,” you think, “I obviously did something wrong, but it’s not apparent to me what I did. I will check the Google.”

But Google only shows you what to do for the full framework.1 The full framework instructions don’t make any sense for your awesome Compact Framework assembly. Uh oh, now what are you going to do?

Maybe it’s your project that’s screwed up. So you start a new one to see if it works. It doesn’t, but you get a different error: References root node unavailable. You might as well search the google for that one and then you get this forum post that repeats the solution over and over:

Restart the IDE.

You figure it can’t hurt, so you try it.

And it works.

You can now use unit tests for .NET CF projects, but you’re no longer smiling about it.


Notes

1 The answer for the full framework is to delete your reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework, then search for it again in the Add Reference dialog. Microsoft forgot to update all the project templates for VS08, so all of the esoteric projects point to the assemblies for VS 2005. Quality tool, my ass.

Posted in .NET | No Comments »

I’ve written often lately about WPF, including BabySmash posts and Missing .NET articles. I’ve decided to do a complete app using WPF. I’ve dabbled here and there with the concepts, but I’ve decided I don’t really know the framework that well. I still have to look up how to do something basic like master-detail data binding. So I set out to do something fairly basic and (barely) doable by one person - kind of what Scott Hanselman is doing with BabySmash, but a little more traditional, so I can take advantage of more of WPF. I shan’t disclose the function of the app for now, because it’s no where near ready. I will, however, document some things I run into, either because they were so useful, but not really advertised, or because I’ve found sharp rocks in the shallows and must warn others. This post is a bit of both.

If you use Visual Studio, this is obscured from you, but every WPF application must contain the equivalent of the following Main

[STAThread]
public static void Main(string[] args)
{
    Application app = new Application();
    Window win = new Window();
    win.Show();
    app.Run();
}

Without the Application class, the above program will end right after you run it. The magic in Application.Run() is that it sets up a Win32 message pump so that your whiz bang WPF objet d’art can interact with the rest of Windows, and not exit immediately. There is a surprising amount going on in those four lines of code. Let me explain the big things, before I tell you about the subtlety I found.

There can only be one Application object per process. After the first line of code in the snippet above is run, you can access the static Application.Current property. Doing a test in the Immediate window in Visual Studio to check equality of app and Application.Current will yield true. You can access this anywhere in your app, which makes it really handy.

Let’s continue with executing the second line.

Once the win instance is created, if we were to inspect the app object again, we’d see a few things have changed: the MainWindow property is now non-null — it’s pointing to the win instance; also, the Windows collection will have a Count of 1. For every other window created during the lifetime of the application, the Windows collection will be added to.

Quite a lot has happened in just two lines of code!

The other two lines are obvious; a lot happens when they execute too, but they’re peripheral to the discussion, so let’s move on.

This is a common pattern. Microsoft recognized this and codified it into a pattern. The Application class is designed to be inherited, and a WPF app that doesn’t show a window is a very boring thing. If you create a new WPF application project in VS, you don’t have to write that Main method above; it’s all done for you with code gen in the inherited Application object. You don’t even need to explicitly instantiate a Window instance: VS points the Application.StartupUri property to the XAML file defining your main window.

Now that’s great for one-off demos or simple applications that do the equivalent of turn a light on and off. But, in my experience as a Windows developer, if you want to do anything complicated, your application will have all sorts of configuration to do; or you have to log in to a service to do anything useful; or whatever. Suppose a developer had to code a scenario to show a dialog on the first run of the app to do some absolutely necessary, can’t-run-the-app-without-it configuration. To develop that scenario, one would have to eschew the StartupUri property for something slightly more complex.

The Application class also has a number of important events concerned with application lifetime. One of them is the Startup event. A naive developer would handle the previously mentioned scenario of a config dialog in that event handler, like so:

public class MyApp : Application
{
    protected override void OnStartup(object sender, StartUpEventArgs e)
    {
        if (firstRun)
        {
            MyConfigDialog dialog = new MyConfigDialog();
            if (!dialog.ShowDialog().Value)
            {
                this.Shutdown();
            }
        }
        MyMainWindow window = new MyMainWindow();
        window.Show();
    }
}

If firstRun is true, and you click OK on the dialog, so that ShowDialog() returns true, then the app will shutdown. I know what you’re thinking:

Huh?

I’m not sure, myself: this may be a bug. But here’s what’s going on: if this is the first run of the app, then the dialog is shown. It’s the first Window class created. Therefore, the Application.MainWindow property is set to the dialog instance. When ShowDialog() returns, the dialog is closed. Therefore, Application.MainWindow is null. It’s like that MyMainWindow instance is invisible or something. He could be screaming at the top of his lungs at Application: “HEY, LOOK AT ME! I’VE GOT SOMETHING TO SHOW YOU!”

Then Application just turns around and exits the building.

“ASSH– wait a minute! I’m invisible! I don’t need that stupid App instance. I’m going to rob a bank! I’ll be rich and the ladies will love me.” Then he falls on the floor lifeless, ’cause the whole process died. Poor MyMainWindow.1

You could also set the MainWindow property yourself, apparently, at any time you want to. But this fails too:

public class MyApp : Application
{
    protected override void OnStartup(object sender, StartUpEventArgs e)
    {
        if (firstRun)
        {
            MyConfigDialog dialog = new MyConfigDialog();
            if (!dialog.ShowDialog().Value)
            {
                this.Shutdown();
            }
        }
        MyMainWindow window = new MyMainWindow();
        //guess what? this doesn't work!
        this.MainWindow = window;
        window.Show();
    }
}

I’m seriously baffled by this. Looking around in Reflector, the code I’m looking at says it shouldn’t act like this. I also don’t touch Application.ShutdownMode (I’ve tested this with OnLastWindowClose and with OnMainWindowClose). Anyway, to workaround the issue, simply ensure that MainWindow is instantiated first:

public class MyApp : Application
{
    protected override void OnStartUp(object sender, StartUpEventArgs e)
    {
        //this works! 
        MainWindow window = new MainWindow();
        if (firstRun)
        {
            MyConfigDialog dialog = new MyConfigDialog();
            if (!dialog.ShowDialog().Value)
            {
                this.Shutdown();
            }
        }
        window.Show();
    }
}

The Application class is a much needed addition to Windows programming. A cross between the ASP.NET Application and Session classes and the WinForms Application class, it provides a property bag, application lifetime events, application-wide resources, an entry point, a Win32 message pump and access to the application’s windows including the Main Window. Architecturally, I find this class very appealing, but that’s a topic for another post.

Just watch out for trying to be fancy with extra windows.


Notes

1 What, you don’t anthropomorphize your objects?

Posted in .NET | 1 Comment »

I’ve recently been asked for more detail on how I extracted my blog posts from Subtext. I hacked my solution together in a few nights of hacking. Once I got it working, I completely flushed all memory of what I did. But I was asked a whole two times, dear readers! With that overwhelming curiosity, I have no choice but to respond. For background, please read the previous post on what I did generally to convert from Subtext to Wordpress.

I’m told that the BlogML export always fails in Subtext, which is the same problem I had. If I recall, it would look like it succeeded, but the XML file you got back would be empty. I was using a version that ran on .NET 1.1 (I think around 1.5, but I’m not sure), but the technique I outline below should work for Subtext 1.9.5. I’ll explain (with some code!) how I got around that and it will hopefully help some people out. I had one single-user blog running on Subtext; Multi-user may need far more attention. You will have to get your hands dirty in the code; and by the end of it, you’ll be more familiar with Subtext than you ever wanted to be. I’m writing this from memory, so take whatever I say as a guide rather than gospel. I no longer have a subtext blog set up so I can’t rerun this to see why I made the changes I made. If you’re really determined, you’ll find a way to get your data. I am willing to help anyone extract their posts from Subtext, though. Just contact me through this post, or through the contact form. Maybe we can make this a little more robust to help others.

When I first tried to export using the web interface, as I mentioned, I’d get an XML file, but it would be empty. Bummer! My first thought was that I had to figure out the right query for the database to extract all the posts. Then I would have to format all the posts into some kind of XML format to import into my new blog engine, Wordpress. That’s a daunting task when you don’t deal with databases much. Luckily, I played some video games instead of bashing on and realized there was an easier way: using the BlogML exporter in Subtext!

I don’t remember exactly how I came to my solution — maybe I bombed around the code and concluded that the reason it was failing had little to do with the BlogML code? — but it worked, and this was the type of quick one-off problem to which one of my favourite sayings applied: If it’s stupid and it works, it isn’t stupid.

So here’s what I did. I created a ConsoleApplication1 project, referenced just enough of the subtext assemblies (Subtext.BlogML, Subtext.Framework and Subtext.Extensibility) to instantiate their BlogMLWriter and write out the BlogML to disk using an XmlTextWriter. Then I hacked the subtext code to make it compile and run without exceptions. Like I said last time, this solution is not pretty or perfect. To make matters worse, the subtext code I used in my hacked solution was not the same code that my blog was running, so the database versions didn’t match up. Column names had been changed or added; stored procedures had been renamed or added to. This made me do some seriously weird things like tweak stored procedures and DataReaders and I think install stored procedures that weren’t there. I did the types of things that shouldn’t really be recorded for posterity on a blog, you know?

Here’s the only code in my ConsoleApplication1 project:

class Program
{
    static void Main(string[] args)
    {
        IBlogMLProvider provider = new Subtext.ImportExport.SubtextBlogMLProvider();

        provider.ConnectionString = "yourConnectionString";
        if (provider.GetBlogMlContext() == null)
        {
            Console.WriteLine("ERror'd");
            return;
        }
        BlogMLWriter writer = BlogMLWriter.Create(provider);

        using (XmlTextWriter xmlWriter = new XmlTextWriter("blog.xml", Encoding.UTF8))
        {
            xmlWriter.Formatting = Formatting.Indented;
            writer.Write(xmlWriter);
            xmlWriter.Flush();
        }
        Console.WriteLine("It worked?!");
    }
}

Looks pretty simple, eh? Too bad all the changes are buried deep in completely unrelated classes. I copied the subtext web.config and renamed it app.config. You have to set your connection string in two places in the config file as well as in the Program.cs file shown above (search for ‘yourConnectionString’). Also, since we’re running code written for ASP.NET in a console app, some things simply will not work, like HttpContext.Current. You’ll be shown them quickly after running the first time.

Below is an example of one of the changes I had to make:

private static SqlParameter BlogIdParam
{
    get
    {
        int blogId;
        //if (InstallationManager.IsInHostAdminDirectory)
        //    blogId = NullValue.NullInt32;
        //else
            blogId = 0;

        return DataHelper.MakeInParam("@BlogId", SqlDbType.Int, 4, DataHelper.CheckNull(blogId));
    }
}

This is in Subtext.Framework\Data\SqlDataProvider.cs. See the commented code? InstallationManager, through a number of indirections (like, I don’t know, 57; Subtext is way over-architected) uses HttpContext.Current, so I commented that out. I may have even hardcoded blogId to 0, I don’t remember.

You can download the ConsoleApplication1 project below and try it out if you wish.

Now, if you want to convert BlogML to the Wordpress export format…

Posted in .NET | No Comments »