<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[getting gui]]></title><description><![CDATA[my ramblings about programming]]></description><link>http://gettinggui.com/</link><generator>Ghost v0.4.2</generator><lastBuildDate>Thu, 16 Apr 2026 21:07:30 GMT</lastBuildDate><atom:link href="http://gettinggui.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Compiling .net projects with node-gyp]]></title><description><![CDATA[<p>In order to actually use <a href='http://gettinggui.com/colorizing-output-from-msbuild-in-strider/' >my custom msbuild logger</a>, it must be compiled. Node has a native compiler that will be run during an <code>npm install</code>: <code>node-gyp</code>. All the documentation seems to indicate that this is only for <code>c/c++</code> projects. I didn't like that answer, so I did a bit of research into projects I knew used <code>c#</code> in <code>node</code>. And I hit the jackpot with <a href='https://github.com/tjanczuk/edge' ><code>edge</code></a> (which is itself <strong>really</strong> cool).</p>

<p>It turns out that you can specify a command line to run as an <code>action</code>. The difference is that instead of allowing <code>node-gyp</code> to create the visual studio project to build (and building it), you just have to specify a command line that will do the build. If using a <code>.csproj</code> file, this is how you'd do so:</p>

<pre><code>{
  'targets': [{
    'target_name': 'my-project',
    'type': 'none',
    'actions': [{
      'action_name': 'compile',
      'inputs': [ 'all.cs', 'your.cs', 'files.cs' ],
      'outputs': [ 'path\to\result.dll' ],
      'message': 'msbuild myproject.csproj',
      'action': ['msbuild', 'myproject.csproj', '/p:Configuration=Release']
    }]
  }]
}
</code></pre>

<p>A couple of notes:</p>

<ul>
<li><code>inputs</code> and <code>outputs</code> <strong>must</strong> be specified, or <code>node-gyp</code> won't run your action during a <code>build</code></li>
<li><code>inputs</code> can be a blank array, but <code>outputs</code> must have at least one item, or <code>node-gyp</code> won't build it.</li>
<li>The project specified as the argument to <code>msbuild</code> will specify where to output the file, so <code>outputs</code> doesn't really matter.</li>
<li>Likewise, the project file specifies the files to build, so the contents of <code>inputs</code> isn't important.</li>
<li><code>outputs</code> can be useful for other actions that wouldn't build your directory structure for you, as <code>node-gyp</code> will create it.</li>
<li>If your code exists in 1 file, consider calling <code>csc</code> (csharp compiler); you won't need a project file.</li>
</ul>

<p>For my project, here is the resultant <code>binding.gyp</code>:</p>

<pre><code>{
  'targets': [{
    'target_name': 'strider-msbuild-logger',
    'type': 'none',
    'actions': [{
      'action_name': 'compile',
      'inputs': [ ],
      'outputs': [ 'strider.msbuild.logger.dll' ],
      'message': 'msbuild Strider.MsBuild.Logger.csproj',
      'action': ['msbuild', 'Strider.MsBuild.Logger.csproj', '/nologo', '/tv:2.0', '/p:Configuration=Release']
    }]
  }]
}
</code></pre>

<p>I'm not using <code>csc</code> here, because I want to force the use of .NET 2.0. That way, all versions of msbuild can use my logger. As far as I'm aware, there is no way to force <code>csc</code> to do so. </p>

<p>I hope this quick tip is enough to get you started. There are more advanced scenarios, such as conditional actions (which would be great for building on linux with mono [in fact, edge does this]).</p>

<p>If you want to see how my project is using this, you can check it out on <a href='https://github.com/abe545/strider-msbuild-logger/tree/5509506a717a8fa39e2a148e3fb13d1c1bd2d4bc' >github</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/compiling-net-projects-with-node-gyp/</link><guid isPermaLink="false">3879ec20-610f-4d62-9271-f92192a59903</guid><category><![CDATA[node]]></category><category><![CDATA[.net]]></category><category><![CDATA[node-gyp]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sat, 28 Jun 2014 21:04:12 GMT</pubDate></item><item><title><![CDATA[Colorizing output from msbuild in strider]]></title><description><![CDATA[<p>Now that I have <a href='http://gettinggui.com/restoring-nuget-packages-for-net-projects-in-strider/' >nuget restoring my projects packages</a> in strider at build time, I wanted to get <code>msbuild</code>'s output colorized. I was hoping that it would have an option to force color on, but unfortunately it does not. What I found odd is that you can force it <em>off</em>. W.T.F. I get that by default you don't want to be sending ANSI color codes to a log file, but why not give both options for controlling color on the console? Thankfully, msbuild supports custom loggers. So, at least there is that. It is annoying that I have to try to duplicate the default logger, but at least it is possible. </p>

<p>Instead of adding the logger to <a href='https://github.com/abe545/strider-dot-net' ><code>strider-dot-net</code></a>, I decided to add a new package: <a href='https://github.com/abe545/strider-msbuild-logger' ><code>strider-msbuild-logger</code></a>. This enabled me to make it an optional dependency for <code>strider-dot-net</code>. This is important because during an <code>npm install</code>, the logger is going to have to be compiled. I didn't want <code>strider-dot-net</code> to fail to install if for some reason the colorized logger couldn't be built. The other thing that this new package does is give you the path to the logger. If it is null, or undefined, you can safely assume that the logger doesn't exist.</p>

<p>The javascript for the logger's <code>index.js</code> is very simple:</p>

<pre><code>var fs = require('fs')  
  , path = require('path');

module.exports = function () {  
  var logger = path.join(__dirname, 'Strider.MsBuild.Logger.dll');
  if (fs.existsSync(logger)) {
    return logger;
  }

  return null;
};
</code></pre>

<p>Since it is an optional dependency, the <code>require</code> could fail, so I have to protect the code that uses it with a <code>try/catch</code> block (in <code>strider-dot-net</code>'s <code>worker.js</code>):</p>

<pre><code>try {  
  var logger = require('strider-msbuild-logger')();
} catch (err) {
  logger = null;
}

if (logger) {  
  // shut off the standard console logger, otherwise the output will be logged twice
  args.push('/noconsolelogger', '/logger:' + logger);
} 
</code></pre>

<p>The actual meat of the logger is pretty boring, as it just implements the <a href='http://msdn.microsoft.com/en-us/library/microsoft.build.framework.ilogger.aspx' ><code>ILogger</code></a> interface. I did finally figure out the ANSI control codes, thanks to <a href='http://en.wikipedia.org/wiki/ANSI_escape_code' >wikipedia</a> (<em>of course</em>). What is interesting, is that it doesn't seem to control the output when building manually in a Windows Command Prompt (it displays them as unicode characters). The article specifically states that Windows Command Prompts don't interepret these sequences, so that would explain it.</p>

<p>At the end of the day, I'm pretty happy with how it turned out:</p>

<p><img src='http://files.gettinggui.com/images/strider-msbuild-color-output.png'  alt="Colorized output from strider-msbuild-logger" /></p>

<p>You can grab the code on <a href='https://github.com/abe545/strider-msbuild-logger/tree/5e64c710fcda3db7f9ae009f18a764216d5efb89' >github</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/colorizing-output-from-msbuild-in-strider/</link><guid isPermaLink="false">94692aeb-6f1c-4ac9-ae5e-fc0474feabf1</guid><category><![CDATA[strider-dot-net]]></category><category><![CDATA[strider]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sat, 28 Jun 2014 16:51:36 GMT</pubDate></item><item><title><![CDATA[Restoring NuGet packages for .NET projects in Strider]]></title><description><![CDATA[<p>Since <a href='http://gettinggui.com/building-net-projects-in-strider/' >getting .NET projects building in strider</a> was pretty easy, I decided to add built-in NuGet package installation. That way, you don't need to store <code>nuget.exe</code> for every single project you create (NuGet package restore).</p>

<p>Thankfully, <a href='http://nuget.org/' >http://nuget.org</a> hosts the latest version of <code>nuget.exe</code> at <a href='http://www.nuget.org/nuget.exe' >http://www.nuget.org/nuget.exe</a>. This makes it extremely easy to pull down the latest version. I used <a href='https://www.npmjs.org/package/request' ><code>request</code></a> to pull it down, as it is easy to download a file:</p>

<pre><code>request.get('http://www.nuget.org/nuget.exe').pipe(file);  
</code></pre>

<p>I decided to store <code>nuget.exe</code> in strider's base directory (c:\.strider on my dev box), as strider is guaranteed to be able to write there. It is pretty easy to get inside a runner context:</p>

<pre><code>var nugetPath = path.join(context.baseDir, 'nuget', 'nuget.exe');  
</code></pre>

<p>I then used <a href='https://www.npmjs.org/package/fs-extra' ><code>fs-extra</code></a> to make sure the full path to the file exists for writing, and then download it:</p>

<pre><code>fs.ensureFile(nugetPath, function() {  
  var file = fs.createWriteStream(nugetPath);
  request.get('http://www.nuget.org/nuget.exe').pipe(file);
});
</code></pre>

<p>I also decided to ensure that the latest version of nuget is installed (if <code>nuget.exe</code> already exists):</p>

<pre><code>fs.exists(nugetPath, function(exists) {  
  if (exists) {
    childProc.spawn(nugetPath, [ 'update', '-Self' ]);
  } else { // download it... see above }
});
</code></pre>

<p>In order to get the packages, I just had to call <code>nuget restore</code>:</p>

<pre><code>context.cmd({  
  cmd: {
    command: nugetPath,
    args: ['restore', '-NonInteractive' ],
    screen: 'nuget restore'
  }
}, done);
</code></pre>

<p>In all these code snippets, I removed all the extraneous logging information. But, in the actual repo, there is a lot of code to give more feedback when building in strider. You can check it out on <a href='https://github.com/abe545/strider-dot-net/tree/91cfab97bf39f198cca54d4da53602a59a95f4da' >github</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/restoring-nuget-packages-for-net-projects-in-strider/</link><guid isPermaLink="false">6fed6127-25d4-422c-b251-866593272ec2</guid><category><![CDATA[strider-dot-net]]></category><category><![CDATA[strider]]></category><category><![CDATA[nuget]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sun, 22 Jun 2014 19:15:32 GMT</pubDate></item><item><title><![CDATA[Building .NET Projects in Strider]]></title><description><![CDATA[<p>After <a href='http://gettinggui.com/fetching-code-from-codeplex-in-strider' >successfully getting code from Codeplex</a>, I was eager to get one of my projects building. The two I care about are both .NET projects. I knew there was no .NET support in strider when I first started investigating it, so I knew I was going to have to make the plugin myself. This is (the beginnings of) my attempt at getting Strider to build my .NET projects.</p>

<p>The build system for .NET is pretty easy to use. It is all supported in <code>msbuild</code>. The problem is how to determine where it lives. And which version to use (as of now, these versions exist: 1.0, 1.1, 2.0, 3.0, 3.5, 4.0).</p>

<p>My first idea was to use the <code>vcvarsall.bat</code> file, as it will put <code>msbuild</code> in the path. Since it is included in Visual Studio, I was all set to give you a choice of which version of VS to use to run the build. And I didn't want to just execute <code>vcvarsall.bat</code> in the same context that strider was running in, as it would pollute the environment for all jobs. Instead, I used <code>cmd.exe</code> (the <code>/c</code> closes the cmd shell after the command has executed) to execute multiple items at once:</p>

<pre><code>cmd /c '/path/to/vcvarsall.bat' &amp; 'msbuild myproj'  
</code></pre>

<p>After getting all that working in strider (it was obviously a lot more complex than that), I realized that Visual Studio should not be installed on a build server. Ideally, it should be as unpolluted as possible, to give more confidence that a user's machine can run your project without additional software (besides the appropriate version of .NET).</p>

<p>Since <code>msbuild</code> is included with the framework, I was able to call it from the .NET installation directory. Which is: <code>%WINDIR%\Microsoft.NET\Framework\{version}</code> or <code>%WINDIR%\Microsoft.NET\Framework64\{version}</code> for 64 bit msbuild. Generally, this will be <code>c:\windows</code>, but using the environment variable is obviously safer than assuming windows is installed to the default directory and drive.</p>

<p>So, now I have a selection box that lets the user pick the version of .NET, and the build step will try to detect if <code>msbuild</code> exists in the given directory. Right now, it favors the 64 bit framework, but I am not entirely sure if that is correct, or if it even matters. For all I know, they are identical programs.</p>

<p>I used <a href='https://www.npmjs.org/package/async' ><code>async</code></a>'s <code>waterfall</code> method, so I don't need a ton of nested function calls in the code that detects <code>msbuild</code>:</p>

<pre><code>function findmsbuild(version, framework, callback) {  
  var root = process.env.windir + '\\Microsoft.NET\\' + framework;
  async.waterfall([
    function (next) {
      fs.readdir(root, next);
    },
    function (files, next) {
      var dir = _.find(files, function(f) {
        return f.indexOf('v' + version) &gt;= 0;
      });

      if (dir) {
        next(null, root + '\\' + dir);
      } else {
        next('msbuild could not be found for .NET ' + version);
      }
    },
    function (dir, next) {
      var msbuild = dir + '\\msbuild.exe';
      fs.exists(msbuild, function(exists) {
        if (exists) {
          next(null, msbuild);
        } else {
          next('msbuild could not be found for .NET ' + version);
        }
      });      
    }
  ], callback);
}
</code></pre>

<p>Then, when I want to call <code>msbuild</code>:</p>

<pre><code>if (config.netVersion &amp;&amp; config.netVersion != 'whatever') {  
  findmsbuild(config.netVersion, 'Framework64', function (err, fullpath) {
    if (err || !fullpath) {
      findmsbuild(config.netVersion, 'Framework', function (err, fullpath) {
        if (err) {
          done(err);
        } else {
          msbuild(context, fullpath, args, screen, done);
        }
      });
    } else {
      msbuild(context, fullpath, args, screen, done);
    }
  });
} else {
  msbuild(context, 'msbuild', args, screen, done);
}
</code></pre>

<p>Where the <code>msbuild</code> function is:</p>

<pre><code>function msbuild(context, path, args, screen, done) {  
  context.cmd({
    cmd: {
      command: path,
      args: args,
      screen: screen
    }
  }, done);
}
</code></pre>

<p>The error in strider when <code>msbuild</code> couldn't be found was pretty bad, so I decided to fix it. The <code>context</code> supports multiple output methods, but there doesn't seem to be any documentation about it. So, I cracked open <code>strider-runner-core</code> to see how to do so. It seems that the <code>status</code> method formats all the output based on the keyword passed as the first argument.</p>

<p>To print the command after the <code>$</code> sign, I had to pass <code>command.start</code>:</p>

<pre><code>var time = new Date();  
context.status('command.start', { command: screen, started: time, time: time, plugin: 'dotnet' });  
</code></pre>

<p>The error had to be passed with <code>stderr</code>:  </p>

<pre><code>context.status('stderr', err);  
</code></pre>

<p>And, I learned I could colorize it by using ANSI control codes. I don't really get how this works; I just ripped it from <code>strider-runner-core</code>:  </p>

<pre><code>context.status('stderr', '\u001b[31;1m' + err + '\u001b[0m');  
</code></pre>

<p>And if I didn't pass <code>command.done</code>, the execution timer never stopped:  </p>

<pre><code>context.status('command.done', { exitCode: 404, time: time, elapsed: 0 });  
</code></pre>

<p>I'm faking the exit code to be 404, because it isn't found. Makes sense, right? </p>

<p>All in all, I'm pretty happy with how easy this was to get setup. With the way strider manages projects, I think the next step is to add the ability to restore <code>nuget</code> packages automatically. I know you can setup nuget package restore to do this, but I think it is silly to store <code>nuget.exe</code> for <strong>every</strong> project you are going to create.</p>

<p>I have pushed the code to github at <a href='https://github.com/abe545/strider-dot-net/tree/520a6e6b490cbf247282db3453db6020b65629e1' >abe545/strider-dot-net</a>.</p>]]></description><link>http://gettinggui.com/building-net-projects-in-strider/</link><guid isPermaLink="false">8220d82f-aa26-41e5-991c-8767a9023a24</guid><category><![CDATA[js]]></category><category><![CDATA[strider-dot-net]]></category><category><![CDATA[strider]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Mon, 09 Jun 2014 01:48:17 GMT</pubDate></item><item><title><![CDATA[Fetching code from Codeplex in Strider]]></title><description><![CDATA[<p><a href='http://gettinggui.com/getting-branches-from-codeplex-in-strider' >Last time</a>, I was able to get strider to recognize my branches in codeplex. However, it still won't fetch the code. Which is the whole point of this entire process!</p>

<p>For a Node project, the first thing that strider does is try to get a <code>package.json</code> file from the repo. Unfortunately, there is no good way to do this with either <code>git</code> or <code>mercurial</code>. And of course, there is no codeplex api to do so. Thankfully, strider allows us to specify that we don't support individual files via <code>fastFile</code>. We will also throw an error if <code>getFile</code> is called(in <code>webapp.js</code>):</p>

<pre><code>fastFile: false,  
getFile: function (filename, ref, account, config, project, done) {  
  done(new Error('not implemented'));
}
</code></pre>

<p>Next, in <code>worker.js</code>, we need to implement two exports: <code>init</code> and <code>fetch</code>. Based on <code>strider-github</code>, <code>init</code> needs to return an object that also calls <code>fetch</code>, like so:</p>

<pre><code>module.exports = {  
  init: function (dirs, account, config, job, done) {
    return done(null, {
      config: config,
      account: account,
      fetch: function (context, done) {
        module.exports.fetch(dirs.data, account, config, job, context, done);
      }
    });
  }
}
</code></pre>

<p>Implementing <code>fetch</code> should be pretty simple. I just need to use <code>strider-git</code> to fetch a <code>git</code> repo, and <del><code>strider-hg</code></del> (crap, when I started this series, I thought it existed, but now I can't find it...) <a href='https://www.npmjs.org/package/hg' ><code>hg</code></a> for <code>mercurial</code> ones:</p>

<pre><code>fetch: function(dest, account, config, job, context, done) {  
  if (config.type === 'git') {
    git.fetch(dest, config, job, context, done);      
  } else if (config.sourceType === 'mercurial') {
    hg.clone(config.sourceUrl, dest, {"-b": job.ref.branch}, done);
  }
}
</code></pre>

<p>Now, when I try to test... <strong>nothing</strong>. Well, crap. After some debugging, it turns out that Codeplex capitalizes <code>git</code> and <code>mercurial</code>. That is annoying, so I decided to alter the <code>parseRepo</code> function in <code>webapp.js</code> to make the <code>sourceType</code> lowercase:</p>

<pre><code>function parseRepo(account, repo) {  
  return {
    id: account.name + '/' + repo.Name,
    name: account.name + '/' + repo.Name,
    display_name: repo.Title,
    display_url: repo.Url,
    group: repo.Role,
    'private': !repo.IsPublished,
    config: {
      sourceType: repo.SourceControl.ServerType.toLowerCase(),
      sourceUrl: repo.SourceControl.Url,
      repoName: repo.Name
    }
  }
}
</code></pre>

<p>Trying it again... And it fails. Because the config is missing an <code>auth</code>:</p>

<pre><code>    config: {
      sourceType: repo.SourceControl.ServerType.toLowerCase(),
      sourceUrl: repo.SourceControl.Url,
      repoName: repo.Name,
      auth: {
        type: 'https'
      }
    }
</code></pre>

<p>Aaaand... Fail. No <code>repo</code>. Grrr. At this point, I just renamed everything to match the <code>strider-github</code> setup:</p>

<pre><code>    config: {
      type: repo.SourceControl.ServerType.toLowerCase(),
      url: repo.SourceControl.Url,
      repo: repo.Name,
      auth: {
        type: 'https'
      }
    }
</code></pre>

<p>I obviously had to change the references everywhere else, also. After doing so, it worked! Well, for git repos anyway. <code>Mercurial</code> repos have an issue with the default branch. In <code>git</code>, it is <code>master</code>, where in <code>mercurial</code> it is <code>default</code>. Strider doesn't take this into account, so I had to:</p>

<pre><code>var branch = job.ref.branch;  
if (branch === 'master') {  
  // hg's default branch is default, not master... Ideally this would be handled in the repo setup, but use this as a workaround
  branch = 'default';
}
</code></pre>

<p>One last problem for the <code>mercurial</code> side of things: it won't report progress to the strider output window. To solve this, I had to do a bit of extra work:</p>

<pre><code>if (config.type === 'mercurial') {  
  var branch = job.ref.branch;
  if (branch === 'master') {
    // hg's default branch is default, not master... Ideally this would be handled in the repo setup, but use this as a workaround
    branch = 'default';
  }
  var start = new Date()
    , cmd = 'hg clone ' + config.url + ' . -b ' + branch;
  context.status('command.start', { command: cmd, time: start, plugin: context.plugin });
  hg.clone(config.url, dest, {"-b": branch}, function(err, output) {
    var end = new Date()
      , elapsed = end.getTime() - start.getTime();
    if (err) {
      context.out('hg error: ' + err.message);
    }

    if (output) {
      output.forEach(function(line) {
        context.out(line.body);
    });
  }

  context.status('command.done', {exitCode: 0, time: end, elapsed: elapsed});
    done(err, output);
  });
}
</code></pre>

<p>And with that, Strider can fetch code from Codeplex!</p>

<p>One last thing I've done, to make the plugin match the other strider plugins: I moved <code>strider.json</code> to <code>package.json</code>.</p>

<p>You can grab the code at <a href='https://github.com/abe545/strider-codeplex/tree/3fe594c9b0f8b2b0102ff4acb6846181249f91b1' >github</a>.</p>

<p>-Ah</p>]]></description><link>http://gettinggui.com/fetching-code-from-codeplex-in-strider/</link><guid isPermaLink="false">9685a31b-0602-40f9-a017-c034252fbe64</guid><category><![CDATA[js]]></category><category><![CDATA[strider-codeplex]]></category><category><![CDATA[codeplex]]></category><category><![CDATA[node]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sun, 01 Jun 2014 01:49:14 GMT</pubDate></item><item><title><![CDATA[Getting Branches from Codeplex in Strider]]></title><description><![CDATA[<p>After my <a href='http://gettinggui.com/adding-a-codeplex-repo-to-strider/' >last post</a>, I was at the point where strider would list my repos, and I could even see a little checkbox by their name. Unfortunately, clicking on the configure buttons would do nothing. This is because clicking those buttons calls <code>getBranches</code>, and I am not yet doing anything in that method.</p>

<p>Unfortunately, the Codeplex API doesn't include any functionality for getting the branches for a given repository. This means I am going to have to do this work manually, and I'm going to have to go through the source control provider. </p>

<p>For Mercurial branches, I thought it would be somewhat of a rigamorale. You see, Mercurial requires the repository to be on a local computer before you can see the branches. It turns out, <a href='http://stackoverflow.com/questions/4296636/list-remote-branches-in-mercurial' >stackoverflow</a> has a question (and answer!) about how to query a remote repository. Since Codeplex uses hgweb to serve the repo, we can query it directly:</p>

<pre><code>if (sourceType === 'mercurial') {  
    request(config.sourceUrl + '/branches?style=raw', function(error, response, body) {
        if (error) return callback(error, null);
        var branches = [];
        var rows = rawText.split(/\r\n|\r|\n/g);

        // ignore the last row... it is always blank
        for (var i = rows.length - 2; i &gt;= 0; i--) {
            var branchInfo = rows[i].split(/\t/g);
            if (branchInfo[2] !== 'closed') {
                branches.push(branchInfo[0]);
            }
        }

        callback(null, branches);
    });
}
</code></pre>

<blockquote>
  <p>Mercurial branches can be marked closed, but they are never deleted. Since Codeplex returns all Mercurial branches, I must filter out the closed ones.</p>
</blockquote>

<p>For git repositories, my first thought was to use <code>strider-git</code>. Unfortunately, it requires a <code>context</code> object, but the <code>context</code> is only available when jobs are being run. Since the branch retrieval is happening long before that, I decided to use <a href='https://www.npmjs.org/package/git-node' >git-node</a>. It is almost as easy to use as the mercurial setup:</p>

<pre><code>if (sourceType === 'git') {  
    var remote = git.remote(config.sourceUrl);
    remote.discover(function(err, refs) {
        if (err) {
            callback(err, null);
        } else {
            remote.close(function(error) {
                if (error) {
                    callback(error, null);
                } else if (!refs) {
                    callback("No data returned for the repo.", null);
                } else {
                    var branches = Object.keys(refs).filter(function (ref) { return ref.indexOf('refs/heads/') == 0; }).map(function (ref) {
                        return ref.replace('refs/heads/', '');
                    });

                    callback(null, branches);
                }
            });
        }
    });
}
</code></pre>

<blockquote>
  <p>I don't want to get anything but branches, hence the filter. If I wanted to use tags, removing this filter will allow me to do so.</p>
</blockquote>

<p>Now when I go to the configure screen, it navigates correctly, but the UI seems... off. It appears that I have missed something... Oh yes, the <code>config.html</code> and <code>config.js</code>. I haven't implemented anything to configure, but after throwing (basically) blank config files at strider, things seem to be working fine:</p>

<pre><code>&lt;div class="row-fluid"&gt;  
&lt;/div&gt;  
</code></pre>

<pre><code>app.controller('CodeplexController', ['$scope', function ($scope) {  
  $scope.config = $scope.providerConfig();

  $scope.save = function () {
    $scope.providerConfig($scope.config, function () {});
  };
}]);
</code></pre>

<p>And with that, I can successfully add projects to strider, open the config screen, and you can get autocomplete in the branch selection box! Woot! Maybe I can soon have it actually fetching and running tests... maybe. As always, you can grab the code on <a href='https://github.com/abe545/strider-codeplex/tree/ac69d6abadb62cb25de9d64a7da28c0c537a271d' >github</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/getting-branches-from-codeplex-in-strider/</link><guid isPermaLink="false">30cd97b1-e691-49a5-bb54-5b26361b3f86</guid><category><![CDATA[strider-codeplex]]></category><category><![CDATA[codeplex]]></category><category><![CDATA[node]]></category><category><![CDATA[strider]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Mon, 28 Apr 2014 08:35:34 GMT</pubDate></item><item><title><![CDATA[Adding a codeplex repo to strider]]></title><description><![CDATA[<p>After my <a href='http://gettinggui.com/making-a-strider-plugin' >last post</a>, I can now get an authenticated user's repositores. However, I am experiencing a couple of issues. </p>

<p>First, the codeplex oauth tokens expire after an hour. Because of this, I am seeing a number of authentication errors. In order to solve this, I need to get the <code>refresh token</code> from codeplex. Thankfully, it seems this is a <a href='https://github.com/jaredhanson/passport-google-oauth/issues/23' >feature built into passport</a>. All I had to do was update the validation methods to take one more parameter:</p>

<pre><code>function validateAuth(req, accessToken, refreshToken, parms, profile, done) {  
  if (!req.user) {
    console.warn('Codeplex OAuth but no logged-in user')
    req.flash('account', "Cannot link a codeplex account if you aren't logged in")
    return done()
  } 
  var account = req.user.account('codeplex', profile.UserName)
  if (account) {
    console.warn("Trying to attach a codeplex account that's already attached...")
    req.flash('account', 'That codeplex account is already linked. &lt;a href='https://codeplex.com/site/signout/'  target="_blank"&gt;Sign out of codeplex&lt;/a&gt; before you click "Add Account".')
    return done(null, req.user)
  }

  req.user.accounts.push(makeAccount(accessToken, refreshToken, profile))
  req.user.save(function (err) {
    done(err, req.user);
  })
}

function makeAccount(accessToken, refreshToken, profile) {  
  var username = profile.UserName;
  return {
    provider: 'codeplex',
    id: username,
    display_url: 'https://www.codeplex.com/site/users/view/' + username,
    title: username,
    config: {
      accessToken: accessToken,
      refreshToken: refreshToken,
      name: username,
      avatar: profile.Avatar
    }
  }
}
</code></pre>

<p>With the refresh token on hand, I was able to use the <a href='https://www.npmjs.org/package/refresh-token' ><code>refresh-token</code></a> package to get a valid oauth token. The way I see it, there are 3 options for handling token refreshes:</p>

<ul>
<li>Always get a fresh token before making an API call</li>
<li>Store the expiration of the token, and only refresh when needed</li>
<li>Assume a valid token; on error, refresh and retry</li>
</ul>

<p>I am unsure if there is a best practice for this, but I decided on option 3. The first option seemed like too much overhead for my taste. The second option is appealing to me, but I was too lazy to go look up how to translate the token's expiration timeout into an absolute expiration date. Horrible, I know. But, there you have it. I went with #3 because lazy.</p>

<p>Now that I might have to refresh the token, my API method will need the <code>clientId</code> and <code>clientSecret</code>. I modified <code>getCodeplex</code> and <code>getRepos</code> to take the <code>appConfig</code>, as both are properties there. The most important bit, <code>getCodeplex</code>:</p>

<pre><code>function getCodeplex(account, appConfig, resourcePath, callback) {

    var options = {
      hostname: 'www.codeplex.com',
      path: resourcePath,
      method: 'GET',
      headers: {'x-ms-version': '2012-09-01' }
    };

    if (account &amp;&amp; account.accessToken) {
        options.headers.Authorization = 'Bearer ' + account.accessToken;
    }

    var req = https.request(options, function(res) {
        var json = '';
        res.on('data', function(d) {
            json += d;
        });
        res.on('error', function(err) {
            callback(err, null);
        });
        res.on('end', function() {
            var fin = JSON.parse(json);

            // this is an error message
            if (fin.Message) {
                if (appConfig.clientId &amp;&amp; appConfig.clientSecret &amp;&amp; fin.Message === 'Authentication required.') {
                    var tokenProvider = new TokenProvider('https://www.codeplex.com/oauth/token', {
                    refresh_token: account.refreshToken, 
                    client_id:     appConfig.clientId, 
                    client_secret: appConfig.clientSecret
                    });

                    tokenProvider.getToken(function (err, token) {
                        if (err) { callback(err, null); }
                        else {
                            account.accessToken = token;
                            getCodeplex(account, resourcePath, callback);
                        }
                    });
                }
                else {
                    callback(fin.Message, null); 
                }
            }
            else { callback(null, fin); }
        });
    });

    req.on('error', function(err) {
        callback(err, null);
    });
    req.end();
}
</code></pre>

<p>The second bug: when I try to add a repo to strider, I get an error message in the UI:</p>

<pre><code>Error creating project for repo aheidebrecht/codeonlystoredprocedures:  
{
  "results": [], 
  "status": "error", 
  "errors": [ { 
    "code": 400, 
    "reason": "provider.repo_id is required" 
  } ]
}
</code></pre>

<p>It seems that I left out a required <code>id</code> property in the <code>parseRepo</code> method:</p>

<pre><code>function parseRepo(account, repo) {  
  return {
    id: account.name + '/' + repo.Name,
    name: account.name + '/' + repo.Name,
    display_name: repo.Title,
    display_url: repo.Url,
    group: account.name,
    'private': !repo.IsPublished,
    config: {
      sourceType: repo.SourceControl.ServerType,
      sourceUrl: repo.SourceControl.Url,
      role: repo.Role
    }
  }
}
</code></pre>

<p>After fixing these issues, I was finally able to start the process of setting up a repo. I decided to hold off on implementing the webhook part mostly because, as of this blog post, there is no generic webhook support (it supports <a href='http://blogs.msdn.com/b/codeplex/archive/2013/06/05/codeplex-learns-to-talk-to-other-services.aspx' >these</a> and <a href='http://blogs.msdn.com/b/codeplex/archive/2013/07/10/codeplex-integrates-with-zapier.aspx' >these</a> commercial websites... oh Microsoft). </p>

<p>Instead, I just let strider think I have done something special. Since I don't have to setup or teardown a webhook, those two required api methods are quite simple:</p>

<pre><code>setupRepo: function (account, config, project, done) {  
  if (!account.accessToken) return done(new Error('Codeplex account not configured'));
  done(null, config);
},

teardownRepo: function (account, config, project, done) {  
  if (!account.accessToken) return done(new Error('Codeplex account not configured'));
  done(null, config);
}
</code></pre>

<p>With those methods in place, we can add and remove a repo to strider! Woot! </p>

<p>You can grab this version at <a href='https://github.com/abe545/strider-codeplex/tree/f879fbb5583f87fcb828e75a57c663889f9827cb' >github</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/adding-a-codeplex-repo-to-strider/</link><guid isPermaLink="false">c1341d52-30bf-47d6-b52f-839bf214452e</guid><category><![CDATA[strider]]></category><category><![CDATA[strider-codeplex]]></category><category><![CDATA[node]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Wed, 19 Mar 2014 07:29:18 GMT</pubDate></item><item><title><![CDATA[Making a strider plugin]]></title><description><![CDATA[<p>When I last left off, my <a href='http://gettinggui.com/my-first-module' >codeplex plugin for strider</a> was able to pull in repos from <a href='http://codeplex.com/' >codeplex</a> by passing in a valid codeplex username. While it was a great proof of concept, it isn't the way that strider wants (and in fact needs to) to interract with source control providers. In order to subscribe to code changes, strider needs to authenticate with OAuth. While this turns out to be pretty easy to do, I realized that the longer I tried to write my plugin outside of strider, the more throwaway code I would have to create. As such, I decided to actually make this code a strider plugin now instead of later.</p>

<p>Over at the project page for the <a href='https://github.com/Strider-CD/strider-extension-loader' >strider extensions loader</a>, there is some documentation about creating a plugin. They have some clearly defined roles, one of which is <code>provider</code>. For source control providers. You know, like codeplex. Based on this documentation, I created the following project structure:</p>

<pre><code>codeplex-for-strider
|
+-config
: |
: +-config.html
: +-config.js
|
+-lib
: |
: +-codeplex.js
|
+-webapp.js
+-worker.js
+-package.json
+-strider.json
</code></pre>

<p>I just created blank files for all the new items. Following along with the readme, I configured my <code>strider.json</code> thusly:</p>

<pre><code>{
  "id": "codeplex",
  "title": "Codeplex",
  "type": "provider",
  "hosted": true,
  "config": {
    "controller": "CodeplexController"
  },
  "accountConfig": {
    "setupLink": "/ext/codeplex/oauth"
  },
  "webapp": "webapp.js",
  "worker": "worker.js",
  "inline_icon": "windows"
}
</code></pre>

<blockquote>
  <p>I don't know if it is a documentation issue, or if there are two ways of specifying the url to call to start the authorization process. The docs say to export <code>setupLink</code>, but both the <a href='https://github.com/Strider-CD/strider-github/blob/master/package.json' ><code>strider-github</code></a> and <a href='https://github.com/Strider-CD/strider-bitbucket/blob/master/package.json' ><code>strider-bitbucket</code></a> plugins specify it in the strider config (in their <code>package.json</code>). Since I trust code more than documentation, I too put it in the config.</p>
</blockquote>

<p>The plugin obviously doesn't yet do anything, but after dropping this folder in strider's <code>node_modules</code> directory, I saw it show up in strider! I didn't even have to put it in the <code>package.json</code>. This makes it <strong>incredibly</strong> easy to test.</p>

<p>Because I'm a <del>sadist</del> masochist, my first instinct was to click the <code>Setup Codeplex</code> button. I knew it would fail, but I was <em>curious</em> to see how explosively. It (pleasantly) surprisingly didn't crash the node process, but instead I got:</p>

<pre><code>500  
Error: no strategy registered under name: codeplex  
</code></pre>

<p>And looking at the stack trace (that is <em>niiiiiiiceeeeee</em>) I can see that the strategy is related to something called <a href='http://passportjs.org/' >passport</a>. I was really hoping that somebody had already done the work of creating a codeplex strategy for me, but alas, no such luck. It turns out you can use the <a href='https://github.com/jaredhanson/passport-oauth2' ><code>passport-ouath2</code></a> strategy directly, but since codeplex recommends passing the api version as a header, I decided to create my own.</p>

<p>Thankfully, this is really easy. I looked at a <a href='https://github.com/jaredhanson/passport-github/blob/master/lib/strategy.js' >number</a> <a href='https://github.com/jaredhanson/passport-windowslive/blob/master/lib/strategy.js' >of</a> <a href='https://github.com/jaredhanson/passport-37signals/blob/master/lib/strategy.js' >examples</a>, and I came to the conclusion that this is pretty much boilerplate code. As such, I won't include it here. I will likely break it out into its own project at some point in the near future, even if it doesn't have a lot going on. </p>

<p>So, with a codeplex passport strategy working, I was able to add the <code>auth</code> export in <code>webapp.js</code>:</p>

<pre><code>var codeplex = require('./lib/codeplex')  
  , CodeplexStrategy = require('./lib/passport-codeplex');

module.exports = {  
  auth: function (passport, context) {
    var config = this.appConfig
    passport.use(new CodeplexStrategy({
      clientID: this.appConfig.clientId,
      clientSecret: this.appConfig.clientSecret,
      callbackURL: this.appConfig.hostname + '/ext/codeplex/oauth/callback',
      passReqToCallback: true
    }, validateAuth));
  }  
  ...
}
</code></pre>

<p>I also had to configure an oauth application at <a href='https://www.codeplex.com/site/developers/apps' >codeplex</a>. After doing so, I had to add the information into the <code>webapp.js</code>:</p>

<pre><code>module.exports = {  
  appConfig: {
    hostname: 'http://localhost:3000',
    clientId: 'feecb876f9044bca8a86ab9089fba8b0',
    clientSecret: 'efc1e8c120c24b59b12ad0f4f7d32d02'
  }
  ...
}
</code></pre>

<p>Thoe credentials are for a test application I created that will connect to the default strider DEV settings (localhost:3000). When this plugin gets put into production, I will obviously be using a different set of credentials.</p>

<p>The last step is to create the callback (<code>validateAuth</code> in the <code>auth</code> export) that will register the account in strider. I shamelessly copied most of this from the <a href='https://github.com/Strider-CD/strider-bitbucket' ><code>strider-bitbucket</code></a> plugin, but modified it slightly to parse the data returned from codeplex:</p>

<pre><code>function validateAuth(req, accessToken, parms, profile, done) {  
  if (!req.user) {
    console.warn('Codeplex OAuth but no logged-in user')
    req.flash('account', "Cannot link a codeplex account if you aren't logged in")
    return done()
  } 
  var account = req.user.account('codeplex', profile.UserName)
  if (account) {
    console.warn("Trying to attach a codeplex account that's already attached...")
    req.flash('account', 'That codeplex account is already linked. &lt;a href='https://codeplex.com/site/signout/'  target="_blank"&gt;Sign out of codeplex&lt;/a&gt; before you click "Add Account".')
    return done(null, req.user)
  }

  req.user.accounts.push(makeAccount(accessToken, profile))
  req.user.save(function (err) {
    done(err, req.user);
  })
}

function makeAccount(accessToken, profile) {  
  var username = profile.UserName;
  return {
    provider: 'codeplex',
    id: username,
    display_url: 'https://www.codeplex.com/site/users/view/' + username,
    title: username,
    config: {
      accessToken: accessToken,
      name: username,
      avatar: profile.Avatar
    }
  }
}
</code></pre>

<p>After that, I clicked on the <code>setup codeplex</code> account button again, and I got directed to codeplex! I get really excited for things like this; sad, I know. Upon authorizing the application... node crashed. We need a <code>listRepos</code> export. Well, we have a function that does this... let's call it! </p>

<pre><code>listRepos: function (account, callback) {  
  codeplex.getRepos(account, callback);
}
</code></pre>

<p>Oh, wait, that account object isn't just a username anymore. We need to update the <code>getRepos</code> function to use the account class. Also, now that we are authorized, we should pass the token instead of the username. I am a little embarrassed by how long it took me (seriously about 5 hours of googling, and I never really found a helpful answer with my searches...) to figure out how to pass the token, but I have never really done web programming before. So, I guess I should feel better. Maybe. </p>

<p>Anyway, you can pass it as the <code>Authorization</code> header. So, my updated <code>getRepos</code> looks like this:</p>

<pre><code>function getRepos(account, callback) {

    var options = {
      hostname: 'www.codeplex.com',
      path: '/api/user/projects',
      method: 'GET',
      headers: {'x-ms-version': '2012-09-01' }
    };

    if (account &amp;&amp; account.accessToken) {
        options.headers.Authorization = 'Bearer ' + account.accessToken;
    }

    var req = https.request(options, function(res) {
        var json = '';
        res.on('data', function(d) {
            json += d;
        });
        res.on('error', function(err) {
            callback(err, null);
        });
        res.on('end', function() {
            var repos = JSON.parse(json);
            callback(null, repos);
        });
    });

    req.on('error', function(err) {
        callback(err, null);
    });
    req.end()
}
</code></pre>

<p>One more try clicking that setup codeplex button... <strong>success</strong>!</p>

<p>I can now go to my codeplex project tab, and I see 2 entries, but they are both blank. Looks like I need to massage the data a little bit. I could do it all in the <code>getRepos</code> method, but eventually I am going to need to make other api calls, and will probably want to use the same helper method for doing so (<code>getRepos</code> is going to become <code>getCodeplex</code>). Keeping this in mind, I created a <code>parseRepo</code> function in <code>webapp.js</code>:</p>

<pre><code>function parseRepo(account, repo) {  
  return {
    name: account.name + '/' + repo.Name,
    display_name: repo.Title,
    display_url: repo.Url,
    group: repo.Role,
    'private': !repo.IsPublished,
    config: {
      sourceType: repo.SourceControl.ServerType,
      sourceUrl: repo.SourceControl.Url
    }
  }
}
</code></pre>

<p>According to the docs, strider needs 3 values for the config: <code>name</code>, <code>url</code>, and <code>display_url</code>. Because strider expects the name to be of the form <code>&lt;username&gt;/&lt;reponame&gt;</code>, I had to pass the account in addition to the repo. The other properties are undocumented, but I found them being set in the <code>strider-bitbucket</code> source, so I too decided to set them. Because codeplex doesn't send the actual owner of a project, I am grouping them by the user's role on the project (both <code>strider-github</code> and <code>strider-bitbucket</code> use the repo's owner for the group). The config property is user defined, but the docs said to also export a <a href='http://mongoosejs.com/' >mongoose template</a> named <code>config</code>:</p>

<pre><code>module.exports = {  
  ...
  config: {
    sourceType: String,
    sourceUrl: String
  },
  ...
}
</code></pre>

<p>I then modified the <code>listRepos</code> method to call <code>parseRepo</code> for each item (<code>map</code>):</p>

<pre><code>module.exports = {  
  ...
  listRepos: function (account, callback) {
    codeplex.getRepos(account, function(err, data) {
        if (err) return callback(err)
        callback(null, data.map(function(repo) { return parseRepo(account, repo); }))
    });
}
</code></pre>

<p>With all that done, I now see all my codeplex repos in strider! You can grab the latest version over at <a href='https://github.com/abe545/codeplex-for-strider/tree/699dc335b6f259f0dcd2fd5a26ef5b63079866ae' >github</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/making-a-strider-plugin/</link><guid isPermaLink="false">e47cfead-4f01-42e3-aff7-06549a9b9b5b</guid><category><![CDATA[strider-codeplex]]></category><category><![CDATA[node]]></category><category><![CDATA[strider]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Mon, 17 Mar 2014 00:17:16 GMT</pubDate></item><item><title><![CDATA[My first module]]></title><description><![CDATA[<p>In my <a href='http://gettinggui.com/hello-codeplex' >previous post</a>, I started a project to create a codeplex plugin for <a href='http://www.stridercd.com/' >strider</a>. Today, I will take another baby step. Because baby steps are the easiest. Unless you're a baby. A node baby. Ahem.</p>

<p>In order to make it useful, I did a little bit of refactoring. I created a new <code>codeplex.js</code> file, and moved the code that does all the work into it. This will be the place where all calls to codeplex occur. I created a method that takes the user's name as a parameter, and will get their repositories. It also takes a callback function, which by <a href='http://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks' >node convention</a> expects two arguments: <code>err</code> and <code>data</code>. Errors will be passed in <code>err</code>, and the results will be passed in <code>data</code>:</p>

<pre><code>function getRepos(user, callback)
</code></pre>

<p>Also, after reading about the <a href='https://www.codeplex.com/site/developers/api/version' >codeplex api version</a>, </p>

<blockquote>
  <p>Wait, wait, wait. Seriously Microsoft... you haven't updated the codeplex <del>api in at least 1.5 years?! Have you done <em>any</em> work on it in that time?</del> site in 5 months?! And the last update to the API (<a href='http://blogs.msdn.com/b/codeplex/archive/2013/06/05/codeplex-learns-to-talk-to-other-services.aspx' >to add 3rd party web apps, but <strong>no generic webhooks</strong></a>) was 9 months ago?! It is no wonder that github is so much better that even your own teams are using it instead of codeplex. Not that I have a horse in the online code source repository race, but abandonement just seems like a common theme with some of Microsoft's best/most promising/much loved technologies lately.</p>
</blockquote>

<p>Anyway, after reading about the codeplex api version, I added the version header to the <code>request options</code>:</p>

<pre><code>var options = {  
  hostname: 'www.codeplex.com',
  path: '/api/users/' + user + '/projects',
  method: 'GET',
  headers: {'x-ms-version': '2012-09-01'}
};
</code></pre>

<p>The rest of the code is very similar, but I added functionality to pass along any errors:</p>

<pre><code>var req = https.request(options, function(res) {  
    var json = '';
    res.on('data', function(d) {
        json += d;
    });
    res.on('error', function(err) {
        callback(err, null);
    });
    res.on('end', function() {
        var repos = JSON.parse(json);
        callback(null, repos);
    });
});

req.on('error', function(err) {  
    callback(err, null);
});
req.end();  
</code></pre>

<p>The last, and probably most important part was exposing the method as a module. Node's module concept is pretty slick; by exposing it as a module, it makes it really easy to call from other code. Like, really easy (from <code>index.js</code>):  </p>

<pre><code>var codeplex = require('./codeplex');

codeplex.getRepos(username, function(err, data) {  
...
});
</code></pre>

<p>If you check out the <a href='https://github.com/abe545/codeplex-for-strider/tree/4609c7a8053ee5e91324c36288287966122cc1d6' >github repo</a>, you'll see I also extended <code>index.js</code> to present a form that you can put in a username to see the codeplex repositories for.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/my-first-module/</link><guid isPermaLink="false">294bf7a0-3c11-4904-8b2f-5c94d849f9a0</guid><category><![CDATA[strider-codeplex]]></category><category><![CDATA[node]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Wed, 12 Mar 2014 07:11:16 GMT</pubDate></item><item><title><![CDATA[Hello codeplex!]]></title><description><![CDATA[<p>Now that I've done the (admittedly easy) work of getting ghost setup, I can dive into learning node. This will essentially be <code>hello, world!</code>, but that isn't particularly interesting to anybody (<a href='http://bit.ly/1i6RPeI' >and it is trivial to find yourself</a>), so I am going to challenge myself a little bit. I've recently been evaluating with continuous deployment at work, and coincidentally for some personal projects. One that I am particularly intrigued by is <a href='http://stridercd.com/' >strider</a>. Since it is written in node, it seems promising as a platform for my experiments. My goal is to actually create a useful plugin, so hopefully I can manage to cobble something together!</p>

<p>Now, I have a couple of projects hosted on codeplex, so any continuous deployment solution for me needs to support it as a source control provider. Seeing as strider has support for plugins, my first forray will be creating just such a plugin. I searched the internet for quite a while to try and find a basic node tutorial without much success. Besides <a href='http://howtonode.org/' >how to node</a>, I found a fairly inexpensive <a href='https://leanpub.com/nodebeginner' >e-book</a> that wound up helping a lot.</p>

<p>Okay, for my first <del>trick</del> test, I am just going to try to get the list of repos that I have on codeplex. According to the <a href='https://www.codeplex.com/site/developers/api/projects' >api docs</a>, this is farily simple. Honestly the biggest snag I ran into was that I was trying to use the <code>http</code> node module to call the api. The docs are clear that you need to use <code>https</code>, but I foolishly did not realize that was a  <strong>separate</strong> module in node. With that much need knowledge, it was pretty darn easy to create a simple server to pull my repos:</p>

<pre><code>var https = require('https');  
var http = require('http');

http.createServer(function(request, response) {  
    console.log("Request handler 'codeplex' was called.");

    var options = {
      hostname: 'www.codeplex.com',
      path: '/api/users/aheidebrecht/projects',
      method: 'GET'
    };

    var req = https.request(options, function(res) {
        var json = '';
        res.on('data', function(d) {
            json += d;
        });

        res.on('end', function() {
            // this is just for display purposes... it is unformatted otherwise
            var str = JSON.stringify(JSON.parse(json), null, "    ");
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.write(str);
            response.end();
        });
    });

    req.end();

    req.on('error', function(err) {
        console.error(err);

        response.writeHead(500, { 'Content-Type': 'text/plain' });
        response.write(err);
        response.end();
    });
}).listen(999);
</code></pre>

<p>Just running it in node, and I get the expected output:  </p>

<pre><code>[
    {
        "Role": "Owner",
        "Name": "wpfprogress",
        "Title": "WPF Background Progress Indicator",
        "Description": "The WPF Background Progress Indicator allows developers to show the application is busy without stopping the animation when the UI thread is busy. The indicator's appearance can be modified by using the BusyStyle property.",
        "Url": "https://wpfprogress.codeplex.com/",
        "IsPublished": true,
        "NumberOfFollowers": 12,
        "SourceControl": {
            "ServerType": "Mercurial",
            "Url": "https://hg.codeplex.com/wpfprogress"
        }
    },
    {
        "Role": "Owner",
        "Name": "codeonlystoredprocedures",
        "Title": "Code Only Stored Procedures",
        "Description": "A library for easily calling Stored Procedures. Works great with Entity Framework Code First models.",
        "Url": "https://codeonlystoredprocedures.codeplex.com/",
        "IsPublished": true,
        "NumberOfFollowers": 2,
        "SourceControl": {
            "ServerType": "Git",
            "Url": "https://git01.codeplex.com/codeonlystoredprocedures"
        }
    }
]
</code></pre>

<p>One of the cool things about codeplex is that you can use different source control providers, and you can see that I'm using both git and mercurial. Luckily, strider has support for both. Codeplex also supports TFS, so I may see if I can figure out a way to add that too, but it is low on my radar. As I am planning on turning this thing into a full fledged provider for strider in subsequent posts, I'm going to host it on <a href='http://github.com/abe545/codeplex-for-strider' >github</a>.</p>

<p>Here is the <a href='http://github.com/abe545/codeplex-for-strider/tree/a9c7cfc4bca28fee2a46485e228aa7655c0c3468' >changeset</a> at this point in the project.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/hello-codeplex/</link><guid isPermaLink="false">9780cb9b-68f9-4ef7-b1c1-441a2cc5188b</guid><category><![CDATA[strider-codeplex]]></category><category><![CDATA[codeplex]]></category><category><![CDATA[node]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Tue, 11 Mar 2014 08:15:29 GMT</pubDate></item><item><title><![CDATA[Pointing my old blog to the new one]]></title><description><![CDATA[<p>Even though my old blog had literally 5 posts, because I am either:</p>

<ul>
<li>A good internet citizen</li>
<li>A narcissist</li>
<li>Both</li>
</ul>

<p>I have decided to do the good thing and do 302 redirects from the old posts to their new locations. </p>

<p>The first thing I needed to do was point my old blog (<a href='http://blog.abrahamheidebrecht.co/' >blog.abrahamheidebrecht.co</a>) to the new location (<a href='http://gettinggui.com/' >gettinggui.com</a>). This was easy to do with my domain registrar, <a href='http://gettinggui.com/hover.com' >hover</a>.  </p>

<blockquote>
  <p>Sidenote: hover is awesome. Definitely the best registrar I've used. If you haven't looked into them, go there now. Thank me later.</p>
</blockquote>

<p>Because my old blog was using wordpress, the permalinks are slightly different from the ghost ones. Thankfully, I wasn't including the date, so it is literally off by one extra word in the path. My wordpress links were of the form <code>/archives/post-slug</code> and the ghost permalinks look are just <code>/post-slug</code>. Now, I am the furthest thing from an expert when it comes to configuring websites, but my spidey sense is telling me this should be easy. It is one word!</p>

<p>Because I am running the new blog on Azure, it is running under IIS (with <a href='https://github.com/tjanczuk/iisnode' >nodeiis</a> to host ghost). This means I can issue redirects through the <code>web.config</code> file. After a bit of <a href='http://stackoverflow.com/questions/15236350/iis-8-0-directory-httpredirect' >googlefu</a>, I altered my <code>web.config</code> to have two new rules (one is for the old rss feed, which is an even simpler redirect):</p>

<pre><code>&lt;rewrite&gt;  
    &lt;rules&gt;
        &lt;rule name="wp-redirect" stopProcessing="true"&gt;
            &lt;match url="archives/(.+)$" /&gt;
            &lt;action type="Redirect" url="/{R:1}" redirectType="Permanent" /&gt;
        &lt;/rule&gt;
        &lt;rule name="wp-rss" stopProcessing="true"&gt;
            &lt;match url="feed" /&gt;
            &lt;action type="Redirect" url="/rss" redirectType="Permanent" /&gt;
        &lt;/rule&gt;
    &lt;/rules&gt;
&lt;/rewrite&gt;  
</code></pre>

<p>And <strong>bam</strong>, the old site's links point to my new blog!</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/pointing-my-old-blog-to-the-new-one/</link><guid isPermaLink="false">1d96a91d-f606-456b-b7b9-69adafe25c4e</guid><category><![CDATA[ghost]]></category><category><![CDATA[iis]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Mon, 10 Mar 2014 09:50:24 GMT</pubDate></item><item><title><![CDATA[Moving to ghost]]></title><description><![CDATA[<p>As is obvious to the most casual of observers, I've never been the most prolific blogger. <strong>But</strong>, I have recently realized that I <em>need</em> to learn javascript (I can't stay a <code>WPF</code> developer my whole career if MS decides to stop updating it...). At least if I want to have a future in software development. As a means to that end, I have decided to startup the blog again, and this time I have decided to use <a href='https://ghost.org/' >Ghost</a>.</p>

<p>It is my intention to learn <code>node.js</code>, and along the way, I can hopefully contribute some thoughtful words. If not, at least I will learn some much needed new skills.</p>

<p>So, I setup the blog on Azure, which was brain dead simple, but I ran into a few snags that took me way too long to figure out. So, I'll just drop them here in case anybody has the same issues and the googles don't seem to be helping.</p>

<p>First, when deploying the website with git, if you find your blog posts disappearing whenever you do a redeploy, it is because ghost uses <code>sqlite</code> by default. The implications of this are that the database is stored in the filesystem. On your website. Which gets overwritten when you push new source to your azure repository. You can work around this by either deploying via FTP, and only copying over the files that have changed. Or, using FTP, you can pull down the <code>ghost.db</code> file, and check it into your git repo. </p>

<p>Now, because I didn't want to go through that hassle every time I wrote a new post, I decided that maybe <code>sqlite</code> wasn't the best choice for me. Since ghost supports MySQL and PostgreSQL, I figured I could set up a MySQL database on <a href='https://www.cleardb.com/' >cleardb</a> easily enough. There are <a href='https://ghost.org/forum/installation/113-ghost-using-mysql/' >many</a> <a href='http://www.allaboutghost.com/connecting-ghost-to-mysql-aws-rds-instance/' >guides</a> <a href='http://www.allaboutghost.com/example-config-js-mysql-database/' >on</a> the internet on how to get MySQL working with ghost. </p>

<p>So, I set it up, and as soon as I tried to set my theme to something other than casper... I got an error because there were too many connections open. You see, the free <code>cleardb</code> plan only allows 4 simultaneous connections. And the <code>mysql</code> driver defaults to allowing 10 simultaneous connections. Since it appears that ghost creates a lot of connections to the database in its normal operations, this is a problem. </p>

<p>After much searching of the intertubes, I <a href='https://github.com/tgriesser/bookshelf/issues/175' >discovered</a> that you can specify the size of the connection pool used by <a href='http://knexjs.org/' >knex</a> (one of the libraries used to abstract the database storage). You can do so by setting up the maximum pool size in config.js:</p>

<pre><code>database: {  
    client: 'mysql',
    connection: {
        host: 'path-to-cleardb',
        user: 'user',
        password: 'pw',
        database: 'db-name',
        charset: 'utf8'
    },
    pool: {
        max: 4,
        min: 0
    }
}
</code></pre>

<p>I thought I was all set, but when I clicked the button to save a draft of the post... I learn I don't have permission to do so. It turns out that when ghost creates the permission tables, it assumes that the id columns will increment by 1. This seems like a normally safe assumption, but in the case of cleardb, they increment by 10 (I assume to allow up to 10 simultaneous inserts to work?). </p>

<p>This was easily fixed by altering the <code>permissions_roles</code> table. Changing the values in <code>permission_id</code> from  </p>

<pre><code>| id | role_id | permission_id |
+----+---------+---------------+
|  1 |       1 |             1 |
+----+---------+---------------+
| 11 |       1 |             2 |
+----+---------+---------------+
| 21 |       1 |             3 |
+----+---------+---------------+
</code></pre>

<p>to  </p>

<pre><code>| id | role_id | permission_id |
+----+---------+---------------+
|  1 |       1 |             1 |
+----+---------+---------------+
| 11 |       1 |            11 |
+----+---------+---------------+
| 21 |       1 |            21 |
+----+---------+---------------+
</code></pre>

<p>With that setup, I now have a fully operational <del>battlestation</del> blog.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/moving-to-ghost/</link><guid isPermaLink="false">e92c6014-7663-4a29-b866-651ee541ba16</guid><category><![CDATA[node]]></category><category><![CDATA[js]]></category><category><![CDATA[ghost]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sun, 09 Mar 2014 10:00:19 GMT</pubDate></item><item><title><![CDATA[Reporting progress from a Task]]></title><description><![CDATA[<p>I have been trying to convert some of my old asynchronous code to the .NET 4.0 Task API.  In particular, I have been trying to convert some code that reported progress through the <code>BackgroundWorker</code> class.  Unfortunately, I haven’t seen a built in way to report the progress of a <code>Task</code>, so I decided to take a go at doing this.</p>

<p>My first thought was to just pass a <code>SynchronizationContext</code> into the delegate used to create the <code>Task</code>.  I didn’t like that solution because now the idea of the <code>Task</code> as a piece of work is polluted with code simply to make a callback onto the correct thread.  Ideally I wouldn’t have to worry about that every time I wanted to report progress from a <code>Task</code>.</p>

<p>The solution I eventually came up with was to use subtasks.  When a new <code>Task</code> is created while another <code>Task</code> is being executed, it is added as a child of that <code>Task</code>.  These <code>Task</code>s are aggregated by the parent <code>Task</code>, and can share the same <code>CancellationToken</code> so that if the main <code>Task</code> is cancelled, the child <code>Task</code>s will also have a cancellation requested.  By waiting for the children to complete, the main <code>Task</code> won’t complete successfully unless all the sub tasks have.</p>

<p>In order to make the programming model as similar as possible to standard <code>Task</code>s, I created a <code>Create</code> method in the <code>ReportableTask</code> static class:  </p>

<pre><code>public static class ReportableTask  
{
    public static Task Create&lt;TResult&gt;(Action&lt;Task&lt;TResult&gt;&gt; reportProgress,
        params Func&lt;TResult&gt;[] createWorkTasks)
    {
        if (createWorkTasks == null || createWorkTasks.Length == 0)
            throw new ArgumentNullException("createWorkTasks",
      "Must specify at least one function to create a reportable task with.");

        TaskScheduler current =
            TaskScheduler.FromCurrentSynchronizationContext();
        return new Task(() =&gt;
        {
            List&lt;Task&gt; children = new List&lt;Task&gt;();

            foreach (var func in createWorkTasks)
            {
                Task&lt;TResult&gt; task = new Task&lt;TResult&gt;(o =&gt;
                    {
                        if (AcknowledgePendingCancellations())
                            return default(TResult);

                        TResult res = ((Func&lt;TResult&gt;)o)();

                        if (AcknowledgePendingCancellations())
                            return default(TResult);

                        return res;
                    }, func, TaskCreationOptions.RespectParentCancellation);

                task.ContinueWith(reportProgress,
                    TaskContinuationOptions.OnlyOnRanToCompletion, current);
                task.Start();

                children.Add(task);
            }

            if (!AcknowledgePendingCancellations())
            {
                try
                {
                    Task.WaitAll(children.ToArray(),
                        Task.Current.CancellationToken);
                }
                catch (OperationCanceledException)
                {
                    AcknowledgePendingCancellations();
                }
            }
        });
    }
}
</code></pre>

<p>I also created <code>StartNew</code> methods to simplify common <code>Task</code> creation scenarios:  </p>

<pre><code>public static Task StartNew&lt;TResult&gt;(Action&lt;Task&lt;TResult&gt;&gt; reportProgress,  
    params Func&lt;TResult&gt;[] createWorkTasks)
{
    Task t = Create&lt;TResult&gt;(reportProgress, createWorkTasks);
    t.Start();
    return t;
}

public static Task StartNew&lt;TResult&gt;(Action&lt;Task&lt;TResult&gt;&gt; reportProgress,  
        Action&lt;Task&gt; continueWith,
        TaskContinuationOptions continueOptions,
        params Func&lt;TResult&gt;[] createWorkTasks)
{
    Task t = Create&lt;TResult&gt;(reportProgress, createWorkTasks);
    t.ContinueWith(continueWith,
            continueOptions,
            TaskScheduler.FromCurrentSynchronizationContext());
    t.Start();
    return t;
}

private static bool AcknowledgePendingCancellations()  
{
    if (Task.Current.IsCancellationRequested)
    {
        Task.Current.AcknowledgeCancellation();
        return true;
    }

    return false;
}
</code></pre>

<p>When <code>Cancel()</code> is called on a <code>Task</code>, it sets the <code>IsCancellationRequested</code> property to true, but unless it is acknowledged with <code>AcknowledgeCancellation</code>, the framework will assume that the <code>Task</code> completed successfully when the delegate returns.  Creating one of these <code>Task</code>s couldn’t be easier:  </p>

<pre><code>_currentTask = ReportableTask.StartNew&lt;int&gt;(OnProgress,  
                       t =&gt; _parent.HasProgress = false,
                       TaskContinuationOptions.OnlyOnRanToCompletion,
                       PerformOperation,
                       PerformLongOperation);
</code></pre>

<p>In the sample project I have included, cancellation of the <code>Task</code> is accomplished by clicking on the button that is used to start the <code>Task</code>s in the first place.  You can tell that the <code>Task</code>s are not completing because when a <code>Task</code> runs to completion, the <code>OnProgress</code> method will add the amount of progress to a list of completed operations to output in an <code>ItemsControl</code>.</p>

<p>The main problem in implementing this as separate sub-tasks is that each sub-task must be atomic.  Unfortunately, that is unlikely to be the case when wanting to report progress on some long running operation.  The reality is that when we are reporting progress, it is generally to indicate when we have completed a certain aspect of a complex problem that is wholly dependent on the previous work being done.</p>

<p>I’m not sure if there is a better way of doing this using <code>Task</code>s, but I would love to hear about it if there is.</p>

<p>Here is the source for the post <a href='http://gettinggui.com/files.gettinggui.com/examples/reporttaskprogress.zip' >ReportTaskProgress.zip</a>.</p>

<p>-AH</p>]]></description><link>http://gettinggui.com/reporting-progress-from-a-task/</link><guid isPermaLink="false">bc3365f4-53ec-4adc-b5ce-a80b48cd5521</guid><category><![CDATA[wpf]]></category><category><![CDATA[task-api]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Tue, 18 Aug 2009 17:38:48 GMT</pubDate></item><item><title><![CDATA[Mouse Wheel Zooming UIElements via Behaviors]]></title><description><![CDATA[<p>I got an email the other day from Lab49’s MVP asking how I would easily zoom a picture using the mouse wheel in WPF.  Since I don’t feel like arbitrarily restricting myself to only zooming images, I’ll show you how to use a behavior to apply this functionality to any <code>UIElement</code>.</p>

<p>First, I’ll show you how I have traditionally implemented this kind of functionality: Attached Behaviors.  This is a concept that has been discussed extensively in the WPF community, so I’ll just show the interesting bits.  I’ve created a <code>Zoom</code> static class with a couple of public attached properties: <code>MinimumScale</code>, <code>MaximumScale</code>, <code>EnableMouseWheel</code>.  When the <code>EnableMouseWheel</code> property changes, we either attach or detach the <code>PreviewMouseWheel</code> event handler on the <code>UIElement</code> (depending on the new value).  Then, when the event is raised, we actually change the <code>RenderTransform</code> of the element to be zoomed: </p>

<pre><code>static void OnEnableMouseWheelChanged(DependencyObject d,  
    DependencyPropertyChangedEventArgs e)  
{
    UIElement elem = d as UIElement;
    if (elem == null)
        throw new NotSupportedException(
            "Can only set the Zoom.EnableMouseWheel attached behavior on a UIElement.");

    if ((bool)e.NewValue)
        elem.PreviewMouseWheel += OnMouseWheel;
    else
        elem.PreviewMouseWheel -= OnMouseWheel;
}

static void OnMouseWheel(object sender, MouseWheelEventArgs e)  
{
    SetZoom(sender as UIElement, e.Delta / 1000.0);
}

private static void SetZoom(UIElement elem, double delta)  
{
    if (GetEnableMouseWheel(elem))
    {
        EnsureRenderTransform(elem);
        ScaleTransform xform = (ScaleTransform)elem.RenderTransform;

        double toSet = (double)elem.GetValue(ScaleFactorProperty);
        elem.SetValue(ScaleFactorProperty, toSet + delta);
        toSet = Math.Pow(Math.E,
            (double)elem.GetValue(ScaleFactorProperty));

        xform.ScaleX =
            xform.ScaleY = toSet;
    }
}

private static void EnsureRenderTransform(UIElement elem)  
{
    if (elem.RenderTransform == null ||
        !(elem.RenderTransform is ScaleTransform))
    {
        elem.RenderTransform = new ScaleTransform(1, 1);
    }
}
</code></pre>

<p>I’m using an exponential function to provide a more natural zooming experience. Since zooming out will eventually cause scales &lt; 1, an exponential function causes these changes to appear more linear.  Likewise when zooming in very far, a linear function would appear to slow down the rate of zooming.  </p>

<p>To use the attached behavior, you would do the following:  </p>

<pre><code>&lt;Image Source="flatiron.jpg"  
       RenderTransformOrigin=".5,.5"   
       lcl:Zoom.EnableMouseWheel="True" /&gt;
</code></pre>

<p>Having just started using Blend 3, I decided to turn this Attached Behavior into a Blend Behavior.  This was fairly trivial, and was basically turning the attached properties into regular dependency properties.  Also, instead of having an <code>EnableMouseWheel</code> property, I had to override a couple of methods in the behavior:  </p>

<pre><code>protected override void OnAttached()  
{
    base.OnAttached();

    AssociatedObject.PreviewMouseWheel += OnMouseWheel;
}

protected override void OnDetaching()  
{
    base.OnDetaching();

    AssociatedObject.PreviewMouseWheel -= OnMouseWheel;
}
</code></pre>

<p>The <code>AssociatedObject</code> is strongly typed to be a <code>UIElement</code>, since this <code>Behavior</code> derives from <code>System.Windows.Interactivity.Behavior&lt;UIElement&gt;</code>.  This is used in a slightly more verbose way in XAML, but it is far easier to apply in blend:  </p>

<pre><code>&lt;Image Source="flatiron.jpg" RenderTransformOrigin=".5,.5"&gt;  
    &lt;i:Interaction.Behaviors&gt;
        &lt;lcl:ZoomingBehavior MaximumScale="100"/&gt;
    &lt;/i:Interaction.Behaviors&gt;
&lt;/Image&gt;  
</code></pre>

<p>There you go, an easy way of adding mouse wheel zooming to an element in WPF.  I am not entirely happy with using a behavior to modify the render transform of an element, so maybe in a future post I’ll create a custom control that can be used to wrap content in a zoom-able container.</p>

<p>Here is the source code including both the attached behavior and the blend behavior: <a href='http://files.gettinggui.com/examples/zoombehavior.zip' >ZoomBehavior.zip</a></p>

<p>-AH</p>]]></description><link>http://gettinggui.com/mouse-wheel-zooming-uielements-via-behaviors/</link><guid isPermaLink="false">309a2253-e629-4587-b7cc-554a5bcf4caa</guid><category><![CDATA[behaviors]]></category><category><![CDATA[wpf]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sat, 15 Aug 2009 02:32:16 GMT</pubDate></item><item><title><![CDATA[Using Tasks in .NET 4.0 to retrieve an RSS feed]]></title><description><![CDATA[<p>Building on my <a href='http://gettinggui.com/the-net-4-0-task-api-returning-results-to-calling-thread/' >last post</a>, I am going to use <code>Tasks</code> to retrieve and display RSS feeds in a WPF application.  Since we are retrieving the feeds over the internet, we really don't need to use threads, as it isn't a CPU bound operation. Instead, we can leverage the existing .NET asynchronous event pattern that classes like <code>WebClient</code> already implement.  </p>

<p>The guys over at <a href='http://blogs.msdn.com/b/pfxteam/archive/2009/06/19/9791857.aspx' >Parallel Programming with .NET Blog</a> have a great write-up about how to encapsulate this pattern into a <code>Task</code>.  It seems they've also written extension methods for common BCL objects that implement this pattern in the <a href='http://code.msdn.microsoft.com/windowsdesktop/Samples-for-Parallel-b4b76364' >Parallel Programming Samples</a>.  </p>

<p>Instead of constructing a <code>Task</code> directly, using this pattern, we retrieve a <code>Task</code> from a <code>TaskCompletionSource</code>.  This object contains methods for controlling a <code>Task</code> object that it manages.  After creating a <code>TaskCompletionSource</code>, we execute the asynchronous operation, and report to the <code>TaskCompletionSource</code> when the operation is finished, cancelled, or has an error.  By putting all this logic into a static function, we make it really easy to create a <code>Task</code> to asynchronously retrieve a <code>Stream</code> from a <code>Uri</code>:  </p>

<pre><code>private static Task&lt;Stream&gt; StartReadTask(Uri address)  
{
    WebClient webClient = new WebClient();
    var tcs = new TaskCompletionSource&lt;Stream&gt;(address, 
        TaskCreationOptions.DetachedFromParent);

    OpenReadCompletedEventHandler handler = null;
    handler = (sender, e) =&gt;
    {
        if (e.UserState == tcs)
        {
            if (e.Cancelled)
                tcs.TrySetCanceled();
            else if (e.Error != null)
                tcs.TrySetException(e.Error);
            else
                tcs.TrySetResult(e.Result);
        }

        webClient.OpenReadCompleted -= handler;
    };

    webClient.OpenReadCompleted += handler;
    try 
    {
        webClient.OpenReadAsync(address, tcs); 
    }
    catch
    {
        webClient.OpenReadCompleted -= handler;
        tcs.TrySetCanceled();
        throw;
    }

    return tcs.Task;
}
</code></pre>

<p>As you can see, this function is responsible for actually calling the methods on the <code>WebClient</code> class that we are using to retrieve a <code>Stream</code> to the given <code>Uri</code>.  It returns a <code>Task</code>, but it is slightly different from other <code>Tasks</code> that we are used to using.  For instance, if you try to call <code>Start</code> on it, an exception will be thrown.  This is because the <code>Task</code> isn't encapsulating work, it is more like a reporting mechanism for work being done.  But, we can still use it to determine when the work has completed, like so:  </p>

<pre><code>Uri url = new Uri(uri);  
Task&lt;Stream&gt; t = StartReadTask(url);  
t.ContinueWith(ReadRssStream, TaskContinuationOptions.DetachedFromParent,  
    TaskScheduler.FromCurrentSynchronizationContext());
</code></pre>

<p>Since we are using the <code>TaskScheduler</code> from our current synchronization context (our UI thread), the <code>ReadRssStream</code> method will be run on our UI thread.  In this method, we take the <code>Stream</code> that was retrieved in our <code>Task</code>, and attempts to parse it into RSS or Atom, and adds the items to the <code>ObservableCollection</code> of <code>SyndicationItems</code>:  </p>

<pre><code>private void ReadRssStream(Task&lt;Stream&gt; task)  
{
    if (task.Status == TaskStatus.RanToCompletion)
    {
        XmlReader rdr = XmlReader.Create(task.Result);
        IEnumerable&lt;SyndicationItem&gt; items;
        if (!TryReadRss(rdr, out items))
            TryReadAtom(rdr, out items);

        if (items == null)
        {
            Error = "No Rss feed found at the given url.";
        }
        else
        {
            _rssItems.Clear();
            foreach (var item in items)
                _rssItems.Add(item);
        }
    }
    else if (task.Exception != null)
    {
        Error = "Address Not Found.";
    }
}
</code></pre>

<p>In our <code>Window</code>, we just bind a <code>ListBox</code> to the list of feeds.  The <code>DataTemplate</code> could probably be improved to show a prettier representation of the content, but this worked for this sample app:  </p>

<pre><code>&lt;ListBox x:Name="_feeds"  
         DockPanel.Dock="Left" 
         Width="350"
         ItemsSource="{Binding RssItems}"
         ScrollViewer.HorizontalScrollBarVisibility="Disabled"
         HorizontalContentAlignment="Stretch"
         SelectionChanged="OnSelectedFeedChanged"&gt;
    &lt;ListBox.ItemTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;StackPanel Orientation="Vertical"&gt;
                &lt;TextBlock FontSize="14"
                           FontWeight="Bold"
                           TextTrimming="CharacterEllipsis"
                           Text="{Binding Title.Text}"
                           Margin="0,0,0,4"/&gt;
                &lt;TextBlock TextWrapping="Wrap"
                           Text="{Binding Summary.Text}" /&gt;
            &lt;/StackPanel&gt;
        &lt;/DataTemplate&gt;
    &lt;/ListBox.ItemTemplate&gt;
&lt;/ListBox&gt;  
</code></pre>

<p>I'm really starting to like the new Task API.  It definitely seems to make writing parallel / asynchronous code easier.  Maybe after playing with it a bit more I'll have some complaints, but it certainly has been pretty nice so far!</p>

<p>Since this post is using features new to .NET 4.0, it was built using VS 2010 Beta 1.  </p>

<p>Here is the source: <a href='http://files.gettinggui.com/examples/rssviatasks.zip' >RssViaTasks.zip</a></p>

<p>-AH</p>]]></description><link>http://gettinggui.com/using-tasks-in-net-4-0-to-retrieve-an-rss-feed/</link><guid isPermaLink="false">305b215f-be00-410c-a3b6-970a7c7f34e8</guid><category><![CDATA[.net 4.0]]></category><category><![CDATA[wpf]]></category><dc:creator><![CDATA[Abraham Heidebrecht]]></dc:creator><pubDate>Sat, 08 Aug 2009 16:36:38 GMT</pubDate></item></channel></rss>