<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <id>http://thomasjo.com/</id>
  <title>THOMASJO</title>
  
  <updated>2011-01-12T00:00:00Z</updated>
  <author>
    <name>Thomas Johansen</name>
  </author>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/thomasjo" /><feedburner:info uri="thomasjo" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/thomasjo" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fthomasjo" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><entry>
    <title type="html">ActionController::MimeResponds is brilliant</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/thomasjo/~3/Szjw9q8_rIE/" />
    <id>http://thomasjo.com/2011/01/12/actioncontroller-mimeresponds-is-brilliant/</id>
    <published>2011-01-12T00:00:00Z</published>
    <updated>2011-01-12T00:00:00Z</updated>
    <author>
      <name>Thomas Johansen</name>
    </author>
    <summary type="html">&lt;p&gt;Was a little bit blown away yesterday, by how smart the ActionController::MimeResponds
module in Rails ActionPack really is. For the longest time when using &lt;code&gt;respond_with&lt;/code&gt;
(the younger sibling of &lt;code&gt;respond_to&lt;/code&gt;,) I&amp;rsquo;ve been doing it wrong&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;Was a little bit blown away yesterday, by how smart the ActionController::MimeResponds
module in Rails ActionPack really is. For the longest time when using &lt;code&gt;respond_with&lt;/code&gt;
(the younger sibling of &lt;code&gt;respond_to&lt;/code&gt;,) I&amp;rsquo;ve been doing it wrong.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve written code similar to this whenever I&amp;rsquo;ve needed to override the default behavior:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;respond_to :html, :json

# .. other actions omitted for brevity

def create
  @discussion = Discussion.find(params[:discussion_id])
  @entry = @discussion.entries.create(params[:entry])

  respond_with @entry do |format|
    format.html do
      if @entry.new_record?
        render 'discussions/show'
      else
        redirect_to discussion_url(@discussion)
      end
    end
    format.json { render :json =&amp;gt; @entry }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;My assumption was that if I needed to change the default behavior, I had to more or less
mimic the behavior of &lt;code&gt;respond_to&lt;/code&gt; (not to be confused with the &lt;code&gt;respond_to&lt;/code&gt; as seen in
the example above) which is to explicitly define behavior for each MIME type response.
Well, it turns out that you only need to override that which deviates from the default
behavior and the rest will still be handled as per the default. The &lt;code&gt;respond_with&lt;/code&gt; block
in the previous example can be simplified as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;respond_with @entry, :location =&amp;gt; discussion_url(@discussion) do |format|
  if @entry.new_record?
    format.html { render 'discussions/show' }
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The only thing that deviates from the standard behavior, is the fact I want to render a
template belonging to another controller and action (the one that initiated the HTTP POST)
whenever the new entry wasn&amp;rsquo;t successfully created. The assumption being it most likely
failed validation, and we need to present the validation errors to the user.&lt;/p&gt;

&lt;p&gt;Why &lt;code&gt;respond_with&lt;/code&gt; hasn&amp;rsquo;t been better documented in e.g. &lt;a href="http://guides.rubyonrails.org/"&gt;The Ruby on Rails Guides&lt;/a&gt;
or in &lt;a href="http://rubydoc.info/docs/rails/3.0.0/ActionController/MimeResponds"&gt;the API documentation&lt;/a&gt;
is not known to me, but my best guess would be because this is a new feature in Rails 3,
nobody has gotten around to it yet.
I only found out about this behavior by looking at the &lt;a href="https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/mime_responds.rb"&gt;source code&lt;/a&gt;,
but for all I know this might be common knowledge and I&amp;rsquo;ve simply overlooked it somehow.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/thomasjo/~4/Szjw9q8_rIE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://thomasjo.com/2011/01/12/actioncontroller-mimeresponds-is-brilliant/</feedburner:origLink></entry>
  <entry>
    <title type="html">Really simple and na&amp;iuml;ve Ruby plugin framework</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/thomasjo/~3/HRwnPuhLtUg/" />
    <id>http://thomasjo.com/2010/12/15/really-simple-and-naive-ruby-plugin-framework/</id>
    <published>2010-12-15T00:00:00Z</published>
    <updated>2010-12-15T00:00:00Z</updated>
    <author>
      <name>Thomas Johansen</name>
    </author>
    <summary type="html">&lt;p&gt;I recently found myself writing some Ruby (IronRuby to be specific) at work for
&lt;a href="http://umbraco.org/"&gt;Umbraco&lt;/a&gt; that needed to generate HTML for different types of content,
destined to be displayed in an aside column. There are many ways of doing something like this,
but in order to not violate the
&lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;Open/Closed Principle&lt;/a&gt;, I decided to
create a very simple and na&amp;iuml;ve plugin framework that would automagically wire up new
content-type handlers.
The way I chose to implement this, was to leverage the meta-programming capabilities in Ruby,
more specifically the &lt;code&gt;inherited&lt;/code&gt; hook&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;I recently found myself writing some Ruby (IronRuby to be specific) at work for
&lt;a href="http://umbraco.org/"&gt;Umbraco&lt;/a&gt; that needed to generate HTML for different types of content,
destined to be displayed in an aside column. There are many ways of doing something like this,
but in order to not violate the
&lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;Open/Closed Principle&lt;/a&gt;, I decided to
create a very simple and na&amp;iuml;ve plugin framework that would automagically wire up new
content-type handlers.
The way I chose to implement this, was to leverage the meta-programming capabilities in Ruby,
more specifically the &lt;code&gt;inherited&lt;/code&gt; hook.&lt;/p&gt;

&lt;h2&gt;Say hello to your friendly neighbourhood hooks&lt;/h2&gt;

&lt;p&gt;One of the most powerful aspects of Ruby, is its meta-programming capabilities; the aspect that
allows you to shape the language to fit your needs and requirements &amp;ndash; at runtime.&lt;/p&gt;

&lt;p&gt;Hooks are perhaps not strictly speaking a meta-programming capability, but they play a very
important role in meta-programming. Undoubtedly the most infamous of all the hooks is
&lt;code&gt;method_missing&lt;/code&gt;. As the name suggest, it&amp;rsquo;s the hook that allows you to intercept calls to
undefined methods.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Hello
  def method_missing(name, *args)
    "Hello #{name.capitalize}!"
  end
end

hello = Hello.new
puts hello.neighbour  # "Hello Neighbour!"
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Respect the hook&lt;/h2&gt;

&lt;p&gt;To implement the plugin framework, I decided to leverage a seemingly under-appreciated hook
found on &lt;code&gt;Class&lt;/code&gt; called &lt;code&gt;inherited&lt;/code&gt;. Yet again, the name gives it all away &amp;ndash; this hook is
called whenever the class is implemented (sub-classed.) We can utilise this hook to implement a
simple plugin registration system packaged up in a module.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;module Plugin
  module ClassMethods
    def repository
      @repository ||= []
    end

    def inherited(klass)
      repository &amp;lt;&amp;lt; klass
    end
  end

  def self.included(klass)
    klass.extend ClassMethods  # Somewhat controversial
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because we want to add singleton methods to whatever class includes our plugin module, we use
a common, albeit slightly controversial technique; leverage another hook &amp;ndash; &lt;code&gt;#included&lt;/code&gt; &amp;ndash; to
automagically extend the target class with the our &lt;code&gt;ClassMethods&lt;/code&gt; modules.&lt;/p&gt;

&lt;h2&gt;Let&amp;rsquo;s build some plugins!&lt;/h2&gt;

&lt;p&gt;With the &lt;code&gt;Plugin&lt;/code&gt; module we have the foundation needed to implement various types of plugins;
let&amp;rsquo;s create a very silly plugin type for displaying various kinds of messages.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# ./lib/message_plugin.rb
require './lib/plugin'

class MessagePlugin
  include Plugin

  def display_output
    raise NotImplementedError.new('OH NOES!')
  end
end

# ./plugins/hello_world.rb
class HelloWorld &amp;lt; MessagePlugin
  def display_output
    puts 'Hello World! :-)'
  end
end

# ./plugins/goodbye_world.rb
class GoodbyeWorld &amp;lt; MessagePlugin
  def display_output
    puts 'Goodbye World... :-('
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Because we&amp;rsquo;ve taken advantage of the &lt;code&gt;inherited&lt;/code&gt; hook, all that is necessary for plugins of
type &lt;code&gt;MessagePlugin&lt;/code&gt; to work, is to require the files containing the implementations, e.g.
a directory called &amp;ldquo;plugins.&amp;rdquo;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dir = './plugins'
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, '*.rb')].each {|file| require File.basename(file) }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now all that is required for someone to add a new message to our application, is to inherit
from &lt;code&gt;MessagePlugin&lt;/code&gt; and drop the implementation into the &amp;ldquo;plugins&amp;rdquo; folder.&lt;/p&gt;

&lt;h2&gt;Taking it one step further&amp;hellip;&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;MessagePlugin&lt;/code&gt; is extremely simple &amp;ndash; what if we want to pass data to a plugin? Perhaps we
only want to pass the data to plugins that can handle that type of data. An easy way
of pulling this off, is to query the registered plugins on whether they can handle it.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# ./lib/type_handler_plugin.rb
require './lib/plugin'

class TypeHandlerPlugin
  include Plugin

  def self.for_type(type)
    repository.find {|handler| handler.can_handle? type }
  end
end

# ./plugins/string_handler.rb
class StringHandler &amp;lt; TypeHandlerPlugin
  def self.can_handle?(type)
    type == String
  end

  def display_output(data)
    puts "String: #{data}"
  end
end

# ./plugins/time_handler.rb
class TimeHandler &amp;lt; TypeHandlerPlugin
  def self.can_handle?(type)
    type == Time
  end

  def display_output(data)
    puts "Formatted Time: #{data.strftime '%A, %B %m, %Y'}"
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;#can_handle?(type)&lt;/code&gt; predicate method hands the responsibility over to the plugins, thus
requiring no changes to any other class whenever we add a new type and/or type handler to the
application. The Open/Closed Principle remains unviolated.&lt;/p&gt;

&lt;h2&gt;One more thing&amp;hellip;&lt;/h2&gt;

&lt;p&gt;Just for good measure, here is a rather silly test harness for running the various plugins
we&amp;rsquo;ve peeked at &amp;ndash; enjoy responsibly!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require './lib/array'
require './lib/message_plugin'
require './lib/type_handler_plugin'

#
# Add plugins folder to LOAD_PATH and subsequently require all plugins.
#
dir = './plugins'
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, '*.rb')].each {|file| require File.basename(file) }

class TestHarness
  def self.run
    run_message_plugin
    run_type_handler_plugin
  end

  private

    def self.run_message_plugin
      message_plugin = MessagePlugin.repository.random.new
      message_plugin.display_output
    end

    def self.run_type_handler_plugin
      random_data = [Time.now, 'Example string.', 1337].random
      type_handler_plugin = TypeHandlerPlugin.for_type(random_data.class)
      unless type_handler_plugin.nil?
        type_handler_plugin = type_handler_plugin.new 
        type_handler_plugin.display_output(random_data)
      end
    end
end

TestHarness.run
&lt;/code&gt;&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/thomasjo/~4/HRwnPuhLtUg" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://thomasjo.com/2010/12/15/really-simple-and-naive-ruby-plugin-framework/</feedburner:origLink></entry>
  <entry>
    <title type="html">Why I love Ruby</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/thomasjo/~3/TtCn7fzHhMs/" />
    <id>http://thomasjo.com/2010/12/09/why-i-love-ruby/</id>
    <published>2010-12-09T00:00:00Z</published>
    <updated>2010-12-09T00:00:00Z</updated>
    <author>
      <name>Thomas Johansen</name>
    </author>
    <summary type="html">&lt;p&gt;I&amp;rsquo;ve been a fan of the Ruby language since I was first introduced to Ruby on Rails back in 2005.
While I was learning both Rails and Ruby, it quickly became apparent that all the awesome-ness
of the former would never have been possible without the latter; what makes Rails great is Ruby,
and Ruby would almost certainly still be an obscure and under-appreciated language had it not
been for Rails. Ruby is a remarkably beautiful language, and I love working with it&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;I&amp;rsquo;ve been a fan of the Ruby language since I was first introduced to Ruby on Rails back in 2005.
While I was learning both Rails and Ruby, it quickly became apparent that all the awesome-ness
of the former would never have been possible without the latter; what makes Rails great is Ruby,
and Ruby would almost certainly still be an obscure and under-appreciated language had it not
been for Rails. Ruby is a remarkably beautiful language, and I love working with it.&lt;/p&gt;

&lt;h2&gt;Freedom to hang ourselves&lt;/h2&gt;

&lt;p&gt;To me, and infinitely more prominent people like David Heinemeier Hansson, Ruby is very much about
&lt;a href="http://tekpub.com/conferences/rubyconf2010/dhh"&gt;freedom&lt;/a&gt;. Freedom to shape the language to suit
our purpose and fulfil our needs.
Ruby will likely never feel old or outdated, because we are free to change it, to create our
own versions of the language. The killer feature is that we can do this without needing to
change the Ruby source and compiling a new version of the language &amp;mdash; we can do it from within
our own frameworks and applications.&lt;/p&gt;

&lt;p&gt;This is the point where many die-hard supporters of statically typed, compiled languages
usually stop and go &amp;ldquo;What? That cannot possibly be safe? How do you guarantee that X does what
X usually does?&amp;rdquo; The answer is that you don&amp;rsquo;t, but why do you need it to? As long as you don&amp;rsquo;t
fundamentally alter (which I would interject might be correct in some scenarios) built-in types
and so on, what is the problem of changing the behaviour to better suit the tasks at hand?
Are you really willing to trade freedom for security? Even if that freedom meant you could
create beautiful code and focus more solving the tasks at hand, as opposed to having
&amp;ldquo;guaranteed&amp;rdquo; runtime behaviour, type safety etc?
When was the last time static type checking saved your day? As DHH himself said in his keynote
at &lt;a href="http://www.rubyconf.org/"&gt;RubyConf 2010&lt;/a&gt; as a response to the oft cited &amp;ldquo;Just enough rope to
hang yourself with&amp;rdquo; comment; &amp;ldquo;Should we outlaw rope, just because people can hang themselves
with it?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;There are things you can do in Ruby, changes that fundamentally alter how the language itself
works, that you probably shouldn&amp;rsquo;t do, but should the language really prevent you from doing it,
or should you learn on your own? Personally, I&amp;rsquo;m all for the latter &amp;mdash; learning through
experience.&lt;/p&gt;

&lt;h2&gt;It&amp;rsquo;s also about the people&lt;/h2&gt;

&lt;p&gt;The freedom Ruby provides me with, is the biggest reason I love it as much as I do, but Ruby
also has a fantastic community. A community that continues to innovate and develop fantastic
services such as &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt;, and projects such as
&lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt;. There is a feeling in the Ruby community that everyone is
free to innovate and create the next big thing. Sure, there are some bad eggs in the batch
and it&amp;rsquo;s not always just peachy, but it&amp;rsquo;s still by far the most inspiring and friendly
community I&amp;rsquo;ve ever felt I&amp;rsquo;ve been a part of.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/thomasjo/~4/TtCn7fzHhMs" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://thomasjo.com/2010/12/09/why-i-love-ruby/</feedburner:origLink></entry>
  <entry>
    <title type="html">XMLDSIG in the .NET framework</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/thomasjo/~3/AWi_G7qGMs0/" />
    <id>http://thomasjo.com/2009/08/04/xmldsig-in-the-net-framework/</id>
    <published>2009-08-04T00:00:00Z</published>
    <updated>2009-08-04T00:00:00Z</updated>
    <author>
      <name>Thomas Johansen</name>
    </author>
    <summary type="html">&lt;p&gt;I was recently given the task on one of my projects at work, to implement a new version of
a digital signature solution that we use to get legally binding signatures" from users.
As part of the upgrade process, I had to implement support for
&lt;a href="http://www.w3.org/TR/2008/REC-xmldsig-core-20080610/"&gt;XMLDSIG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To my great joy, I discovered that the .NET framework has supported XMLDSIG for years, but
I quickly got into problems and all of the documentation I found online, including the
official MSDN documentation covering the XMLDSIG support was either lacking or incorrect&amp;hellip;&lt;/p&gt;
</summary>
    <content type="html">&lt;p&gt;I was recently given the task on one of my projects at work, to implement a new version of
a digital signature solution that we use to get legally binding signatures" from users.
As part of the upgrade process, I had to implement support for
&lt;a href="http://www.w3.org/TR/2008/REC-xmldsig-core-20080610/"&gt;XMLDSIG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To my great joy, I discovered that the .NET framework has supported XMLDSIG for years, but
I quickly got into problems and all of the documentation I found online, including the
official MSDN documentation covering the XMLDSIG support was either lacking or incorrect.&lt;/p&gt;

&lt;h2&gt;What is XMLDSIG?&lt;/h2&gt;

&lt;p&gt;Before I get to the code, and the problems I encountered, I&amp;rsquo;ll briefly explain the concept
of XMLDSIG; &lt;a href="http://www.w3.org/Signature/Drafts/WD-xmldsig-core-20000114/"&gt;XMLDSIG is an old standard&lt;/a&gt;
in Internet years, and is seemingly accepted as the best and easiest way of digitally
signing XML documents.&lt;/p&gt;

&lt;p&gt;The signature can distributed in three different variants;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/2008/REC-xmldsig-core-20080610/#def-SignatureEnveloped"&gt;Enveloped signature&lt;/a&gt;
&amp;mdash; the signature is added to the document that was signed.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/2008/REC-xmldsig-core-20080610/#def-SignatureEnveloping"&gt;Enveloping signature&lt;/a&gt;
&amp;mdash; the signature contains the document that was signed.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.w3.org/TR/2008/REC-xmldsig-core-20080610/#def-SignatureDetached"&gt;Detached signature&lt;/a&gt;
&amp;mdash; the signature is distributed separate from the document that was signed.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The differences are rather subtle, but there are many transformations that can be applied
to the document prior to signing, and only the right combinations provide valid signatures,
and that is one of the problems I encountered with the
&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signedxml.aspx"&gt;problematic MSDN documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Enveloping != Enveloped&lt;/h2&gt;

&lt;p&gt;The problem with the MSDN documentation, and virtually every other example of doing
XMLDSIG in .NET, is that they are only based around the &amp;ldquo;enveloped signature&amp;rdquo; variant,
even when they tell you they are showing you an example of the &amp;ldquo;enveloping signature&amp;rdquo;
variant. Either the authors of the examples have misunderstood the XMLDSIG specification,
or have mistakenly used the word &amp;ldquo;enveloping&amp;rdquo;, when they should have used &amp;ldquo;enveloped.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;The problem is that, most, if not all, of the authors tell you they are showing you an
example of the enveloping variant, they are instead using some freakish hybrid variant,
and the only reason the sample actually works, is because they are combining the enveloped
and enveloping variants. Any attempt to validate the signature without the context of the
parent document, will fail.&lt;/p&gt;

&lt;p&gt;One approach for generating valid enveloping signatures, is to utilize a different
transform that is designed to work with the enveloping variant. The transform I ended up
using was the &lt;a href="http://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/"&gt;Exclusive XML Canonicalization&lt;/a&gt;
transform, as it lends itself very well to extracting the enveloped document and using it
in another context.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public static class XmlDsig
{
    private const LoadOptions SafeLoadOptions = LoadOptions.PreserveWhitespace;
    private const SaveOptions SafeSaveOptions = SaveOptions.DisableFormatting;


    public static XDocument SignDocument(XDocument originalDocument,
                                         X509Certificate2 certificate)
    {
        if (originalDocument.Root == null) {
            throw new ArgumentException(
                "Invalid XML document; no root element found.", "originalDocument");
        }

        SignedXml signature = GetSignature(originalDocument, certificate);
        XDocument signatureDocument = GetSignedDocument(signature);

        VerifySignature(signatureDocument, certificate);

        return signatureDocument;
    }


    private static SignedXml GetSignature(XNode originalDocument,
                                          X509Certificate2 certificate)
    {
        XmlDocument document = GetXmlDocument(originalDocument);
        if (document.DocumentElement == null) {
            throw new InvalidOperationException(
                "Invalid XML document; no root element found.");
        }

        var signedXml = new SignedXml(document);
        var dataObject = new DataObject("message", "", "", document.DocumentElement);

        signedXml.AddReference(GetSignatureReference());
        signedXml.AddObject(dataObject);
        signedXml.SigningKey = certificate.PrivateKey;
        signedXml.KeyInfo = GetCertificateKeyInfo(certificate);
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
        signedXml.ComputeSignature();

        return signedXml;
    }


    private static XmlDocument GetXmlDocument(XNode originalDocument)
    {
        var document = new XmlDocument { PreserveWhitespace = true };
        document.LoadXml(originalDocument.ToString(SafeSaveOptions));

        return document;
    }


    private static Reference GetSignatureReference()
    {
        var signatureReference = new Reference("#message");
        signatureReference.AddTransform(new XmlDsigExcC14NTransform());

        return signatureReference;
    }


    private static KeyInfo GetCertificateKeyInfo(X509Certificate certificate)
    {
        var certificateKeyInfo = new KeyInfo();
        certificateKeyInfo.AddClause(new KeyInfoX509Data(certificate));

        return certificateKeyInfo;
    }


    private static XDocument GetSignedDocument(SignedXml signedXml)
    {
        string signatureXml = signedXml.GetXml().OuterXml;
        XDocument signedDocument = XDocument.Parse(signatureXml, SafeLoadOptions);

        return signedDocument;
    }


    private static void VerifySignature(XNode signedDocument,
                                        X509Certificate2 certificate)
    {
        var document = new XmlDocument { PreserveWhitespace = true };
        document.LoadXml(signedDocument.ToString(SafeSaveOptions));
        if (document.DocumentElement == null) {
            throw new InvalidOperationException(
                "Invalid XML document; no root element found.");
        }

        var signedXml = new SignedXml(document);
        signedXml.LoadXml(document.DocumentElement);
        if (!signedXml.CheckSignature(certificate, true)) {
            throw new InvalidOperationException("Signature is invalid.");
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I had to make another little adjustment to get everything to work correctly, and that was
explicitly setting the canonicalization method. Changing the transform, also solved
another problem I encountered; the inability to reference the object elements by URI ID,
as the default behavior when using the enveloped variant is to look for elements matching
the URI ID within the document being signed, instead of within the signature.&lt;/p&gt;

&lt;h2&gt;But what if I want to use the &amp;ldquo;enveloped signature&amp;rdquo; variant?&lt;/h2&gt;

&lt;p&gt;If you don&amp;rsquo;t want the variant I needed (enveloping), then changing the code sample above
to produce signatures of the enveloped kind, is trivial; first make sure to remove the
following two lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;signedXml.AddObject(dataObject);
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next step is to change the GetSignatureReference method; we need to replace the
transform implementation with something that is suitable for the enveloped signature.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;private static Reference GetSignatureReference()
{
    var signatureReference = new Reference();
    signatureReference.AddTransform(new XmlDsigEnvelopedSignatureTransform());

    return signatureReference;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We also need to add an extra argument to the GetSignedDocument method, so that we can pass
in the original document.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;private static XDocument GetSignedDocument(XNode originalDocument, SignedXml signedXml)
{
    string signatureXml = signedXml.GetXml().OuterXml;
    XElement signatureElement = XElement.Parse(signatureXml, SafeLoadOptions);
    XDocument signedDocument = XDocument.Load(
        originalDocument.CreateReader(),
        SafeLoadOptions);
    if (signedDocument.Root == null) {
        throw new InvalidOperationException("Invalid XML document; no root element found.");
    }

    signedDocument.Root.Add(signatureElement);

    return signedDocument;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you spot any errors, please let me know, so that there can exist at least one correct
example of using XMLDSIG in the .NET framework.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/thomasjo/~4/AWi_G7qGMs0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://thomasjo.com/2009/08/04/xmldsig-in-the-net-framework/</feedburner:origLink></entry>
</feed>

