<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Jay Harris is Cpt. LoadTest - Programming</title>
    <link>http://www.cptloadtest.com/</link>
    <description>a .net developers blog on improving user experience of humans and coders</description>
    <language>en-us</language>
    <copyright>Jason Harris</copyright>
    <lastBuildDate>Tue, 03 Dec 2013 05:34:25 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.12105.0</generator>
    <managingEditor>jharris@harrisdesigns.com</managingEditor>
    <webMaster>jharris@harrisdesigns.com</webMaster>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Azure Websites are a fantastic method of hosting your own web site. At Arana Software,
we use them often, particularly as test environments for our client projects. We can
quickly spin up a free site that is constantly up-to-date with the latest code using
continuous deployment from the project’s Git repository. Clients are able to see progress
on our development efforts without us having to worry about synchronizing codebases
or managing infrastructure. Since Windows Azure is a Microsoft offering, it is a natural
for handling .NET projects, but JavaScript-based nodejs is also a natural fit and
a first-class citizen on the Azure ecosystem.
</p>
        <h3>Incorporating Grunt
</h3>
        <p>
          <a href="http://gruntjs.com/">Grunt</a> is a JavaScript-based task runner for your
development projects to help you with those repetitive, menial, and mundane tasks
that are necessary for production readiness. This could be running unit tests, compiling
code, image processing, bundling and minification, and more. For our production deployments,
we commonly use Grunt to compile LESS into CSS, CoffeeScript into JavaScript, and
Jade into HTML, taking the code we write and preparing it for browser consumption.
We also use Grunt to optimize these various files for speed through bundling and minification.
The output of this work is done at deployment rather than development, with only the
source code committed into Git and never its optimized output.
</p>
        <h3>Git Deploy and Kudu
</h3>
        <p>
Continuous deployment will automatically update your site with the latest source code
whenever modifications are made to the source repository. This will also work with
Mercurial. There is plenty of existing documentation on <a href="http://www.windowsazure.com/en-us/develop/nodejs/common-tasks/publishing-with-git/">setting
up Git Deploy in Azure</a>, so consider that a prerequisite for this article. However,
Git Deploy, alone, will only take the files as they are in source, and directly deploy
them to the site. If you need to run additional tasks, such as compiling your .NET
source or running Grunt, that is where Kudu comes in.
</p>
        <p>
Kudu is the engine that drives Git deployments in Windows Azure. Untouched, it will
simply synchronize files from Git to your /wwwroot, but it can be easily reconfigured
to execute a deployment command, such as a Windows Command file, a Shell Script, or
a nodejs script. This is enabled through a standardized file named ".deployment".
For Grunt deployment, we are going to execute a Shell Script that will perform npm,
Bower, and Grunt commands in an effort to make our code production-ready. For other
options on .deployment, check out the <a href="https://github.com/projectkudu/kudu/wiki">Kudu
project wiki</a>.
</p>
        <p>
Kudu is also available locally for testing, and to help build out your deployment
scripts. The engine is available as a part of the cross-platform Windows Azure Command
Line Tools, available through npm.
</p>
        <h4>Installing the Azure CLI
</h4>
        <pre class="plain:nocontrols" name="code">npm install azure-cli –-global</pre>
        <p>
We can also use the Azure CLI to generate default Kudu scripts for our nodejs project.
Though we will need to make a few modifications to make the scripts work with Grunt,
it will give us a good start.
</p>
        <pre class="plain:nocontrols" name="code">azure site deploymentscript –-node</pre>
        <p>
This command will generate both our &lt;code&gt;.deployment&lt;/code&gt; and the default
&lt;code&gt;deploy.sh&lt;/code&gt;.
</p>
        <h4>Our .deployment file
</h4>
        <pre class="plain" name="code">[config]
command = bash ./deploy.sh</pre>
        <h3>Customizing deploy.sh for Grunt Deployment
</h3>
        <p>
From <code>.deployment</code>, Kudu will automatically execute our <code>deploy.sh</code> script.
Kudu’s default <code>deploy.sh</code> for a nodejs project will establish the environment
for node and npm as well as some supporting environment variables. It will also include
a "# Deployment" section containing all of the deployment steps. By default,
this will copy your repository contents to your /wwwroot, and then execute <code>npm
install --production</code> against wwwroot, as if installing the application's operating
dependencies. However, under Grunt, we want to execute tasks prior to <code>/wwwroot</code> deployment,
such as executing our Grunt tasks to compile LESS into CSS and CoffeeScript into JavaScript.
By replacing the entire Deployment section with the code below, we instruct Kudu to
perform the following tasks:
</p>
        <ol>
          <li>
Get the latest changes from Git (or Hg). This is done automatically before running
deploy.sh. 
</li>
          <li>
Run <code>npm install</code>, installing all dependencies, including those necessary
for development. 
</li>
          <li>
Optionally run <code>bower install</code>, if bower.json exists. This will update
our client-side JavaScript libraries. 
</li>
          <li>
Optionally run <code>grunt</code>, if Gruntfile.js exists. Below, I have grunt configured
to run the Clean, Common, and Dist tasks, which are LinemanJS's default tasks for
constructing a production-ready build. You can update the script to run whichever
tasks you need, or modify your Gruntfile to set these as the default tasks. 
</li>
          <li>
Finally, sync the contents of the prepared <code>/dist</code> directory to <code>/wwwroot</code>.
It is important to note that this is a KuduSync (similar to RSync), and not just a
copy. We only need to update the files that changed, which includes removing any obsolete
files. 
</li>
        </ol>
        <h4>Our deploy.sh file's Deployment Section
</h4>
        <pre class="plain:firstline[98]" name="code"># Deployment
# ----------

echo Handling node.js grunt deployment.

# 1. Select node version
selectNodeVersion

# 2. Install npm packages
if [ -e "$DEPLOYMENT_SOURCE/package.json" ]; then
  eval $NPM_CMD install
  exitWithMessageOnError "npm failed"
fi

# 3. Install bower packages
if [ -e "$DEPLOYMENT_SOURCE/bower.json" ]; then
  eval $NPM_CMD install bower
  exitWithMessageOnError "installing bower failed"
  ./node_modules/.bin/bower install
  exitWithMessageOnError "bower failed"
fi

# 4. Run grunt
if [ -e "$DEPLOYMENT_SOURCE/Gruntfile.js" ]; then
  eval $NPM_CMD install grunt-cli
  exitWithMessageOnError "installing grunt failed"
  ./node_modules/.bin/grunt --no-color clean common dist
  exitWithMessageOnError "grunt failed"
fi

# 5. KuduSync to Target
"$KUDU_SYNC_CMD" -v 500 -f "$DEPLOYMENT_SOURCE/dist" -t "$DEPLOYMENT_TARGET" -n "$NEXT_MANIFEST_PATH" -p "$PREVIOUS_MANIFEST_PATH" -i ".git;.hg;.deployment;deploy.sh"
exitWithMessageOnError "Kudu Sync to Target failed"</pre>
        <p>
These commands will execute bower and Grunt from local npm installations, rather than
the global space, as Windows Azure does not allow easy access to global installations.
Because bower and Grunt are manually installed based on the existence of bower.json
or Gruntfile.js, they also are not required to be referenced in your own package.json.
Finally, be sure to leave the –no-color flag enabled for Grunt execution, as the Azure
Deployment Logs will stumble when processing the ANSI color codes that are common
on Grunt output.
</p>
        <p>
Assuming that Git Deployment has already been configured, committing these files in
to Git will complete the process. Because the latest changes from Git are pulled before
executing the deployment steps, these two new files (<code>.deployment</code> and <code>deploy.sh</code>)
will be available when Kudu is ready for them.
</p>
        <h3>Troubleshooting
</h3>
        <h4>Long Directory Paths and the 260-Character Path Limit
</h4>
        <p>
Though Azure does a fantastic job of hosting nodejs projects, at the end of the day
Azure is still hosted on the Windows platform, and brings with it Windows limitations.
One of the issues that you will quickly run into under node is the <a href="http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#maxpath">260-Character
Path Limitation</a>. Under nodejs, the dependency tree for a node modules can get
rather deep. And because each dependency module loads up its own dependency modules
under its child folder structure, the folder structure can get rather deep, too. For
example, Lineman requires Testem, which requires Winston, which requires Request;
in the end, the directory tree can lead to ~/node_modules/lineman/node_modules/testem/node_modules/winston/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream,
which combined with the root path structure, can far exceed the 260 limit.
</p>
        <p>
          <i>The Workaround</i>
        </p>
        <p>
To reduce this nesting, make some of these dependencies into first-level dependencies.
With the nodejs dependency model, if a module has already been brought in at a higher
level, it is not repeated in the chain. Thus, if Request is made as a direct dependency
and listed in your project's project.json, it will no longer be nested under Winston,
splitting this single dependency branch in two:
</p>
        <ol>
          <li>
~/node_modules/lineman/node_modules/testem/node_modules/winston 
</li>
          <li>
~/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream 
</li>
        </ol>
        <p>
This is not ideal, but it will solve is a workaround for the Windows file structure
limitations. The element that you must be careful of is with dependency versioning,
as you will need to make sure your <code>package.json</code> references the appropriate
version of your pseudo-dependency; in this case, make sure your <code>package.json</code> references
the same version of Request as is referenced by Winston.
</p>
        <p>
To help find those deep dependencies, use <code>npm list</code>. It will show you
the full graph on the command line, supplying a handy visual indicator.
</p>
        <h4>__dirname vs Process.cwd()
</h4>
        <p>
In the node ecosystem, <code>Process.cwd()</code> is the current working directory
for the node process. There is also a common variable named <code>__dirname</code> that
is created by node; its value is the directory that contained your node script. If
you executed node against a script in the current working directory, then these values
should be the same. Except when they aren't, like in Windows Azure.
</p>
        <p>
In Windows Azure, everything is executed on the system drive, C:. Node and npm live
here, and it appears as though your deployment space does as well. However, this deployment
space is really a mapped directory, coming in from a network share where your files
are persisted. In Azure's node ecosystem, this means that your <code>Process.cwd()</code> is
the C-rooted path, while <code>__dirname</code> is the \\10.whatever-rooted UNC path
to your persisted files. Some Grunt-based tools and plugins (including Lineman) will
fail because that it will reference <code>__dirname</code> files while Grunt's core
is attempting to run tasks with the scope of <code>Process.cwd()</code>; Grunt recognizes
that it's trying to take action on \\10.whatever-rooted files in a C-rooted scope,
and fails because the files are not in a child directory.
</p>
        <p>
          <i>The Workaround</i>
        </p>
        <p>
If you are encountering this issue, reconfigure Grunt to work in the \\10.whatever-rooted
scope. You can do this by setting it's base path to <code>__dirname</code>, overriding
the default <code>Process.cwd()</code>. Within your Gruntfile.js, set the base path
immediately within your module export:
</p>
        <pre class="jscript" name="code">module.exports = function (grunt) {
  grunt.file.setBase(__dirname);
  // Code omitted
}</pre>
        <h4>Unable to find environment variable LINEMAN_MAIN
</h4>
        <p>
If like me, you are using Lineman to build your applications, you will encounter this
issue. Lineman manages Grunt and its configuration, so it prefers that all Grunt tasks
are executed via the Lineman CLI rather than directly executed via the Grunt CLI.
Lineman's Gruntfile.js includes a reference to an environment variable LINEMAN_MAIN,
set by the Lineman CLI, so that Grunt will run under the context of the proper Lineman
installation, which is what causes the failure if Grunt is executed directly.
</p>
        <p>
          <i>The Fix (Because this isn't a hack)</i>
        </p>
        <p>
Your development cycle has been configured to use lineman, so your deployment cycle
should use it, too! Update your <code>deploy.sh</code> Grunt execution to run Lineman
instead of Grunt. Also, since Lineman is referenced in your package.json, we don't
need to install it; it is already there.
</p>
        <p>
Option 1: deploy.sh
</p>
        <pre class="plain:firstline[120]" name="code"># 4. Run grunt
if [ -e "$DEPLOYMENT_SOURCE/Gruntfile.js" ]; then
  ./node_modules/.bin/lineman --no-color grunt clean common dist
  exitWithMessageOnError "lineman failed"
fi</pre>
        <p>
Recommendation: Since Lineman is wrapping Grunt for all of its tasks, consider simplifying <code>lineman
grunt clean common dist</code> into <code>lineman clean build</code>. You will still
need the <code>--no-color</code> flag, so that Grunt will not use ANSI color codes. 
</p>
        <p>
          <i>The Alternate Workaround</i>
        </p>
        <p>
If you don't want to change your <code>deploy.sh</code>—perhaps because you want to
maintain the generic file to handle all things Grunt—then as an alternative you can
update your <code>Gruntfile.js</code> to specify a default value for the missing <code>LINEMAN_MAIN</code> environment
variable. This environment variable is just a string value passed in to node's require
function, so that the right Lineman module can be loaded. Since Lineman is already
included in your <code>package.json</code>, it will already be available in the local <code>/node_modules</code> folder
because of the earlier <code>npm install</code> (deploy.sh, Step #2), and we can pass
'lineman' into <code>require( )</code> to have Grunt load the local Lineman installation.
Lineman will then supply its configuration into Grunt, and the system will proceed
as if you executed Lineman directly.
</p>
        <p>
Option 2: Gruntfile.js
</p>
        <pre class="jscript" name="code">module.exports = function(grunt) {
  grunt.file.setBase(__dirname);
  if (process.env['LINEMAN_MAIN'] === null || process.env['LINEMAN_MAIN'] === undefined) {
    process.env['LINEMAN_MAIN'] = 'lineman';
  }
  require(process.env['LINEMAN_MAIN']).config.grunt.run(grunt);
};</pre>
        <h3>Credits
</h3>
        <p>
Thank you to <a href="http://www.twitter.com/davidebbo">@davidebbo</a>, <a href="http://www.twitter.com/guayan">@guayan</a>, <a href="http://www.twitter.com/amitapl">@amitapl</a>,
and <a href="http://www.twitter.com/dburton">@dburton</a> for helping troubleshoot
Kudu and Grunt Deploy, making this all possible.
</p>
        <h3>Changelog
</h3>
        <p>
2013-12-03: Updated LINEMAN_MAIN Troubleshooting to improve resolution. Rather than
editing deploy.sh to set the environment variable, edit the file to execute Lineman.
This is the proper (and more elegant) solution. [Credit: <a href="http://www.twitter.com/searls">@searls</a>]
</p>
        <div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9b0ba700-7d7e-41fe-8c1b-8c35f6d0d010" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px">Technorati
Tags: <a href="http://technorati.com/tags/Grunt" rel="tag">Grunt</a>,<a href="http://technorati.com/tags/Lineman" rel="tag">Lineman</a>,<a href="http://technorati.com/tags/Node" rel="tag">Node</a>,<a href="http://technorati.com/tags/Azure" rel="tag">Azure</a>,<a href="http://technorati.com/tags/Git" rel="tag">Git</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d" />
      </body>
      <title>Git and Grunt Deploy to Windows Azure</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d.aspx</guid>
      <link>http://www.cptloadtest.com/2013/12/03/Git-And-Grunt-Deploy-To-Windows-Azure.aspx</link>
      <pubDate>Tue, 03 Dec 2013 05:34:25 GMT</pubDate>
      <description>&lt;p&gt;
Azure Websites are a fantastic method of hosting your own web site. At Arana Software,
we use them often, particularly as test environments for our client projects. We can
quickly spin up a free site that is constantly up-to-date with the latest code using
continuous deployment from the project’s Git repository. Clients are able to see progress
on our development efforts without us having to worry about synchronizing codebases
or managing infrastructure. Since Windows Azure is a Microsoft offering, it is a natural
for handling .NET projects, but JavaScript-based nodejs is also a natural fit and
a first-class citizen on the Azure ecosystem.
&lt;/p&gt;
&lt;h3&gt;Incorporating Grunt
&lt;/h3&gt;
&lt;p&gt;
&lt;a href="http://gruntjs.com/"&gt;Grunt&lt;/a&gt; is a JavaScript-based task runner for your
development projects to help you with those repetitive, menial, and mundane tasks
that are necessary for production readiness. This could be running unit tests, compiling
code, image processing, bundling and minification, and more. For our production deployments,
we commonly use Grunt to compile LESS into CSS, CoffeeScript into JavaScript, and
Jade into HTML, taking the code we write and preparing it for browser consumption.
We also use Grunt to optimize these various files for speed through bundling and minification.
The output of this work is done at deployment rather than development, with only the
source code committed into Git and never its optimized output.
&lt;/p&gt;
&lt;h3&gt;Git Deploy and Kudu
&lt;/h3&gt;
&lt;p&gt;
Continuous deployment will automatically update your site with the latest source code
whenever modifications are made to the source repository. This will also work with
Mercurial. There is plenty of existing documentation on &lt;a href="http://www.windowsazure.com/en-us/develop/nodejs/common-tasks/publishing-with-git/"&gt;setting
up Git Deploy in Azure&lt;/a&gt;, so consider that a prerequisite for this article. However,
Git Deploy, alone, will only take the files as they are in source, and directly deploy
them to the site. If you need to run additional tasks, such as compiling your .NET
source or running Grunt, that is where Kudu comes in.
&lt;/p&gt;
&lt;p&gt;
Kudu is the engine that drives Git deployments in Windows Azure. Untouched, it will
simply synchronize files from Git to your /wwwroot, but it can be easily reconfigured
to execute a deployment command, such as a Windows Command file, a Shell Script, or
a nodejs script. This is enabled through a standardized file named &amp;quot;.deployment&amp;quot;.
For Grunt deployment, we are going to execute a Shell Script that will perform npm,
Bower, and Grunt commands in an effort to make our code production-ready. For other
options on .deployment, check out the &lt;a href="https://github.com/projectkudu/kudu/wiki"&gt;Kudu
project wiki&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Kudu is also available locally for testing, and to help build out your deployment
scripts. The engine is available as a part of the cross-platform Windows Azure Command
Line Tools, available through npm.
&lt;/p&gt;
&lt;h4&gt;Installing the Azure CLI
&lt;/h4&gt;
&lt;pre class="plain:nocontrols" name="code"&gt;npm install azure-cli –-global&lt;/pre&gt;
&lt;p&gt;
We can also use the Azure CLI to generate default Kudu scripts for our nodejs project.
Though we will need to make a few modifications to make the scripts work with Grunt,
it will give us a good start.
&lt;/p&gt;
&lt;pre class="plain:nocontrols" name="code"&gt;azure site deploymentscript –-node&lt;/pre&gt;
&lt;p&gt;
This command will generate both our &amp;lt;code&amp;gt;.deployment&amp;lt;/code&amp;gt; and the default
&amp;lt;code&amp;gt;deploy.sh&amp;lt;/code&amp;gt;.
&lt;/p&gt;
&lt;h4&gt;Our .deployment file
&lt;/h4&gt;
&lt;pre class="plain" name="code"&gt;[config]
command = bash ./deploy.sh&lt;/pre&gt;
&lt;h3&gt;Customizing deploy.sh for Grunt Deployment
&lt;/h3&gt;
&lt;p&gt;
From &lt;code&gt;.deployment&lt;/code&gt;, Kudu will automatically execute our &lt;code&gt;deploy.sh&lt;/code&gt; script.
Kudu’s default &lt;code&gt;deploy.sh&lt;/code&gt; for a nodejs project will establish the environment
for node and npm as well as some supporting environment variables. It will also include
a &amp;quot;# Deployment&amp;quot; section containing all of the deployment steps. By default,
this will copy your repository contents to your /wwwroot, and then execute &lt;code&gt;npm
install --production&lt;/code&gt; against wwwroot, as if installing the application's operating
dependencies. However, under Grunt, we want to execute tasks prior to &lt;code&gt;/wwwroot&lt;/code&gt; deployment,
such as executing our Grunt tasks to compile LESS into CSS and CoffeeScript into JavaScript.
By replacing the entire Deployment section with the code below, we instruct Kudu to
perform the following tasks:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Get the latest changes from Git (or Hg). This is done automatically before running
deploy.sh. 
&lt;/li&gt;
&lt;li&gt;
Run &lt;code&gt;npm install&lt;/code&gt;, installing all dependencies, including those necessary
for development. 
&lt;/li&gt;
&lt;li&gt;
Optionally run &lt;code&gt;bower install&lt;/code&gt;, if bower.json exists. This will update
our client-side JavaScript libraries. 
&lt;/li&gt;
&lt;li&gt;
Optionally run &lt;code&gt;grunt&lt;/code&gt;, if Gruntfile.js exists. Below, I have grunt configured
to run the Clean, Common, and Dist tasks, which are LinemanJS's default tasks for
constructing a production-ready build. You can update the script to run whichever
tasks you need, or modify your Gruntfile to set these as the default tasks. 
&lt;/li&gt;
&lt;li&gt;
Finally, sync the contents of the prepared &lt;code&gt;/dist&lt;/code&gt; directory to &lt;code&gt;/wwwroot&lt;/code&gt;.
It is important to note that this is a KuduSync (similar to RSync), and not just a
copy. We only need to update the files that changed, which includes removing any obsolete
files. 
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Our deploy.sh file's Deployment Section
&lt;/h4&gt;
&lt;pre class="plain:firstline[98]" name="code"&gt;# Deployment
# ----------

echo Handling node.js grunt deployment.

# 1. Select node version
selectNodeVersion

# 2. Install npm packages
if [ -e &amp;quot;$DEPLOYMENT_SOURCE/package.json&amp;quot; ]; then
  eval $NPM_CMD install
  exitWithMessageOnError &amp;quot;npm failed&amp;quot;
fi

# 3. Install bower packages
if [ -e &amp;quot;$DEPLOYMENT_SOURCE/bower.json&amp;quot; ]; then
  eval $NPM_CMD install bower
  exitWithMessageOnError &amp;quot;installing bower failed&amp;quot;
  ./node_modules/.bin/bower install
  exitWithMessageOnError &amp;quot;bower failed&amp;quot;
fi

# 4. Run grunt
if [ -e &amp;quot;$DEPLOYMENT_SOURCE/Gruntfile.js&amp;quot; ]; then
  eval $NPM_CMD install grunt-cli
  exitWithMessageOnError &amp;quot;installing grunt failed&amp;quot;
  ./node_modules/.bin/grunt --no-color clean common dist
  exitWithMessageOnError &amp;quot;grunt failed&amp;quot;
fi

# 5. KuduSync to Target
&amp;quot;$KUDU_SYNC_CMD&amp;quot; -v 500 -f &amp;quot;$DEPLOYMENT_SOURCE/dist&amp;quot; -t &amp;quot;$DEPLOYMENT_TARGET&amp;quot; -n &amp;quot;$NEXT_MANIFEST_PATH&amp;quot; -p &amp;quot;$PREVIOUS_MANIFEST_PATH&amp;quot; -i &amp;quot;.git;.hg;.deployment;deploy.sh&amp;quot;
exitWithMessageOnError &amp;quot;Kudu Sync to Target failed&amp;quot;&lt;/pre&gt;
&lt;p&gt;
These commands will execute bower and Grunt from local npm installations, rather than
the global space, as Windows Azure does not allow easy access to global installations.
Because bower and Grunt are manually installed based on the existence of bower.json
or Gruntfile.js, they also are not required to be referenced in your own package.json.
Finally, be sure to leave the –no-color flag enabled for Grunt execution, as the Azure
Deployment Logs will stumble when processing the ANSI color codes that are common
on Grunt output.
&lt;/p&gt;
&lt;p&gt;
Assuming that Git Deployment has already been configured, committing these files in
to Git will complete the process. Because the latest changes from Git are pulled before
executing the deployment steps, these two new files (&lt;code&gt;.deployment&lt;/code&gt; and &lt;code&gt;deploy.sh&lt;/code&gt;)
will be available when Kudu is ready for them.
&lt;/p&gt;
&lt;h3&gt;Troubleshooting
&lt;/h3&gt;
&lt;h4&gt;Long Directory Paths and the 260-Character Path Limit
&lt;/h4&gt;
&lt;p&gt;
Though Azure does a fantastic job of hosting nodejs projects, at the end of the day
Azure is still hosted on the Windows platform, and brings with it Windows limitations.
One of the issues that you will quickly run into under node is the &lt;a href="http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx#maxpath"&gt;260-Character
Path Limitation&lt;/a&gt;. Under nodejs, the dependency tree for a node modules can get
rather deep. And because each dependency module loads up its own dependency modules
under its child folder structure, the folder structure can get rather deep, too. For
example, Lineman requires Testem, which requires Winston, which requires Request;
in the end, the directory tree can lead to ~/node_modules/lineman/node_modules/testem/node_modules/winston/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream,
which combined with the root path structure, can far exceed the 260 limit.
&lt;/p&gt;
&lt;p&gt;
&lt;i&gt;The Workaround&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
To reduce this nesting, make some of these dependencies into first-level dependencies.
With the nodejs dependency model, if a module has already been brought in at a higher
level, it is not repeated in the chain. Thus, if Request is made as a direct dependency
and listed in your project's project.json, it will no longer be nested under Winston,
splitting this single dependency branch in two:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
~/node_modules/lineman/node_modules/testem/node_modules/winston 
&lt;/li&gt;
&lt;li&gt;
~/node_modules/request/node_modules/form-data/node_modules/combined-stream/node_modules/delayed-stream 
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
This is not ideal, but it will solve is a workaround for the Windows file structure
limitations. The element that you must be careful of is with dependency versioning,
as you will need to make sure your &lt;code&gt;package.json&lt;/code&gt; references the appropriate
version of your pseudo-dependency; in this case, make sure your &lt;code&gt;package.json&lt;/code&gt; references
the same version of Request as is referenced by Winston.
&lt;/p&gt;
&lt;p&gt;
To help find those deep dependencies, use &lt;code&gt;npm list&lt;/code&gt;. It will show you
the full graph on the command line, supplying a handy visual indicator.
&lt;/p&gt;
&lt;h4&gt;__dirname vs Process.cwd()
&lt;/h4&gt;
&lt;p&gt;
In the node ecosystem, &lt;code&gt;Process.cwd()&lt;/code&gt; is the current working directory
for the node process. There is also a common variable named &lt;code&gt;__dirname&lt;/code&gt; that
is created by node; its value is the directory that contained your node script. If
you executed node against a script in the current working directory, then these values
should be the same. Except when they aren't, like in Windows Azure.
&lt;/p&gt;
&lt;p&gt;
In Windows Azure, everything is executed on the system drive, C:. Node and npm live
here, and it appears as though your deployment space does as well. However, this deployment
space is really a mapped directory, coming in from a network share where your files
are persisted. In Azure's node ecosystem, this means that your &lt;code&gt;Process.cwd()&lt;/code&gt; is
the C-rooted path, while &lt;code&gt;__dirname&lt;/code&gt; is the \\10.whatever-rooted UNC path
to your persisted files. Some Grunt-based tools and plugins (including Lineman) will
fail because that it will reference &lt;code&gt;__dirname&lt;/code&gt; files while Grunt's core
is attempting to run tasks with the scope of &lt;code&gt;Process.cwd()&lt;/code&gt;; Grunt recognizes
that it's trying to take action on \\10.whatever-rooted files in a C-rooted scope,
and fails because the files are not in a child directory.
&lt;/p&gt;
&lt;p&gt;
&lt;i&gt;The Workaround&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
If you are encountering this issue, reconfigure Grunt to work in the \\10.whatever-rooted
scope. You can do this by setting it's base path to &lt;code&gt;__dirname&lt;/code&gt;, overriding
the default &lt;code&gt;Process.cwd()&lt;/code&gt;. Within your Gruntfile.js, set the base path
immediately within your module export:
&lt;/p&gt;
&lt;pre class="jscript" name="code"&gt;module.exports = function (grunt) {
  grunt.file.setBase(__dirname);
  // Code omitted
}&lt;/pre&gt;
&lt;h4&gt;Unable to find environment variable LINEMAN_MAIN
&lt;/h4&gt;
&lt;p&gt;
If like me, you are using Lineman to build your applications, you will encounter this
issue. Lineman manages Grunt and its configuration, so it prefers that all Grunt tasks
are executed via the Lineman CLI rather than directly executed via the Grunt CLI.
Lineman's Gruntfile.js includes a reference to an environment variable LINEMAN_MAIN,
set by the Lineman CLI, so that Grunt will run under the context of the proper Lineman
installation, which is what causes the failure if Grunt is executed directly.
&lt;/p&gt;
&lt;p&gt;
&lt;i&gt;The Fix (Because this isn't a hack)&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
Your development cycle has been configured to use lineman, so your deployment cycle
should use it, too! Update your &lt;code&gt;deploy.sh&lt;/code&gt; Grunt execution to run Lineman
instead of Grunt. Also, since Lineman is referenced in your package.json, we don't
need to install it; it is already there.
&lt;/p&gt;
&lt;p&gt;
Option 1: deploy.sh
&lt;/p&gt;
&lt;pre class="plain:firstline[120]" name="code"&gt;# 4. Run grunt
if [ -e &amp;quot;$DEPLOYMENT_SOURCE/Gruntfile.js&amp;quot; ]; then
  ./node_modules/.bin/lineman --no-color grunt clean common dist
  exitWithMessageOnError &amp;quot;lineman failed&amp;quot;
fi&lt;/pre&gt;
&lt;p&gt;
Recommendation: Since Lineman is wrapping Grunt for all of its tasks, consider simplifying &lt;code&gt;lineman
grunt clean common dist&lt;/code&gt; into &lt;code&gt;lineman clean build&lt;/code&gt;. You will still
need the &lt;code&gt;--no-color&lt;/code&gt; flag, so that Grunt will not use ANSI color codes. 
&lt;/p&gt;
&lt;p&gt;
&lt;i&gt;The Alternate Workaround&lt;/i&gt;
&lt;/p&gt;
&lt;p&gt;
If you don't want to change your &lt;code&gt;deploy.sh&lt;/code&gt;—perhaps because you want to
maintain the generic file to handle all things Grunt—then as an alternative you can
update your &lt;code&gt;Gruntfile.js&lt;/code&gt; to specify a default value for the missing &lt;code&gt;LINEMAN_MAIN&lt;/code&gt; environment
variable. This environment variable is just a string value passed in to node's require
function, so that the right Lineman module can be loaded. Since Lineman is already
included in your &lt;code&gt;package.json&lt;/code&gt;, it will already be available in the local &lt;code&gt;/node_modules&lt;/code&gt; folder
because of the earlier &lt;code&gt;npm install&lt;/code&gt; (deploy.sh, Step #2), and we can pass
'lineman' into &lt;code&gt;require( )&lt;/code&gt; to have Grunt load the local Lineman installation.
Lineman will then supply its configuration into Grunt, and the system will proceed
as if you executed Lineman directly.
&lt;/p&gt;
&lt;p&gt;
Option 2: Gruntfile.js
&lt;/p&gt;
&lt;pre class="jscript" name="code"&gt;module.exports = function(grunt) {
  grunt.file.setBase(__dirname);
  if (process.env['LINEMAN_MAIN'] === null || process.env['LINEMAN_MAIN'] === undefined) {
    process.env['LINEMAN_MAIN'] = 'lineman';
  }
  require(process.env['LINEMAN_MAIN']).config.grunt.run(grunt);
};&lt;/pre&gt;
&lt;h3&gt;Credits
&lt;/h3&gt;
&lt;p&gt;
Thank you to &lt;a href="http://www.twitter.com/davidebbo"&gt;@davidebbo&lt;/a&gt;, &lt;a href="http://www.twitter.com/guayan"&gt;@guayan&lt;/a&gt;, &lt;a href="http://www.twitter.com/amitapl"&gt;@amitapl&lt;/a&gt;,
and &lt;a href="http://www.twitter.com/dburton"&gt;@dburton&lt;/a&gt; for helping troubleshoot
Kudu and Grunt Deploy, making this all possible.
&lt;/p&gt;
&lt;h3&gt;Changelog
&lt;/h3&gt;
&lt;p&gt;
2013-12-03: Updated LINEMAN_MAIN Troubleshooting to improve resolution. Rather than
editing deploy.sh to set the environment variable, edit the file to execute Lineman.
This is the proper (and more elegant) solution. [Credit: &lt;a href="http://www.twitter.com/searls"&gt;@searls&lt;/a&gt;]
&lt;/p&gt;
&lt;div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9b0ba700-7d7e-41fe-8c1b-8c35f6d0d010" class="wlWriterEditableSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/Grunt" rel="tag"&gt;Grunt&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Lineman" rel="tag"&gt;Lineman&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Node" rel="tag"&gt;Node&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Azure" rel="tag"&gt;Azure&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Git" rel="tag"&gt;Git&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,1a39fd38-1ee4-4c7d-85fd-4b10cb7ea54d.aspx</comments>
      <category>Azure</category>
      <category>Continuous Integration</category>
      <category>JavaScript</category>
      <category>Programming</category>
      <category>Task Automation</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=afcf9193-f07d-4c12-a7e9-f1640a235fd7</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,afcf9193-f07d-4c12-a7e9-f1640a235fd7.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,afcf9193-f07d-4c12-a7e9-f1640a235fd7.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=afcf9193-f07d-4c12-a7e9-f1640a235fd7</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The new season of Come Jam With Us in Ann Arbor is upon us. Come Jam With Us is a
weekly software developers' study group in Ann Arbor for gaining exposure to and learning
about many different software development topics. The group originally started in
late 2008 by a group of developers looking for a way to help each other prepare for
and pass one of the Microsoft .NET exams, and now has hour-long weekly Jam sessions
covering Java, Ruby, .NET, F#, Silverlight, Design Patterns, and more.
</p>
        <p>
The Winter/Spring 2010 Schedule begins this Tuesday, February 2nd, and continues every
week until early May. Come Jam With Us in Ann Arbor, at the offices of SRT Solutions,
206 South 5th Ave, Suite 200. More information, including the prerequisites for each
session (such as what software you need to have pre-installed), is available at the
group's web site, <a href="http://www.comejamwithus.org">http://www.comejamwithus.org</a>.
</p>
        <h3>Come Jam With Us in Ann Arbor
</h3>
        <p>
Every Tuesday, 5:30p-6:30p 
<br />
February 2nd through May 5th, 2010
</p>
        <p>
SRT Solutions 
<br />
206 S. 5th Ave, Suite 200 
<br />
Ann Arbor, MI 48104 | <a title="Map to Come Jam With Us" href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=206+S.+5th+Ave,+Ann+Arbor,+MI+48104&amp;sll=42.619931,-83.788419&amp;sspn=0.008542,0.018926&amp;ie=UTF8&amp;hq=&amp;hnear=206+S+5th+Ave,+Ann+Arbor,+Washtenaw,+Michigan+48104&amp;z=16">Map</a></p>
        <h4>Winter/Spring 2010 Jam Schedule
</h4>
        <p>
2-02 : Django with Darrell Hawley 
<br />
2-09 : ASP.NET MVC2 with Jay Harris 
<br />
2-16 : RESTful Web Services with Mike Smithson 
<br />
2-23 : Erlang with Carl Wright 
<br />
3-02 : MVVM with Brian Genisio 
<br />
3-09 : F# (Part 1 of 3) with Chris Marinos 
<br />
3-16 : F# (Part 2 of 3) with Chris Marinos 
<br />
3-23 : F# (Part 3 of 3) with Chris Marinos 
<br />
3-30 : WPF with Anne Marsan 
<br />
4-06 : Getting to know jQuery with Dennis Burton 
<br />
4-13 : Testing with WatiN with Jay Harris 
<br />
4-20 : Adobe Air with Bill Heitzeg 
<br />
4-27 : ActiveMQ with Becky Glesner 
<br />
5-04 : NoSQL MongoDB with Dennis Burton
</p>
        <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8a5318ea-21d7-481f-92ce-534658626a52" class="wlWriterEditableSmartContent">Technorati
Tags: <a href="http://technorati.com/tags/Ann+Arbor" rel="tag">Ann Arbor</a>,<a href="http://technorati.com/tags/Software" rel="tag">Software</a>,<a href="http://technorati.com/tags/Code+Jam" rel="tag">Code
Jam</a>,<a href="http://technorati.com/tags/Study+Group" rel="tag">Study Group</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=afcf9193-f07d-4c12-a7e9-f1640a235fd7" />
      </body>
      <title>Come Jam With Us in Ann Arbor</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,afcf9193-f07d-4c12-a7e9-f1640a235fd7.aspx</guid>
      <link>http://www.cptloadtest.com/2010/02/01/Come-Jam-With-Us-In-Ann-Arbor.aspx</link>
      <pubDate>Mon, 01 Feb 2010 01:28:41 GMT</pubDate>
      <description>&lt;p&gt;
The new season of Come Jam With Us in Ann Arbor is upon us. Come Jam With Us is a
weekly software developers' study group in Ann Arbor for gaining exposure to and learning
about many different software development topics. The group originally started in
late 2008 by a group of developers looking for a way to help each other prepare for
and pass one of the Microsoft .NET exams, and now has hour-long weekly Jam sessions
covering Java, Ruby, .NET, F#, Silverlight, Design Patterns, and more.
&lt;/p&gt;
&lt;p&gt;
The Winter/Spring 2010 Schedule begins this Tuesday, February 2nd, and continues every
week until early May. Come Jam With Us in Ann Arbor, at the offices of SRT Solutions,
206 South 5th Ave, Suite 200. More information, including the prerequisites for each
session (such as what software you need to have pre-installed), is available at the
group's web site, &lt;a href="http://www.comejamwithus.org"&gt;http://www.comejamwithus.org&lt;/a&gt;.
&lt;/p&gt;
&lt;h3&gt;Come Jam With Us in Ann Arbor
&lt;/h3&gt;
&lt;p&gt;
Every Tuesday, 5:30p-6:30p 
&lt;br /&gt;
February 2nd through May 5th, 2010
&lt;/p&gt;
&lt;p&gt;
SRT Solutions 
&lt;br /&gt;
206 S. 5th Ave, Suite 200 
&lt;br /&gt;
Ann Arbor, MI 48104 | &lt;a title="Map to Come Jam With Us" href="http://maps.google.com/maps?f=q&amp;amp;source=s_q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=206+S.+5th+Ave,+Ann+Arbor,+MI+48104&amp;amp;sll=42.619931,-83.788419&amp;amp;sspn=0.008542,0.018926&amp;amp;ie=UTF8&amp;amp;hq=&amp;amp;hnear=206+S+5th+Ave,+Ann+Arbor,+Washtenaw,+Michigan+48104&amp;amp;z=16"&gt;Map&lt;/a&gt;
&lt;/p&gt;
&lt;h4&gt;Winter/Spring 2010 Jam Schedule
&lt;/h4&gt;
&lt;p&gt;
2-02 : Django with Darrell Hawley 
&lt;br /&gt;
2-09 : ASP.NET MVC2 with Jay Harris 
&lt;br /&gt;
2-16 : RESTful Web Services with Mike Smithson 
&lt;br /&gt;
2-23 : Erlang with Carl Wright 
&lt;br /&gt;
3-02 : MVVM with Brian Genisio 
&lt;br /&gt;
3-09 : F# (Part 1 of 3) with Chris Marinos 
&lt;br /&gt;
3-16 : F# (Part 2 of 3) with Chris Marinos 
&lt;br /&gt;
3-23 : F# (Part 3 of 3) with Chris Marinos 
&lt;br /&gt;
3-30 : WPF with Anne Marsan 
&lt;br /&gt;
4-06 : Getting to know jQuery with Dennis Burton 
&lt;br /&gt;
4-13 : Testing with WatiN with Jay Harris 
&lt;br /&gt;
4-20 : Adobe Air with Bill Heitzeg 
&lt;br /&gt;
4-27 : ActiveMQ with Becky Glesner 
&lt;br /&gt;
5-04 : NoSQL MongoDB with Dennis Burton
&lt;/p&gt;
&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8a5318ea-21d7-481f-92ce-534658626a52" class="wlWriterEditableSmartContent"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/Ann+Arbor" rel="tag"&gt;Ann Arbor&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Software" rel="tag"&gt;Software&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Code+Jam" rel="tag"&gt;Code
Jam&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Study+Group" rel="tag"&gt;Study Group&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=afcf9193-f07d-4c12-a7e9-f1640a235fd7" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,afcf9193-f07d-4c12-a7e9-f1640a235fd7.aspx</comments>
      <category>Events</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=4837e042-3810-4dd1-8460-4c4dc229d5fd</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,4837e042-3810-4dd1-8460-4c4dc229d5fd.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,4837e042-3810-4dd1-8460-4c4dc229d5fd.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=4837e042-3810-4dd1-8460-4c4dc229d5fd</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Have you ever made comments when committing in to source control that you wish you
could take back? Perhaps in a rage, you entered "Jimmy's code was a pile of fermenting
humus that didn't work. So I fixed it!" Now you realize that Jimmy will see it, your
boss is going to see it, and you want to change the comments to something that has
a bit more tact. Or maybe your reason is far less malicious: you identified a major
bug that you just committed, and you would like to update the comment log to say "Don't
use this revision. It has a major bug."
</p>
        <p>
In Subversion, the comments can be updated long after the original commit. Log messages
are just a property on the repository revision.
</p>
        <pre class="nocontrols" name="code">svn propset --revision &lt;REVISION&gt; --revprop &lt;MESSAGE&gt; &lt;URL&gt;</pre>
        <ul>
          <li>
&lt;REVISION&gt; : The revision number of the target log message. 
</li>
          <li>
&lt;MESSAGE&gt; : The value of the new log message, wrapped in quotes if necessary. 
</li>
          <li>
&lt;URL&gt; : The base URL of your repository. Since this applies to a revision property,
rather than a file property, only the base URL of the repository is needed, rather
than a URL directly to a file.</li>
        </ul>
        <p>
Now your malicious revision comment can be overwritten by:
</p>
        <pre class="nocontrols" name="code">svn propset --revision 123 --revprop "Fixed issue #17" http://svnserver/myrepos/</pre>
        <p>
But next time, do try to be nice to Jimmy.
</p>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4cb2c096-64fc-4552-836a-fb52d0af0452" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
Tags: <a href="http://technorati.com/tags/Subversion" rel="tag">Subversion</a>,<a href="http://technorati.com/tags/Quick%20Tips" rel="tag">Quick
Tips</a>,<a href="http://technorati.com/tags/Programming" rel="tag">Programming</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=4837e042-3810-4dd1-8460-4c4dc229d5fd" />
      </body>
      <title>Quick Tips: Changing Subversion Commit Comments</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,4837e042-3810-4dd1-8460-4c4dc229d5fd.aspx</guid>
      <link>http://www.cptloadtest.com/2009/02/27/Quick-Tips-Changing-Subversion-Commit-Comments.aspx</link>
      <pubDate>Fri, 27 Feb 2009 21:54:45 GMT</pubDate>
      <description>&lt;p&gt;
Have you ever made comments when committing in to source control that you wish you
could take back? Perhaps in a rage, you entered "Jimmy's code was a pile of fermenting
humus that didn't work. So I fixed it!" Now you realize that Jimmy will see it, your
boss is going to see it, and you want to change the comments to something that has
a bit more tact. Or maybe your reason is far less malicious: you identified a major
bug that you just committed, and you would like to update the comment log to say "Don't
use this revision. It has a major bug."
&lt;/p&gt;
&lt;p&gt;
In Subversion, the comments can be updated long after the original commit. Log messages
are just a property on the repository revision.
&lt;/p&gt;
&lt;pre class="nocontrols" name="code"&gt;svn propset --revision &amp;lt;REVISION&amp;gt; --revprop &amp;lt;MESSAGE&amp;gt; &amp;lt;URL&amp;gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&amp;lt;REVISION&amp;gt; : The revision number of the target log message. 
&lt;li&gt;
&amp;lt;MESSAGE&amp;gt; : The value of the new log message, wrapped in quotes if necessary. 
&lt;li&gt;
&amp;lt;URL&amp;gt; : The base URL of your repository. Since this applies to a revision property,
rather than a file property, only the base URL of the repository is needed, rather
than a URL directly to a file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Now your malicious revision comment can be overwritten by:
&lt;/p&gt;
&lt;pre class="nocontrols" name="code"&gt;svn propset --revision 123 --revprop "Fixed issue #17" http://svnserver/myrepos/&lt;/pre&gt;
&lt;p&gt;
But next time, do try to be nice to Jimmy.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4cb2c096-64fc-4552-836a-fb52d0af0452" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/Subversion" rel="tag"&gt;Subversion&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Quick%20Tips" rel="tag"&gt;Quick
Tips&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Programming" rel="tag"&gt;Programming&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=4837e042-3810-4dd1-8460-4c4dc229d5fd" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,4837e042-3810-4dd1-8460-4c4dc229d5fd.aspx</comments>
      <category>Programming</category>
      <category>Quick Tips</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=54e51040-72cb-4297-9012-bfaa4caa364f</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,54e51040-72cb-4297-9012-bfaa4caa364f.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,54e51040-72cb-4297-9012-bfaa4caa364f.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=54e51040-72cb-4297-9012-bfaa4caa364f</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
My earlier post on creating custom brushes in Google Syntax Highlighter (<a title="Jay Harris, Blog Post: Extending Language Support in Google Syntax Highlighter" href="http://www.cptloadtest.com/2008/12/10/ExtendingLanguageSupportInGoogleSyntaxHighlighter.aspx">Extending
Language Support in Google Syntax Highlighter</a>) contains a rudimentary brush for
ActionScript. The original is designed for Stone Soup; it is something to get an AS
brush established, but is not meant to be exhaustive. I have revisited the brush and
added some meat. The bush should now supply a more thorough coverage of the language.
A download is provided below.
</p>
        <h3>ActionScript Brush
</h3>
        <pre class="js:nocontrols" name="code">dp.sh.Brushes.ActionScript = function() {
  var keywords = 'and arguments asfunction break call case catch clear ' +
    'continue default do else escape eval false finally for getProperty ' +
    'if ifFrameLoaded in instanceof loop NaN new newline not null or ' +
    'prototype return set super switch targetPath tellTarget this throw ' +
    'trace true try typeof undefined unescape var visible void while with';
  var builtin = '_currentframe _droptarget _framesloaded _global _height ' +
    '_level _name _root _rotation _target _totalframes _url _visible ' +
    '_width _x _xmouse _xscale _y _ymouse _yscale Array Boolean Button ' +
    'bytesLoaded bytesTotal Camera Color Date enabled Error focusEnabled ' +
    'Key LoadVars Math Mouse MovieClip nextFrame Number Object Selection ' +
    'Sound Stage String StyleSheet System TextFormat';
  var funcs = 'addProperty attachMovie attachVideo browse cancel ' +
    'clearInterval clone concat createEmptyMovieClip createTextField ' +
    'dispose draw duplicateMovieClip dynamic equals extends function ' +
    'getInstanceAtDepth gotoAndPlay gotoAndStop identity implements ' +
    'import interface isEmpty isFinite isNAN join length loadClip ' +
    'loadMovie loadMovieNum loadVariables loadVariablesNum merge moveTo ' +
    'on onClipEvent onDragOut onDragOver onEnterFrame onKeyDown onKeyUp ' +
    'onKillFocus onMouseDown onMouseMove onMouseUp onPress onRelease ' +
    'onReleaseOutside onRollOut onRollOver onUnload play pop prevFrame ' +
    'private public push registerClass removeMovieClip reverse rotate ' +
    'scale setEmpty setInterval setProperty shift slice sort sortOn ' +
    'splice startDrag static stopAllSounds stopDrag subtract swapDepths ' +
    'toString toString translate union unloadClip unloadMovie ' +
    'unloadMovieNum unshiftclass unwatch valueOf watch';
  var includes = '#include #initClip #endInitClip';

  this.regexList = [
    {regex: dp.sh.RegexLib.SingleLineCComments, css: 'comment' },
    {regex: dp.sh.RegexLib.MultiLineCComments, css: 'comment' },
    {regex: dp.sh.RegexLib.DoubleQuotedString, css: 'string' },
    {regex: dp.sh.RegexLib.SingleQuotedString, css: 'string' },
    {regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' },
    {regex: new RegExp(this.GetKeywords(funcs), 'gm'), css: 'func' },
    {regex: new RegExp(this.GetKeywords(builtin), 'gm'), css: 'builtin' },
    {regex: new RegExp(this.GetKeywords(includes), 'gm'), css: 'preprocessor'}
  ];
  this.CssClass = 'dp-as';
  this.Style = '.dp-as .func { color: #000099; }' +
               '.dp-as .builtin { color: #990000; }';
}

dp.sh.Brushes.ActionScript.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.ActionScript.Aliases = ['actionscript', 'as'];</pre>
        <h3>Usage
</h3>
        <p>
Upload the Brush javascript file to your Google Syntax Highlighter <em>Scripts</em> directory,
and load the file in unto your HTML with a &lt;SCRIPT&gt; tag with your other brushes.
</p>
        <pre class="html:nogutter:nocontrols" name="code">&lt;script language="javascript"
  src="dp.SyntaxHighlighter/Scripts/shBrushAs.js"&gt;&lt;/script&gt;</pre>
        <p>
Display syntax-highlighted ActionScript using a traditional Google Syntax Highlighter
&lt;PRE&gt; tag, using <em>as</em> or <em>actionscript</em> as the language alias.
</p>
        <pre class="html:nogutter:nocontrols" name="code">&lt;pre name="code" class="as"&gt;
  // Some ActionScript Code
&lt;/pre&gt;</pre>
        <h3>Brush In Action
</h3>
        <pre class="as:nocontrols" name="code">/*
Sample ActionScript for Demo
ActionScript Brush for Google Syntax Highlighter
*/
if (dteDate.getMonth() == intCurrMonth &amp;&amp; intCurrMonth == intOldMonth
    &amp;&amp; intOldYear == intCurrYear) {
  if (dteDate.getDay() == 0 and dteDate.getDate()&gt;1) {
    intYPosition = intYPosition+20;
  }
  duplicateMovieClip ("DayContainer", "DayContainer"+intDate, intDate);
  setProperty ("DayContainer"+intDate, _y, intYPosition);
  setProperty ("DayContainer"+intDate, _x, intXPosition[dteDate.getDay()]);

  } else if (intCurrMonth == 6) {
    if (intDate == 4) {
      clrFColor = new Color("DayContainer"+intDate+".foreground");
      clrFColor.setRGB(0xFF0000);
      clrBColor = new Color("DayContainer"+intDate+".background");
      clrBColor.setRGB(0xFF0000);
    }
  } else if (intCurrMonth == 9) {
    if (intDate == 31) {
      clrFColor = new Color("DayContainer"+intDate+".foreground");
      clrFColor.setRGB(0xFF9922);
      clrBColor = new Color("DayContainer"+intDate+".background");
      clrBColor.setRGB(0xFF9922);
    }
  } else if (intCurrMonth == 10) {
    if (intDate &gt;= 22 &amp;&amp; intDate &lt;= 28 &amp;&amp; dteDate.getDay() == 4) {
      clrFColor = new Color("DayContainer"+intDate+".foreground");
      clrFColor.setRGB(0xFFCC00);
      clrBColor = new Color("DayContainer"+intDate+".background");
      clrBColor.setRGB(0xFFCC00);
    }
  set ("DayContainer"+intDate+":MyDate", new Date(dteDate.getFullYear(),
    dteDate.getMonth(), dteDate.getDate()));
  setProperty ("DayContainer"+intDate, _visible, true);
  intDate++;
  dteDate.setDate(intDate);
}</pre>
        <h3>Download
</h3>
        <blockquote>
          <p>
            <strong>Download:</strong>
            <a title="ActionScript Brush for Google Syntax Highlighter" href="http://www.cptloadtest.com/content/binary/shBrushAs.zip">shBrushAs.zip</a>
            <br />
Includes:
</p>
          <ul>
            <li>
Compressed <em>shBrushAs.js</em> for production.  
</li>
            <li>
Uncompressed <em>shBurshAs.js</em> for debugging.</li>
          </ul>
          <p>
As always, this code is provided with no warranties or guarantees. Use at your own
risk. Your mileage may vary.
</p>
        </blockquote>
        <pre>
          <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a7707e63-5a44-4a88-b27c-59fab2383def" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
Tags: <a href="http://technorati.com/tags/Google%20Code" rel="tag">Google Code</a>,<a href="http://technorati.com/tags/SyntaxHighlighter" rel="tag">SyntaxHighlighter</a>,<a href="http://technorati.com/tags/Syntax%20Highlighter" rel="tag">Syntax
Highlighter</a>,<a href="http://technorati.com/tags/ActionScript" rel="tag">ActionScript</a></div>
        </pre>
        <pre> </pre>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=54e51040-72cb-4297-9012-bfaa4caa364f" />
      </body>
      <title>ActionScript Brush for Google Syntax Highlighter</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,54e51040-72cb-4297-9012-bfaa4caa364f.aspx</guid>
      <link>http://www.cptloadtest.com/2008/12/12/ActionScript-Brush-For-Google-Syntax-Highlighter.aspx</link>
      <pubDate>Fri, 12 Dec 2008 13:25:38 GMT</pubDate>
      <description>&lt;p&gt;
My earlier post on creating custom brushes in Google Syntax Highlighter (&lt;a title="Jay Harris, Blog Post: Extending Language Support in Google Syntax Highlighter" href="http://www.cptloadtest.com/2008/12/10/ExtendingLanguageSupportInGoogleSyntaxHighlighter.aspx"&gt;Extending
Language Support in Google Syntax Highlighter&lt;/a&gt;) contains a rudimentary brush for
ActionScript. The original is designed for Stone Soup; it is something to get an AS
brush established, but is not meant to be exhaustive. I have revisited the brush and
added some meat. The bush should now supply a more thorough coverage of the language.
A download is provided below.
&lt;/p&gt;
&lt;h3&gt;ActionScript Brush
&lt;/h3&gt;
&lt;pre class="js:nocontrols" name="code"&gt;dp.sh.Brushes.ActionScript = function() {
  var keywords = 'and arguments asfunction break call case catch clear ' +
    'continue default do else escape eval false finally for getProperty ' +
    'if ifFrameLoaded in instanceof loop NaN new newline not null or ' +
    'prototype return set super switch targetPath tellTarget this throw ' +
    'trace true try typeof undefined unescape var visible void while with';
  var builtin = '_currentframe _droptarget _framesloaded _global _height ' +
    '_level _name _root _rotation _target _totalframes _url _visible ' +
    '_width _x _xmouse _xscale _y _ymouse _yscale Array Boolean Button ' +
    'bytesLoaded bytesTotal Camera Color Date enabled Error focusEnabled ' +
    'Key LoadVars Math Mouse MovieClip nextFrame Number Object Selection ' +
    'Sound Stage String StyleSheet System TextFormat';
  var funcs = 'addProperty attachMovie attachVideo browse cancel ' +
    'clearInterval clone concat createEmptyMovieClip createTextField ' +
    'dispose draw duplicateMovieClip dynamic equals extends function ' +
    'getInstanceAtDepth gotoAndPlay gotoAndStop identity implements ' +
    'import interface isEmpty isFinite isNAN join length loadClip ' +
    'loadMovie loadMovieNum loadVariables loadVariablesNum merge moveTo ' +
    'on onClipEvent onDragOut onDragOver onEnterFrame onKeyDown onKeyUp ' +
    'onKillFocus onMouseDown onMouseMove onMouseUp onPress onRelease ' +
    'onReleaseOutside onRollOut onRollOver onUnload play pop prevFrame ' +
    'private public push registerClass removeMovieClip reverse rotate ' +
    'scale setEmpty setInterval setProperty shift slice sort sortOn ' +
    'splice startDrag static stopAllSounds stopDrag subtract swapDepths ' +
    'toString toString translate union unloadClip unloadMovie ' +
    'unloadMovieNum unshiftclass unwatch valueOf watch';
  var includes = '#include #initClip #endInitClip';

  this.regexList = [
    {regex: dp.sh.RegexLib.SingleLineCComments, css: 'comment' },
    {regex: dp.sh.RegexLib.MultiLineCComments, css: 'comment' },
    {regex: dp.sh.RegexLib.DoubleQuotedString, css: 'string' },
    {regex: dp.sh.RegexLib.SingleQuotedString, css: 'string' },
    {regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' },
    {regex: new RegExp(this.GetKeywords(funcs), 'gm'), css: 'func' },
    {regex: new RegExp(this.GetKeywords(builtin), 'gm'), css: 'builtin' },
    {regex: new RegExp(this.GetKeywords(includes), 'gm'), css: 'preprocessor'}
  ];
  this.CssClass = 'dp-as';
  this.Style = '.dp-as .func { color: #000099; }' +
               '.dp-as .builtin { color: #990000; }';
}

dp.sh.Brushes.ActionScript.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.ActionScript.Aliases = ['actionscript', 'as'];&lt;/pre&gt;
&lt;h3&gt;Usage
&lt;/h3&gt;
&lt;p&gt;
Upload the Brush javascript file to your Google Syntax Highlighter &lt;em&gt;Scripts&lt;/em&gt; directory,
and load the file in unto your HTML with a &amp;lt;SCRIPT&amp;gt; tag with your other brushes.
&lt;/p&gt;
&lt;pre class="html:nogutter:nocontrols" name="code"&gt;&amp;lt;script language="javascript"
  src="dp.SyntaxHighlighter/Scripts/shBrushAs.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;
Display syntax-highlighted ActionScript using a traditional Google Syntax Highlighter
&amp;lt;PRE&amp;gt; tag, using &lt;em&gt;as&lt;/em&gt; or &lt;em&gt;actionscript&lt;/em&gt; as the language alias.
&lt;/p&gt;
&lt;pre class="html:nogutter:nocontrols" name="code"&gt;&amp;lt;pre name="code" class="as"&amp;gt;
  // Some ActionScript Code
&amp;lt;/pre&amp;gt;&lt;/pre&gt;
&lt;h3&gt;Brush In Action
&lt;/h3&gt;
&lt;pre class="as:nocontrols" name="code"&gt;/*
Sample ActionScript for Demo
ActionScript Brush for Google Syntax Highlighter
*/
if (dteDate.getMonth() == intCurrMonth &amp;amp;&amp;amp; intCurrMonth == intOldMonth
    &amp;amp;&amp;amp; intOldYear == intCurrYear) {
  if (dteDate.getDay() == 0 and dteDate.getDate()&amp;gt;1) {
    intYPosition = intYPosition+20;
  }
  duplicateMovieClip ("DayContainer", "DayContainer"+intDate, intDate);
  setProperty ("DayContainer"+intDate, _y, intYPosition);
  setProperty ("DayContainer"+intDate, _x, intXPosition[dteDate.getDay()]);

  } else if (intCurrMonth == 6) {
    if (intDate == 4) {
      clrFColor = new Color("DayContainer"+intDate+".foreground");
      clrFColor.setRGB(0xFF0000);
      clrBColor = new Color("DayContainer"+intDate+".background");
      clrBColor.setRGB(0xFF0000);
    }
  } else if (intCurrMonth == 9) {
    if (intDate == 31) {
      clrFColor = new Color("DayContainer"+intDate+".foreground");
      clrFColor.setRGB(0xFF9922);
      clrBColor = new Color("DayContainer"+intDate+".background");
      clrBColor.setRGB(0xFF9922);
    }
  } else if (intCurrMonth == 10) {
    if (intDate &amp;gt;= 22 &amp;amp;&amp;amp; intDate &amp;lt;= 28 &amp;amp;&amp;amp; dteDate.getDay() == 4) {
      clrFColor = new Color("DayContainer"+intDate+".foreground");
      clrFColor.setRGB(0xFFCC00);
      clrBColor = new Color("DayContainer"+intDate+".background");
      clrBColor.setRGB(0xFFCC00);
    }
  set ("DayContainer"+intDate+":MyDate", new Date(dteDate.getFullYear(),
    dteDate.getMonth(), dteDate.getDate()));
  setProperty ("DayContainer"+intDate, _visible, true);
  intDate++;
  dteDate.setDate(intDate);
}&lt;/pre&gt;
&lt;h3&gt;Download
&lt;/h3&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Download:&lt;/strong&gt; &lt;a title="ActionScript Brush for Google Syntax Highlighter" href="http://www.cptloadtest.com/content/binary/shBrushAs.zip"&gt;shBrushAs.zip&lt;/a&gt;
&lt;br&gt;
Includes:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Compressed &lt;em&gt;shBrushAs.js&lt;/em&gt; for production.&amp;nbsp; 
&lt;li&gt;
Uncompressed &lt;em&gt;shBurshAs.js&lt;/em&gt; for debugging.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
As always, this code is provided with no warranties or guarantees. Use at your own
risk. Your mileage may vary.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;pre&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:a7707e63-5a44-4a88-b27c-59fab2383def" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/Google%20Code" rel="tag"&gt;Google Code&lt;/a&gt;,&lt;a href="http://technorati.com/tags/SyntaxHighlighter" rel="tag"&gt;SyntaxHighlighter&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Syntax%20Highlighter" rel="tag"&gt;Syntax
Highlighter&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ActionScript" rel="tag"&gt;ActionScript&lt;/a&gt;
&lt;/div&gt;
&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=54e51040-72cb-4297-9012-bfaa4caa364f" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,54e51040-72cb-4297-9012-bfaa4caa364f.aspx</comments>
      <category>Blogging</category>
      <category>Flash</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As I discussed in an earlier post (<a title="Jay Harris, Blog Post: Blog your code using Google Syntax Highlighter" href="http://www.cptloadtest.com/2008/11/24/BlogYourCodeUsingGoogleSyntaxHighlighter.aspx">Blog
your code using Google Syntax Highlighter</a>), Google Syntax Highlighter is a simple
tool that allows bloggers to easily display code in a format that is familiar end
users. The tool renders the code in a very consumable fashion that includes colored
syntax highlighting, line highlighting, and line numbers. Out of the box it supports
most of the common languages of today, and a few from yesterday, but some common languages
are unsupported. Perl, ColdFusion, and Flash's ActionScript all are unloved by Google
Syntax Highlighter, as are many others that you may want to post to your blog. For
these languages, the solution is a custom brush.
</p>
        <h3>Syntax Highlighting Brushes
</h3>
        <p>
For Google Syntax Highlighter, brushes are JavaScript files that govern the syntax
highlighting process, with names following the format of shBrushLanguage.js, such
as shBrushXml.js. Brushes contain information about the keywords, functions, and operators
of a language, as well as the syntax for comments, strings, and other syntax characteristics.
Keyword-level syntax is applied to any specific word in the language, including keywords,
functions, and any word operators, such as <em>and</em>, <em>or</em>, and <em>not</em>.
Regular expressions apply character-level syntax to code, and identifies items such
as character operators, the remainder of an inline comment, or the entire contents
of a comment block. Finally, aliases are defined for the brush; these are the language
aliases that are used within the <em>class</em> attribute of the Google Syntax Highlighter
&lt;PRE&gt; tag. With this information, the brush applies the syntax highlighting
styles according to the CSS defined for each component of the language. 
</p>
        <h3>Breaking Down Brushes
</h3>
        <h4>Decomposing the SQL Brush
</h4>
        <p>
In JavaScript, everything is an object that can be assigned to a variable, whether
its a number, string, function, or class. Brushes are each a delegate function. The
variable name of the brush must match <em>dp.sh.Brushes.SomeLanguage</em>.
</p>
        <pre class="js:nocontrols:firstline[1]" name="code">dp.sh.Brushes.Sql = function() {</pre>
        <p>
Next, define the list of keywords for applying syntax highlighting. Each list is not
an array, but rather a single-space delimited string of keywords that will be highlighted.
Also, multiple keyword lists can exist, such as one list for function names, another
for keywords, and perhaps another for types, and unique styling can be applied to
each grouping (we'll get to styling a little later). 
</p>
        <pre class="js:nocontrols:firstline[2]" name="code">  var funcs = 'abs avg case cast coalesce convert count current_timestamp ' +
    'current_user day isnull left lower month nullif replace right ' +
    'session_user space substring sum system_user upper user year';

  var keywords = 'absolute action add after alter as asc at authorization ' +
    'begin bigint binary bit by cascade char character check checkpoint ' +
    'close collate column commit committed connect connection constraint ' +
    'contains continue create cube current current_date current_time ' +
    'cursor database date deallocate dec decimal declare default delete ' +
    'desc distinct double drop dynamic else end end-exec escape except ' +
    'exec execute false fetch first float for force foreign forward free ' +
    'from full function global goto grant group grouping having hour ' +
    'ignore index inner insensitive insert instead int integer intersect ' +
    'into is isolation key last level load local max min minute modify ' +
    'move name national nchar next no numeric of off on only open option ' +
    'order out output partial password precision prepare primary prior ' +
    'privileges procedure public read real references relative repeatable ' +
    'restrict return returns revoke rollback rollup rows rule schema ' +
    'scroll second section select sequence serializable set size smallint ' +
    'static statistics table temp temporary then time timestamp to top ' +
    'transaction translation trigger true truncate uncommitted union ' +
    'unique update values varchar varying view when where with work';

  var operators = 'all and any between cross in join like not null or ' +
    'outer some';</pre>
        <p>
Following the keyword definitions is the Regular Expression pattern and Style definition
object list. The list, <em>this.regexList</em>, is an array of pattern/style objects: <em>{regex:
regexPattern, css: classString}</em>. The <em>regexPattern</em> is a JavaScript <em>RegExp</em> object,
and defines the pattern to match in the source code; this pattern can be created using
one of three options within Google Syntax Highlighter. 
</p>
        <dl>
          <dt>Predefined Patterns </dt>
          <dd>Within Google Syntax Highlighter, <em>dp.sh.RegexLib</em> contains five predefined
regular expression patterns. <em>MultiLineCComments</em> is used for any language
that uses C-style multi-line comment blocks: <em>/* my comment block */</em>. <em>SingleLineCComments</em> is
used for any language that uses C-style single line or inline comments: <em>// my
comment</em>. <em>SingleLinePerlComments</em> applies for Perl-style single line comments: <em>#
my comment</em>. <em>DoubleQuotedString</em> identifies any string wrapped in double-quotes
and <em>SingleQuotedString</em> identifies strings wrapped in single-quotes. These
options are used in place of creating a new instance of the <em>RegExp</em> object. 
</dd>
          <dt>Keyword Patterns </dt>
          <dd>Google Syntax Highlighter has a <em>GetKeywords(string)</em> function which will
build a pattern string based on one of the brush's defined keyword strings. However,
this is only the pattern string, and not the <em>RegExp</em> object. Pass this value
into the <em>RegExp</em> constructor: <em>new RegExp(this.GetKeyword(keywords), 'gmi')</em></dd>
          <dt>Custom Pattern Definition </dt>
          <dd>Create a new <em>RegExp</em> object using a custom pattern. For example, use <em>new
RegExp('--(.*)$', 'gm')</em> to match all Sql comments, such as <em>--my comment</em>.</dd>
        </dl>
        <p>
For these pattern/style objects, the regular expression pattern is followed by the
name of the CSS class to apply to any regular expression matches. The style sheet
packaged with Google Syntax Highlighter, SyntaxHighlighter.css, already defines the
many CSS classes used by GSH; place the additional styles for your custom brushes
within this file, in a new file, in your HTML, or defined them within the brush using
JavaScript.
</p>
        <pre class="js:nocontrols:firstline[27]" name="code">  this.regexList = [
    {regex: new RegExp('--(.*)$', 'gm'), css: 'comment'},
    {regex: dp.sh.RegexLib.DoubleQuotedString, css: 'string'},
    {regex: dp.sh.RegexLib.SingleQuotedString, css: 'string'},
    {regex: new RegExp(this.GetKeywords(funcs), 'gmi'), css: 'func'},
    {regex: new RegExp(this.GetKeywords(operators), 'gmi'), css: 'op'},
    {regex: new RegExp(this.GetKeywords(keywords), 'gmi'), css: 'keyword'}
  ];</pre>
        <p>
The delegate definition ends with any style specifications. Apply a style sheet to
the entire code block using <em>this.CssClass</em>. Also, as mentioned above, the
brush can define custom CSS using this.Style as an alternative to placing the CSS
in HTML or a CSS file. When finished, close the delegate.
</p>
        <pre class="js:nocontrols:firstline[36]" name="code">  this.CssClass = 'dp-sql';
  this.Style = '.dp-sql .func { color: #ff1493; }' +
    '.dp-sql .op { color: #808080; }'; }
</pre>
        <p>
The final component of a Brush, set outside of your delegate, contains the prototype
declaration and any aliases to apply to the Brush. Aliases consist of a string array
(a real array this time, not a space-delimited string) of language aliases to use,
such as ['c#','c-sharp','csharp']. Alias values must be unique across all defined
brushes that you have included into your site.
</p>
        <pre class="js:nocontrols:firstline[40]" name="code">dp.sh.Brushes.Sql.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.Sql.Aliases = ['sql'];</pre>
        <h3>Making a Custom Brush (for ActionScript) 
</h3>
        <p>
I like rich media applications, such as those developed in Flash or Silverlight. I
was surprised when I found that Google Syntax Highlighter does not ship with an ActionScript
brush, and more surprised when I found out that no one has written one, yet. So, using
the methods from above, I created one. This isn't meant to be an exhaustive brush,
but more like <a href="http://en.wikipedia.org/wiki/Stone_soup">Stone Soup</a>. It's
a start. Please feel free to add to it.
</p>
        <pre class="js" name="code">dp.sh.Brushes.ActionScript = function() {

  var keywords = 'and break case catch class continue default do dynamic else ' +
    'extends false finally for if implements import in interface NaN new not ' +
    'null or private public return static super switch this throw true try ' +
    'undefined var void while with';

  this.regexList = [{regex: dp.sh.RegexLib.SingleLineCComments, css: 'comment'},
    {regex: dp.sh.RegexLib.MultiLineCComments, css: 'comment'},
    {regex: dp.sh.RegexLib.DoubleQuotedString, css: 'string'},
    {regex: dp.sh.RegexLib.SingleQuotedString, css: 'string'},
    {regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword'}];

    this.CssClass = 'dp-as';
}

dp.sh.Brushes.ActionScript.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.ActionScript.Aliases = ['actionscript', 'as'];</pre>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:51b61cce-ee33-4c5c-9de4-a3c6cf350c46" style="margin: 0px; padding: 0px; display: inline;">Technorati
Tags: <a href="http://technorati.com/tags/Syntax%20Highlighter" rel="tag">Syntax Highlighter</a>,<a href="http://technorati.com/tags/SyntaxHighlighter" rel="tag">SyntaxHighlighter</a>,<a href="http://technorati.com/tags/Google%20Code" rel="tag">Google
Code</a>,<a href="http://technorati.com/tags/ActionScript" rel="tag">ActionScript</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9" />
      </body>
      <title>Extending Language Support in Google Syntax Highlighter</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9.aspx</guid>
      <link>http://www.cptloadtest.com/2008/12/10/Extending-Language-Support-In-Google-Syntax-Highlighter.aspx</link>
      <pubDate>Wed, 10 Dec 2008 21:47:27 GMT</pubDate>
      <description>&lt;p&gt;
As I discussed in an earlier post (&lt;a title="Jay Harris, Blog Post: Blog your code using Google Syntax Highlighter" href="http://www.cptloadtest.com/2008/11/24/BlogYourCodeUsingGoogleSyntaxHighlighter.aspx"&gt;Blog
your code using Google Syntax Highlighter&lt;/a&gt;), Google Syntax Highlighter is a simple
tool that allows bloggers to easily display code in a format that is familiar end
users. The tool renders the code in a very consumable fashion that includes colored
syntax highlighting, line highlighting, and line numbers. Out of the box it supports
most of the common languages of today, and a few from yesterday, but some common languages
are unsupported. Perl, ColdFusion, and Flash's ActionScript all are unloved by Google
Syntax Highlighter, as are many others that you may want to post to your blog. For
these languages, the solution is a custom brush.
&lt;/p&gt;
&lt;h3&gt;Syntax Highlighting Brushes
&lt;/h3&gt;
&lt;p&gt;
For Google Syntax Highlighter, brushes are JavaScript files that govern the syntax
highlighting process, with names following the format of shBrushLanguage.js, such
as shBrushXml.js. Brushes contain information about the keywords, functions, and operators
of a language, as well as the syntax for comments, strings, and other syntax characteristics.
Keyword-level syntax is applied to any specific word in the language, including keywords,
functions, and any word operators, such as &lt;em&gt;and&lt;/em&gt;, &lt;em&gt;or&lt;/em&gt;, and &lt;em&gt;not&lt;/em&gt;.
Regular expressions apply character-level syntax to code, and identifies items such
as character operators, the remainder of an inline comment, or the entire contents
of a comment block. Finally, aliases are defined for the brush; these are the language
aliases that are used within the &lt;em&gt;class&lt;/em&gt; attribute of the Google Syntax Highlighter
&amp;lt;PRE&amp;gt; tag. With this information, the brush applies the syntax highlighting
styles according to the CSS defined for each component of the language. 
&lt;/p&gt;
&lt;h3&gt;Breaking Down Brushes
&lt;/h3&gt;
&lt;h4&gt;Decomposing the SQL Brush
&lt;/h4&gt;
&lt;p&gt;
In JavaScript, everything is an object that can be assigned to a variable, whether
its a number, string, function, or class. Brushes are each a delegate function. The
variable name of the brush must match &lt;em&gt;dp.sh.Brushes.SomeLanguage&lt;/em&gt;.
&lt;/p&gt;
&lt;pre class="js:nocontrols:firstline[1]" name="code"&gt;dp.sh.Brushes.Sql = function() {&lt;/pre&gt;
&lt;p&gt;
Next, define the list of keywords for applying syntax highlighting. Each list is not
an array, but rather a single-space delimited string of keywords that will be highlighted.
Also, multiple keyword lists can exist, such as one list for function names, another
for keywords, and perhaps another for types, and unique styling can be applied to
each grouping (we'll get to styling a little later). 
&lt;/p&gt;
&lt;pre class="js:nocontrols:firstline[2]" name="code"&gt;  var funcs = 'abs avg case cast coalesce convert count current_timestamp ' +
    'current_user day isnull left lower month nullif replace right ' +
    'session_user space substring sum system_user upper user year';

  var keywords = 'absolute action add after alter as asc at authorization ' +
    'begin bigint binary bit by cascade char character check checkpoint ' +
    'close collate column commit committed connect connection constraint ' +
    'contains continue create cube current current_date current_time ' +
    'cursor database date deallocate dec decimal declare default delete ' +
    'desc distinct double drop dynamic else end end-exec escape except ' +
    'exec execute false fetch first float for force foreign forward free ' +
    'from full function global goto grant group grouping having hour ' +
    'ignore index inner insensitive insert instead int integer intersect ' +
    'into is isolation key last level load local max min minute modify ' +
    'move name national nchar next no numeric of off on only open option ' +
    'order out output partial password precision prepare primary prior ' +
    'privileges procedure public read real references relative repeatable ' +
    'restrict return returns revoke rollback rollup rows rule schema ' +
    'scroll second section select sequence serializable set size smallint ' +
    'static statistics table temp temporary then time timestamp to top ' +
    'transaction translation trigger true truncate uncommitted union ' +
    'unique update values varchar varying view when where with work';

  var operators = 'all and any between cross in join like not null or ' +
    'outer some';&lt;/pre&gt;
&lt;p&gt;
Following the keyword definitions is the Regular Expression pattern and Style definition
object list. The list, &lt;em&gt;this.regexList&lt;/em&gt;, is an array of pattern/style objects: &lt;em&gt;{regex:
regexPattern, css: classString}&lt;/em&gt;. The &lt;em&gt;regexPattern&lt;/em&gt; is a JavaScript &lt;em&gt;RegExp&lt;/em&gt; object,
and defines the pattern to match in the source code; this pattern can be created using
one of three options within Google Syntax Highlighter. 
&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Predefined Patterns &lt;/dt&gt;
&lt;dd&gt;Within Google Syntax Highlighter, &lt;em&gt;dp.sh.RegexLib&lt;/em&gt; contains five predefined
regular expression patterns. &lt;em&gt;MultiLineCComments&lt;/em&gt; is used for any language
that uses C-style multi-line comment blocks: &lt;em&gt;/* my comment block */&lt;/em&gt;. &lt;em&gt;SingleLineCComments&lt;/em&gt; is
used for any language that uses C-style single line or inline comments: &lt;em&gt;// my
comment&lt;/em&gt;. &lt;em&gt;SingleLinePerlComments&lt;/em&gt; applies for Perl-style single line comments: &lt;em&gt;#
my comment&lt;/em&gt;. &lt;em&gt;DoubleQuotedString&lt;/em&gt; identifies any string wrapped in double-quotes
and &lt;em&gt;SingleQuotedString&lt;/em&gt; identifies strings wrapped in single-quotes. These
options are used in place of creating a new instance of the &lt;em&gt;RegExp&lt;/em&gt; object. 
&lt;/dd&gt;
&lt;dt&gt;Keyword Patterns &lt;/dt&gt;
&lt;dd&gt;Google Syntax Highlighter has a &lt;em&gt;GetKeywords(string)&lt;/em&gt; function which will
build a pattern string based on one of the brush's defined keyword strings. However,
this is only the pattern string, and not the &lt;em&gt;RegExp&lt;/em&gt; object. Pass this value
into the &lt;em&gt;RegExp&lt;/em&gt; constructor: &lt;em&gt;new RegExp(this.GetKeyword(keywords), 'gmi')&lt;/em&gt; 
&lt;/dd&gt;
&lt;dt&gt;Custom Pattern Definition &lt;/dt&gt;
&lt;dd&gt;Create a new &lt;em&gt;RegExp&lt;/em&gt; object using a custom pattern. For example, use &lt;em&gt;new
RegExp('--(.*)$', 'gm')&lt;/em&gt; to match all Sql comments, such as &lt;em&gt;--my comment&lt;/em&gt;.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;
For these pattern/style objects, the regular expression pattern is followed by the
name of the CSS class to apply to any regular expression matches. The style sheet
packaged with Google Syntax Highlighter, SyntaxHighlighter.css, already defines the
many CSS classes used by GSH; place the additional styles for your custom brushes
within this file, in a new file, in your HTML, or defined them within the brush using
JavaScript.
&lt;/p&gt;
&lt;pre class="js:nocontrols:firstline[27]" name="code"&gt;  this.regexList = [
    {regex: new RegExp('--(.*)$', 'gm'), css: 'comment'},
    {regex: dp.sh.RegexLib.DoubleQuotedString, css: 'string'},
    {regex: dp.sh.RegexLib.SingleQuotedString, css: 'string'},
    {regex: new RegExp(this.GetKeywords(funcs), 'gmi'), css: 'func'},
    {regex: new RegExp(this.GetKeywords(operators), 'gmi'), css: 'op'},
    {regex: new RegExp(this.GetKeywords(keywords), 'gmi'), css: 'keyword'}
  ];&lt;/pre&gt;
&lt;p&gt;
The delegate definition ends with any style specifications. Apply a style sheet to
the entire code block using &lt;em&gt;this.CssClass&lt;/em&gt;. Also, as mentioned above, the
brush can define custom CSS using this.Style as an alternative to placing the CSS
in HTML or a CSS file. When finished, close the delegate.
&lt;/p&gt;
&lt;pre class="js:nocontrols:firstline[36]" name="code"&gt;  this.CssClass = 'dp-sql';
  this.Style = '.dp-sql .func { color: #ff1493; }' +
    '.dp-sql .op { color: #808080; }'; }
&lt;/pre&gt;
&lt;p&gt;
The final component of a Brush, set outside of your delegate, contains the prototype
declaration and any aliases to apply to the Brush. Aliases consist of a string array
(a real array this time, not a space-delimited string) of language aliases to use,
such as ['c#','c-sharp','csharp']. Alias values must be unique across all defined
brushes that you have included into your site.
&lt;/p&gt;
&lt;pre class="js:nocontrols:firstline[40]" name="code"&gt;dp.sh.Brushes.Sql.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.Sql.Aliases = ['sql'];&lt;/pre&gt;
&lt;h3&gt;Making a Custom Brush (for ActionScript) 
&lt;/h3&gt;
&lt;p&gt;
I like rich media applications, such as those developed in Flash or Silverlight. I
was surprised when I found that Google Syntax Highlighter does not ship with an ActionScript
brush, and more surprised when I found out that no one has written one, yet. So, using
the methods from above, I created one. This isn't meant to be an exhaustive brush,
but more like &lt;a href="http://en.wikipedia.org/wiki/Stone_soup"&gt;Stone Soup&lt;/a&gt;. It's
a start. Please feel free to add to it.
&lt;/p&gt;
&lt;pre class="js" name="code"&gt;dp.sh.Brushes.ActionScript = function() {

  var keywords = 'and break case catch class continue default do dynamic else ' +
    'extends false finally for if implements import in interface NaN new not ' +
    'null or private public return static super switch this throw true try ' +
    'undefined var void while with';

  this.regexList = [{regex: dp.sh.RegexLib.SingleLineCComments, css: 'comment'},
    {regex: dp.sh.RegexLib.MultiLineCComments, css: 'comment'},
    {regex: dp.sh.RegexLib.DoubleQuotedString, css: 'string'},
    {regex: dp.sh.RegexLib.SingleQuotedString, css: 'string'},
    {regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword'}];

    this.CssClass = 'dp-as';
}

dp.sh.Brushes.ActionScript.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.ActionScript.Aliases = ['actionscript', 'as'];&lt;/pre&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:51b61cce-ee33-4c5c-9de4-a3c6cf350c46" style="margin: 0px; padding: 0px; display: inline;"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/Syntax%20Highlighter" rel="tag"&gt;Syntax Highlighter&lt;/a&gt;,&lt;a href="http://technorati.com/tags/SyntaxHighlighter" rel="tag"&gt;SyntaxHighlighter&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Google%20Code" rel="tag"&gt;Google
Code&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ActionScript" rel="tag"&gt;ActionScript&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,e54fb1b0-d25c-4f0b-a4cd-eefa8c3715e9.aspx</comments>
      <category>Blogging</category>
      <category>Flash</category>
      <category>JavaScript</category>
      <category>Programming</category>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=71ba8b42-6bcc-49e3-9f2f-48de47d8f275</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,71ba8b42-6bcc-49e3-9f2f-48de47d8f275.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,71ba8b42-6bcc-49e3-9f2f-48de47d8f275.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=71ba8b42-6bcc-49e3-9f2f-48de47d8f275</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Did you know that <em>yourdomain.com</em> and <em>www.yourdomain.com</em> are actually
different sites? Are they both serving the same content? If so, it may be negatively
impacting your search engine rankings.
</p>
        <h3>Subdomains and the Synonymous 'WWW'
</h3>
        <p>
Sub-domains are the prefix to a domain (<em>http://subdomain.yourdomain.com</em>),
and are treated by browsers, computers, domain name systems (DNS), search engines,
and the general internet as separate, individual web sites. Google's primary web presence, <a href="http://www.google.com">http://www.google.com</a>,
is very different than Google Mail, <a href="http://mail.google.com">http://mail.google.com</a>,
or Google Documents, <a href="http://docs.google.com">http://docs.google.com</a>,
all because of subdomains. However, what many do not realize is that <em>www</em> is,
itself, a subdomain.
</p>
        <p>
A domain, on its own, requires no <em>www</em> prefix; a subdomain-less <em>http://yourdomain.com</em> should
be sufficient for serving up a web site. And since <em>www</em> is a subdomain, dropping
the prefix could potentially return a different response. There are some sites that
will fail to return without the prefix, and some sites that fail with it, but the
most common practice is that the <em>www</em> subdomain is synonymous for no subdomain
at all.
</p>
        <h3>The Synonymous WWW and SEO
</h3>
        <p>
The issue with having two synonymous URLs (<em>http://yourdomain.com</em> and <em>http://www.yourdomain.com</em>)
is that search engines may interpret them as separate sites, even if they are serving
the same content. The two addresses are technically independent and are potentially
serving unique content; to a cautious search engine, even if pages appear to contain
the same content, there may be something different under the covers. This means your
audience's search results returns two entries for the same content. Some users will
happen to click on <em>yourdomain.com</em> while others navigate to <em>www.yourdomain.com</em>,
splitting your traffic, your page hits, your search ranking between two sites, unnecessarily.
</p>
        <p>
HTTP Redirects will cure the issue. If you access <a href="http://google.com">http://google.com</a>,
your browser is instantly redirected to <a href="http://www.google.com">http://www.google.com</a>.
This is done through a HTTP 301 permanent redirect. Search Spiders recognize HTTP
response codes, and understand the 301 as a "use this other URL instead" command.
Many search engines, such as Google, will then update all page entries for the original
URI (<em>http://yourdomain.com</em>) and replace it with the 301's destination URL
(<em>http://www.yourdomain.com</em>). If there is already an entry for the destination
URL, the two entries will be merged together. The search entries for <em>yourdomain.com</em> and <em>www.yourdomain.com</em> will
now share traffic, share page hits, and share search ranking. Instead of having two
entries on the second and third pages of search results, combining these entries may
be just enough to place you on the first page of results.
</p>
        <blockquote>In addition to combining search entries for subdomains, you can also combine
root-level domains through HTTP 301. On this site, in addition to adding the <em>www</em> prefix
if no subdomain is specified, <a href="http://captainloadtest.com">captainloadtest.com</a> will
HTTP 301 redirect to <a href="http://www.cptloadtest.com">www.cptloadtest.com</a>.</blockquote>
        <h3>Combining the Synonyms
</h3>
        <p>
We need a way to implement an HTTP 301 redirect at the domain level for all requests
to a site; however, often we are using applications that may not grant us access to
the source, or we don't have the access into IIS through our host to set up redirects
for ourselves. <a href="http://www.cptloadtest.com/2008/11/11/URLRewritePart2HTTP301MovedPermanently.aspx">URL
Rewrite, Part 2</a> covers a great <a href="http://www.pluralsight.com/community/blogs/fritz/archive/2004/07/21/1651.aspx">drop-in
redirect module</a> by <a href="http://www.pluralsight.com/community/blogs/fritz/">Fritz
Onion</a> that uses a stand-alone assembly with a few additions in web.config to HTTP
301 redirect paths in your domain (it also supports HTTP 302 redirects). This module
is perfect for converting a WordPress blog post URL, such as <a href="http://www.cptloadtest.com/?p=56">cptloadtest.com/?p=56</a>,
to a DasBlog blog post URL like <a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx">cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx</a>.
However, to redirect domains and subdomains, the module must go a step further and
redirect based on matches against the entire URL, such as directing http:// to https://
or captainloadtest.com to cptloadtest.com, which it does not support. It's time for
some modifications.
</p>
        <pre class="csharp:nocontrols:linenumber[20]" name="code">private void OnBeginRequest(object src, EventArgs e) {
  HttpApplication app = src as HttpApplication;
  string reqUrl = app.Request.Url.AbsoluteUri;
  redirections redirs
    = (redirections) ConfigurationManager.GetSection("redirections");

  foreach (Add a in redirs.Adds) {
    Regex regex = new Regex(a.targetUrl, RegexOptions.IgnoreCase);
    if (regex.IsMatch(reqUrl)) {
      string targetUrl = regex.Replace(reqUrl, a.destinationUrl, 1);

      if (a.permanent) {
        app.Response.StatusCode = 301; // make a permanent redirect
        app.Response.AddHeader("Location", targetUrl);
        app.Response.End();
      }
      else
        app.Response.Redirect(targetUrl);

      break;
    }    
  }
}</pre>
        <p>
By converting <em>app.Request.RawURL</em> to <em>app.Request.AbsoluteUri</em>, the
regular expression will now match against the entire URL, rather than just the requested
path. There is one downside to this change: the value is the actual path processed,
not necessarily what was in the originally requested URL. To this effect, the value
of <em>AbsoluteUri</em> for requesting <a href="http://www.cptloadtest.com?p=56">http://www.cptloadtest.com?p=56</a> is
actually <a href="http://www.cptloadtest.com/default.aspx?p=56">http://www.cptloadtest.com/default.aspx?p=56</a>;
by requesting the root directory, the default page is being processed, not the directory
itself, so <em>default.aspx</em> is added to the URL. Keep this in mind when setting
up your redirection rules. Also, the original code converted the URL to lower case;
with my modifications, I chose to maintain the case of the URL, since sometimes case
matters, and instead ignore case in the regular expression match using <em>RegexOptions.IgnoreCase</em>.
Finally, I made some other minor enhancements, like using the ConfigurationManager,
since ConfigurationSettings is now obsolete, and reusing the matching Regex instance
for replacements.
</p>
        <blockquote>
          <p>
            <strong>Download:</strong>
            <a href="http://www.cptloadtest.com/content/binary/RedirectModule.zip">RedirectModule.zip</a>
          </p>
          <p>
Includes:
</p>
          <ul>
            <li>
Source code for the drop-in Redirect Module 
</li>
            <li>
Sample web.config that uses the module 
</li>
            <li>
Compiled version of redirectmodule.dll</li>
          </ul>
          <p>
The code is based on the original <a href="http://www.pluralsight.com/community/blogs/fritz/archive/2004/07/21/1651.aspx">Redirect
Module</a> by <a href="http://www.pluralsight.com/community/blogs/fritz/default.aspx">Fritz
Onion</a> and the <a href="http://alt.pluralsight.com/wiki/default.aspx/Craig/XmlSerializerSectionHandler.html">Xml
Serializer Section Handler</a> by <a href="http://www.pluralsight.com/community/blogs/craig/default.aspx">Craig
Andera</a>. As always, this code is provided with no warranties or guarantees. Use
at your own risk. Your mileage may vary. Thanks to Fritz Onion for the original work,
and allowing me extend his code further.
</p>
        </blockquote>
        <p>
The usage is the same as Fritz Onion's original module. Drop the assembly into your
site's bin, and place a few lines into the web.config. The example below contains
the rules as they would apply to this site, 301 redirecting <a href="http://www.captainloadtest.com">http://www.captainloadtest.com</a> to <a href="http://www.cptloadtest.com">http://www.cptloadtest.com</a>,
and adding the <em>www</em> subdomain to any domain requests that have no subdomain.
</p>
        <pre class="xml:nocontrols:linenumber[20]" name="code">&lt;?xml version="1.0"?&gt;
&lt;configuration&gt;
  &lt;configSections&gt;
    &lt;section name="redirections"
      type="Pluralsight.Website.XmlSerializerSectionHandler, redirectmodule" /&gt;
  &lt;/configSections&gt;
  &lt;!-- Redirect Rules --&gt;
  &lt;redirections type="Pluralsight.Website.redirections, redirectmodule"&gt;
    &lt;!-- Domain Redirects //--&gt;
    &lt;add targetUrl="captainloadtest\.com/Default\.aspx"
      destinationUrl="cptloadtest.com/" permanent="true" /&gt;
    &lt;add targetUrl="captainloadtest\.com"
      destinationUrl="cptloadtest.com" permanent="true" /&gt;

    &lt;!-- Add 'WWW' to the domain request //--&gt;
    &lt;add targetUrl="://cptloadtest\.com/Default\.aspx"
      destinationUrl="://www.$1.com/" permanent="true" /&gt;
    &lt;add targetUrl="://cptloadtest\.com"
      destinationUrl="://www.$1.com" permanent="true" /&gt;

    &lt;!-- ...More Redirects --&gt;
  &lt;/redirections&gt;
  &lt;system.web&gt;
    &lt;httpModules&gt;
      &lt;add name="RedirectModule"
        type="Pluralsight.Website.RedirectModule, redirectmodule" /&gt;
    &lt;/httpModules&gt;
  &lt;/system.web&gt;
&lt;/configuration&gt;</pre>
        <p>
The component is easy to use, and can redirect your site traffic to any URL you choose.
Neither code changes to the application nor configuration changes to IIS are needed.
By using this module to combine synonymous versions of your URLs, such as alternate
domains or subdomains, you will improve your page ranking through combining duplicate
search result entries. One more step towards your own search engine optimization goals.
</p>
        <h3>URL Rewrite
</h3>
        <ul>
          <li>
Part 1: <a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx">HTTP
302, Temporarily Relocated</a></li>
          <li>
Part 2: <a href="http://www.cptloadtest.com/2008/11/11/URLRewritePart2HTTP301MovedPermanently.aspx">HTTP
301, Moved Permanently</a></li>
          <li>
Part 3: Improving SEO and the 'www' subdomain</li>
        </ul>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:796ee61e-98c9-4ab1-8aef-6f3caa04ea6e" style="margin: 0px; padding: 0px; display: inline;">Technorati
Tags: <a href="http://technorati.com/tags/SEO" rel="tag">SEO</a>,<a href="http://technorati.com/tags/Search%20Engine%20Optimization" rel="tag">Search
Engine Optimization</a>,<a href="http://technorati.com/tags/Page%20Rank" rel="tag">Page
Rank</a>,<a href="http://technorati.com/tags/HTTP%20301" rel="tag">HTTP 301</a>,<a href="http://technorati.com/tags/ASP.NET" rel="tag">ASP.NET</a>,<a href="http://technorati.com/tags/Fritz%20Onion" rel="tag">Fritz
Onion</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=71ba8b42-6bcc-49e3-9f2f-48de47d8f275" />
      </body>
      <title>URL Rewrite, Part 3: Improving SEO and the 'www' subdomain</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,71ba8b42-6bcc-49e3-9f2f-48de47d8f275.aspx</guid>
      <link>http://www.cptloadtest.com/2008/12/04/URL-Rewrite-Part-3-Improving-SEO-And-The-Www-Subdomain.aspx</link>
      <pubDate>Thu, 04 Dec 2008 21:43:10 GMT</pubDate>
      <description>&lt;p&gt;
Did you know that &lt;em&gt;yourdomain.com&lt;/em&gt; and &lt;em&gt;www.yourdomain.com&lt;/em&gt; are actually
different sites? Are they both serving the same content? If so, it may be negatively
impacting your search engine rankings.
&lt;/p&gt;
&lt;h3&gt;Subdomains and the Synonymous 'WWW'
&lt;/h3&gt;
&lt;p&gt;
Sub-domains are the prefix to a domain (&lt;em&gt;http://subdomain.yourdomain.com&lt;/em&gt;),
and are treated by browsers, computers, domain name systems (DNS), search engines,
and the general internet as separate, individual web sites. Google's primary web presence, &lt;a href="http://www.google.com"&gt;http://www.google.com&lt;/a&gt;,
is very different than Google Mail, &lt;a href="http://mail.google.com"&gt;http://mail.google.com&lt;/a&gt;,
or Google Documents, &lt;a href="http://docs.google.com"&gt;http://docs.google.com&lt;/a&gt;,
all because of subdomains. However, what many do not realize is that &lt;em&gt;www&lt;/em&gt; is,
itself, a subdomain.
&lt;/p&gt;
&lt;p&gt;
A domain, on its own, requires no &lt;em&gt;www&lt;/em&gt; prefix; a subdomain-less &lt;em&gt;http://yourdomain.com&lt;/em&gt; should
be sufficient for serving up a web site. And since &lt;em&gt;www&lt;/em&gt; is a subdomain, dropping
the prefix could potentially return a different response. There are some sites that
will fail to return without the prefix, and some sites that fail with it, but the
most common practice is that the &lt;em&gt;www&lt;/em&gt; subdomain is synonymous for no subdomain
at all.
&lt;/p&gt;
&lt;h3&gt;The Synonymous WWW and SEO
&lt;/h3&gt;
&lt;p&gt;
The issue with having two synonymous URLs (&lt;em&gt;http://yourdomain.com&lt;/em&gt; and &lt;em&gt;http://www.yourdomain.com&lt;/em&gt;)
is that search engines may interpret them as separate sites, even if they are serving
the same content. The two addresses are technically independent and are potentially
serving unique content; to a cautious search engine, even if pages appear to contain
the same content, there may be something different under the covers. This means your
audience's search results returns two entries for the same content. Some users will
happen to click on &lt;em&gt;yourdomain.com&lt;/em&gt; while others navigate to &lt;em&gt;www.yourdomain.com&lt;/em&gt;,
splitting your traffic, your page hits, your search ranking between two sites, unnecessarily.
&lt;/p&gt;
&lt;p&gt;
HTTP Redirects will cure the issue. If you access &lt;a href="http://google.com"&gt;http://google.com&lt;/a&gt;,
your browser is instantly redirected to &lt;a href="http://www.google.com"&gt;http://www.google.com&lt;/a&gt;.
This is done through a HTTP 301 permanent redirect. Search Spiders recognize HTTP
response codes, and understand the 301 as a "use this other URL instead" command.
Many search engines, such as Google, will then update all page entries for the original
URI (&lt;em&gt;http://yourdomain.com&lt;/em&gt;) and replace it with the 301's destination URL
(&lt;em&gt;http://www.yourdomain.com&lt;/em&gt;). If there is already an entry for the destination
URL, the two entries will be merged together. The search entries for &lt;em&gt;yourdomain.com&lt;/em&gt; and &lt;em&gt;www.yourdomain.com&lt;/em&gt; will
now share traffic, share page hits, and share search ranking. Instead of having two
entries on the second and third pages of search results, combining these entries may
be just enough to place you on the first page of results.
&lt;/p&gt;
&lt;blockquote&gt;In addition to combining search entries for subdomains, you can also combine
root-level domains through HTTP 301. On this site, in addition to adding the &lt;em&gt;www&lt;/em&gt; prefix
if no subdomain is specified, &lt;a href="http://captainloadtest.com"&gt;captainloadtest.com&lt;/a&gt; will
HTTP 301 redirect to &lt;a href="http://www.cptloadtest.com"&gt;www.cptloadtest.com&lt;/a&gt;.&lt;/blockquote&gt; 
&lt;h3&gt;Combining the Synonyms
&lt;/h3&gt;
&lt;p&gt;
We need a way to implement an HTTP 301 redirect at the domain level for all requests
to a site; however, often we are using applications that may not grant us access to
the source, or we don't have the access into IIS through our host to set up redirects
for ourselves. &lt;a href="http://www.cptloadtest.com/2008/11/11/URLRewritePart2HTTP301MovedPermanently.aspx"&gt;URL
Rewrite, Part 2&lt;/a&gt; covers a great &lt;a href="http://www.pluralsight.com/community/blogs/fritz/archive/2004/07/21/1651.aspx"&gt;drop-in
redirect module&lt;/a&gt; by &lt;a href="http://www.pluralsight.com/community/blogs/fritz/"&gt;Fritz
Onion&lt;/a&gt; that uses a stand-alone assembly with a few additions in web.config to HTTP
301 redirect paths in your domain (it also supports HTTP 302 redirects). This module
is perfect for converting a WordPress blog post URL, such as &lt;a href="http://www.cptloadtest.com/?p=56"&gt;cptloadtest.com/?p=56&lt;/a&gt;,
to a DasBlog blog post URL like &lt;a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx"&gt;cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx&lt;/a&gt;.
However, to redirect domains and subdomains, the module must go a step further and
redirect based on matches against the entire URL, such as directing http:// to https://
or captainloadtest.com to cptloadtest.com, which it does not support. It's time for
some modifications.
&lt;/p&gt;
&lt;pre class="csharp:nocontrols:linenumber[20]" name="code"&gt;private void OnBeginRequest(object src, EventArgs e) {
  HttpApplication app = src as HttpApplication;
  string reqUrl = app.Request.Url.AbsoluteUri;
  redirections redirs
    = (redirections) ConfigurationManager.GetSection("redirections");

  foreach (Add a in redirs.Adds) {
    Regex regex = new Regex(a.targetUrl, RegexOptions.IgnoreCase);
    if (regex.IsMatch(reqUrl)) {
      string targetUrl = regex.Replace(reqUrl, a.destinationUrl, 1);

      if (a.permanent) {
        app.Response.StatusCode = 301; // make a permanent redirect
        app.Response.AddHeader("Location", targetUrl);
        app.Response.End();
      }
      else
        app.Response.Redirect(targetUrl);

      break;
    }    
  }
}&lt;/pre&gt;
&lt;p&gt;
By converting &lt;em&gt;app.Request.RawURL&lt;/em&gt; to &lt;em&gt;app.Request.AbsoluteUri&lt;/em&gt;, the
regular expression will now match against the entire URL, rather than just the requested
path. There is one downside to this change: the value is the actual path processed,
not necessarily what was in the originally requested URL. To this effect, the value
of &lt;em&gt;AbsoluteUri&lt;/em&gt; for requesting &lt;a href="http://www.cptloadtest.com?p=56"&gt;http://www.cptloadtest.com?p=56&lt;/a&gt; is
actually &lt;a href="http://www.cptloadtest.com/default.aspx?p=56"&gt;http://www.cptloadtest.com/default.aspx?p=56&lt;/a&gt;;
by requesting the root directory, the default page is being processed, not the directory
itself, so &lt;em&gt;default.aspx&lt;/em&gt; is added to the URL. Keep this in mind when setting
up your redirection rules. Also, the original code converted the URL to lower case;
with my modifications, I chose to maintain the case of the URL, since sometimes case
matters, and instead ignore case in the regular expression match using &lt;em&gt;RegexOptions.IgnoreCase&lt;/em&gt;.
Finally, I made some other minor enhancements, like using the ConfigurationManager,
since ConfigurationSettings is now obsolete, and reusing the matching Regex instance
for replacements.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;strong&gt;Download:&lt;/strong&gt; &lt;a href="http://www.cptloadtest.com/content/binary/RedirectModule.zip"&gt;RedirectModule.zip&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Includes:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Source code for the drop-in Redirect Module 
&lt;/li&gt;
&lt;li&gt;
Sample web.config that uses the module 
&lt;/li&gt;
&lt;li&gt;
Compiled version of redirectmodule.dll&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The code is based on the original &lt;a href="http://www.pluralsight.com/community/blogs/fritz/archive/2004/07/21/1651.aspx"&gt;Redirect
Module&lt;/a&gt; by &lt;a href="http://www.pluralsight.com/community/blogs/fritz/default.aspx"&gt;Fritz
Onion&lt;/a&gt; and the &lt;a href="http://alt.pluralsight.com/wiki/default.aspx/Craig/XmlSerializerSectionHandler.html"&gt;Xml
Serializer Section Handler&lt;/a&gt; by &lt;a href="http://www.pluralsight.com/community/blogs/craig/default.aspx"&gt;Craig
Andera&lt;/a&gt;. As always, this code is provided with no warranties or guarantees. Use
at your own risk. Your mileage may vary. Thanks to Fritz Onion for the original work,
and allowing me extend his code further.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
The usage is the same as Fritz Onion's original module. Drop the assembly into your
site's bin, and place a few lines into the web.config. The example below contains
the rules as they would apply to this site, 301 redirecting &lt;a href="http://www.captainloadtest.com"&gt;http://www.captainloadtest.com&lt;/a&gt; to &lt;a href="http://www.cptloadtest.com"&gt;http://www.cptloadtest.com&lt;/a&gt;,
and adding the &lt;em&gt;www&lt;/em&gt; subdomain to any domain requests that have no subdomain.
&lt;/p&gt;
&lt;pre class="xml:nocontrols:linenumber[20]" name="code"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;section name="redirections"
      type="Pluralsight.Website.XmlSerializerSectionHandler, redirectmodule" /&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;!-- Redirect Rules --&amp;gt;
  &amp;lt;redirections type="Pluralsight.Website.redirections, redirectmodule"&amp;gt;
    &amp;lt;!-- Domain Redirects //--&amp;gt;
    &amp;lt;add targetUrl="captainloadtest\.com/Default\.aspx"
      destinationUrl="cptloadtest.com/" permanent="true" /&amp;gt;
    &amp;lt;add targetUrl="captainloadtest\.com"
      destinationUrl="cptloadtest.com" permanent="true" /&amp;gt;

    &amp;lt;!-- Add 'WWW' to the domain request //--&amp;gt;
    &amp;lt;add targetUrl="://cptloadtest\.com/Default\.aspx"
      destinationUrl="://www.$1.com/" permanent="true" /&amp;gt;
    &amp;lt;add targetUrl="://cptloadtest\.com"
      destinationUrl="://www.$1.com" permanent="true" /&amp;gt;

    &amp;lt;!-- ...More Redirects --&amp;gt;
  &amp;lt;/redirections&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;httpModules&amp;gt;
      &amp;lt;add name="RedirectModule"
        type="Pluralsight.Website.RedirectModule, redirectmodule" /&amp;gt;
    &amp;lt;/httpModules&amp;gt;
  &amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;p&gt;
The component is easy to use, and can redirect your site traffic to any URL you choose.
Neither code changes to the application nor configuration changes to IIS are needed.
By using this module to combine synonymous versions of your URLs, such as alternate
domains or subdomains, you will improve your page ranking through combining duplicate
search result entries. One more step towards your own search engine optimization goals.
&lt;/p&gt;
&lt;h3&gt;URL Rewrite
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
Part 1: &lt;a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx"&gt;HTTP
302, Temporarily Relocated&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
Part 2: &lt;a href="http://www.cptloadtest.com/2008/11/11/URLRewritePart2HTTP301MovedPermanently.aspx"&gt;HTTP
301, Moved Permanently&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
Part 3: Improving SEO and the 'www' subdomain&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:796ee61e-98c9-4ab1-8aef-6f3caa04ea6e" style="margin: 0px; padding: 0px; display: inline;"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/SEO" rel="tag"&gt;SEO&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Search%20Engine%20Optimization" rel="tag"&gt;Search
Engine Optimization&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Page%20Rank" rel="tag"&gt;Page
Rank&lt;/a&gt;,&lt;a href="http://technorati.com/tags/HTTP%20301" rel="tag"&gt;HTTP 301&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASP.NET" rel="tag"&gt;ASP.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Fritz%20Onion" rel="tag"&gt;Fritz
Onion&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=71ba8b42-6bcc-49e3-9f2f-48de47d8f275" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,71ba8b42-6bcc-49e3-9f2f-48de47d8f275.aspx</comments>
      <category>ASP.Net</category>
      <category>Blogging</category>
      <category>Programming</category>
      <category>SEO</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=417c2df3-d32c-436c-8c5c-46e1fe4b2808</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,417c2df3-d32c-436c-8c5c-46e1fe4b2808.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,417c2df3-d32c-436c-8c5c-46e1fe4b2808.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=417c2df3-d32c-436c-8c5c-46e1fe4b2808</wfw:commentRss>
      <slash:comments>9</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <a href="http://code.google.com/p/syntaxhighlighter/">Google Syntax Highlighter</a> is
a simple tool that allows bloggers to easily display code in a format that is familiar
end users. The tool renders the code in a very consumable fashion that includes colored
syntax highlighting, line highlighting, and line numbers.
</p>
        <pre class="csharp:nocontrols" name="code">/*
This is an example of how Google
Syntax Highlighter can highlight and display syntax
to you, the end user
*/
public void HelloWorld()
{
  // I have some comments
  Console.WriteLine("Hello, World!");
}</pre>
        <p>
It is purely a client-side tool, as all of the processing is done strictly within
the browser through JavaScript. There is no server-side processing. Since it is all
JavaScript, you don't need special Copy/Paste plugins and macros installed to your
favorite IDE or your blog authoring tool. (I am leery of random plugins and installing
them into the software that I use to feed my family.) To including code in your blog
post, copy your code from Visual Studio, Notepad, Flash, Firebug, or any tool that
displays text, and paste it in to your post. As of v1.5.1, Google Syntax Highlighter
supports C, C++, C#, CSS, Delphi, HTML, Java, JavaScript, PHP, Pascal, Python, Ruby,
SQL, VB, VB.NET, XML, XSLT, and all of this is just what comes out of the box.
</p>
        <h3>Setting Up Syntax Highlighter
</h3>
        <p>
To get Syntax Highlighter running on your blog, <a href="http://code.google.com/p/syntaxhighlighter/downloads/list">download</a> the
latest version of the RAR archive and extract the code. The archive contains a parent
folder, <em>dp.SyntaxHighlighter</em>, with three child folders:
</p>
        <blockquote>
          <pre>dp.SyntaxHighlighter
  \Scripts         //Production-ready (Compressed) scripts
  \Styles          //CSS
  \Uncompressed    //Human-readable (Uncompressed/Debug) scripts</pre>
        </blockquote>
        <p>
Once the archive is extracted, upload <em>dp.SyntaxHighlighter</em> to your blog.
Feel free to rename the folder if you like, though I did not. It is not necessary
to upload the <em>Uncompressed</em> folder and its files; they are best used for debugging
or for viewing the code, as the files in the <em>Scripts</em> folder have been compressed
to reduce bandwidth by having most of their whitespace removed.
</p>
        <p>
After you have uploaded the files, you will need to add script and style references
to your site's HTML. This is code is not for your posts, but rather for your blog
template. In DasBlog, I place this code in the &lt;HEAD&gt; block of my <em>homeTemplate.blogtemplate</em> file.
Remember to change the file paths to match the path to where you uploaded the code.
</p>
        <pre class="html:nocontrols:nogutter" name="code">&lt;link type="text/css" rel="stylesheet"
  href="dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css"&gt;&lt;/link&gt;
&lt;script language="javascript" src="dp.SyntaxHighlighter/Scripts/shCore.js"&gt;&lt;/script&gt;
&lt;script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushCSharp.js"&gt;&lt;/script&gt;
&lt;script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushXml.js"&gt;&lt;/script&gt;
&lt;script language="javascript"&gt;
window.onload = function () {
  dp.SyntaxHighlighter.ClipboardSwf = 'dp.SyntaxHighlighter/Scripts/clipboard.swf';
  dp.SyntaxHighlighter.HighlightAll('code');
}
&lt;/script&gt;</pre>
        <p>
To make the tool most efficient, including minimizing the code download by the client
browser, highlighting is only enabled for the languages that you specify. The highlighting
rules for each language is available through a file referred to as a Brush. The code
sample above enables only C# and XML/HTML by including the core file, <em>shCore.js</em>,
the C# brush, <em>shBrushCSharp.js</em> and the XML/HTML brush, <em>shBrushXml.js</em>.
A unique brush file is available for each of the supported languages, and only the
core file is required. These brushes are located in your <em>Scripts</em> directory
(the human-readable version is in the <em>Uncompressed</em> folder). Include only
the brushes that you like; if you forgot a language brush, the code will still display
on your page, but as unformatted text.
</p>
        <pre>&lt;!-- Unformatted HTML Code / No Brush --&gt;
&lt;p id="greeting"&gt;Hi, mom &amp; dad!&lt;/p&gt;</pre>
        <pre class="html:nogutter:nocontrols" name="code">&lt;!-- Formatted HTML Code --&gt;
&lt;p id="greeting"&gt;Hi, mom &amp; dad!&lt;/p&gt;</pre>
        <h3>Making Syntax Highlighter Go
</h3>
        <p>
Now that the application is deployed to the site, how does it get applied to a post?
Paste the code into the HTML view of your post, inside of a &lt;PRE&gt; tag. Create
a <em>name</em> attribute on your tag with a value of <em>code</em>, and a <em>class</em> attribute
set to the language and options you are using.
</p>
        <pre class="html:nocontrols:nogutter" name="code">&lt;pre name="code" class="c-sharp"&gt;
  public void HelloWorld()
  {
    Console.WriteLine("Hello, World!");
  }
&lt;/pre&gt;</pre>
        <p>
One catch is the code must be first made HTML-safe. All angle-brackets, <em>&lt;tag&gt;</em>,
must be converted to their HTML equivalent, <em>&amp;lt;tag&amp;gt;</em>, as well
as ampersands, <em>&amp;</em> to <em>&amp;amp;</em>. I also find it helpful if your
code-indentation uses two-spaces, rather than tabs.
</p>
        <pre class="html:nocontrols" name="code">&lt;!-- Pre-converted code --&gt;
&lt;p&gt;Hi, mom &amp; dad!&lt;/p&gt;</pre>
        <pre class="html:nocontrols" name="code">&lt;!-- Converted code --&gt;
&lt;pre name="code" class="html"&gt;
  &amp;lt;p&amp;gt;Hi, mom &amp;amp; dad!&amp;lt;/p&amp;gt;
&lt;/pre&gt;</pre>
        <p>
The <em>class</em> attribute is made up of both language and option aliases. These
aliases consist of one language followed by your desired options, all in a colon delimited
list.
</p>
        <p>
class="language[:option[:option[:option]]]"
</p>
        <p>
The value of language is any of Syntax Highlighter's defined language aliases, such
as <em>c#</em>, <em>csharp</em>, or <em>c-sharp</em> for C#, or <em>rb</em>, <em>ruby</em>, <em>rails</em>,
or <em>ror</em> for Ruby. See: <a href="http://code.google.com/p/syntaxhighlighter/wiki/Languages">full
list</a> of available languages.
</p>
        <p>
Options allow for such things as turning off the plain text / copy / about controls
(<em>nocontrols</em>), turning off the line number gutter (<em>nogutter</em>), or
specifying the number of the first line (<em>firstline[n]</em>). A JavaScript code
block with no controls header, and starting the line numbering at 34 would have a <em>class</em> attribute
value of <em>class="js:nocontrols:linenumber[34]"</em>. See: <a href="http://code.google.com/p/syntaxhighlighter/wiki/Configuration">full
list</a> of available options.
</p>
        <h3>Extending Syntax Highlighter
</h3>
        <p>
Because Google Syntax Highlighter is entirely in JavaScript, you have access to all
of the code. Edit it however you like to suit your needs. Additionally, brushes are
very easy to create, and include little more than a list of a highlighted language's
keywords in a string and an array of language aliases. Creating a brush for ActionScript
or QBasic would not take much time. Language brushes exist in the wild for <a href="http://nevstokes.com/includes/syntax/scripts/shBrushPerl.js">Perl</a>, <a href="http://pcnorb.blogspot.com/2008/10/shbrushbatch-for-google.html">DOS
Batch</a>, and <a href="http://blog.tech-cats.com/2007/10/syntax-highlighting-for-coldfusion.html">ColdFusion</a>.
</p>
        <p>
In a future post I plan on discussing Brush Creation in depth through creating a brush
for ActionScript.
</p>
        <h3>Comparing Syntax Highlighter to Others
</h3>
        <p>
I am a fan of this tool, though that should be obvious considering it is what I use
on this blog. I like how readable the code is, how extendable it is, and how easy
it is to use. I don't like its compatibility--or lack thereof--with RSS; since all
of the work is done in JavaScript, and RSS doesn't do JavaScript, there is no syntax
highlighting, numbers, or options within a feed, though the code formatting is still
maintained. Other tools, like the <em><a href="http://www.jtleigh.com/people/colin/software/CopySourceAsHtml/">CopySourceAsHtml</a></em> plugin
for Visual Studio or <em><a href="http://lvildosola.blogspot.com/2007/02/code-snippet-plugin-for-windows-live.html">Insert
Code Snippet</a></em> for Windows Live Writer convert your code into formatted HTML,
where all of the syntax highlighting is applied through HTML attributes and embedded
CSS. Their methods are much easier than Syntax Highlighter, since there are no stylesheets
or JavaScript files to include in your HTML, and you don't have to worry about making
your code HTML-safe. Also, their method works in RSS feeds. However, there isn't the
same level of control. Through Syntax Highlighter's extendibility, I can theme my
code views, such as if I wanted them to look like my personal Visual Studio theme.
Through Syntax Highlighter, I can also make changes at a later time, and those changes
will immediately reflected in all past posts, whereas making modifications to the
HTML/embedded CSS pattern is much more difficult.
</p>
        <h3>Final Thoughts
</h3>
        <p>
I like CopySourceAsHtml in Visual Studio. I used it for years on this blog. But I
code in more languages than VB.Net or C#, and the plugin isn't available within the
Flash or LoadRunner IDE. I was also frustrated with pasting my code in, only to find
that it was too wide for my blog theme's margins, and would have to go back to Visual
Studio, change my line endings, and repeat the process. I'm sticking with Google Syntax
Highlighter. It works for all of my languages (as soon as I finish writing my ActionScript
brush), and when my line endings are too long, I simply change my HTML. And in my
HTML, my code still looks like code, rather than a mess of embedded style. I have
to sacrifice RSS formatting, but as a presentation developer that is very particular
about his HTML, I am glad for the customization and control.
</p>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:5e03f5f4-120c-4ce0-96ea-32867691f7e7" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
Tags: <a href="http://technorati.com/tags/SyntaxHighlighter" rel="tag">SyntaxHighlighter</a>,<a href="http://technorati.com/tags/Syntax%20Highlighter" rel="tag">Syntax
Highlighter</a>,<a href="http://technorati.com/tags/Google%20Code" rel="tag">Google
Code</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=417c2df3-d32c-436c-8c5c-46e1fe4b2808" />
      </body>
      <title>Blog your code using Google Syntax Highlighter</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,417c2df3-d32c-436c-8c5c-46e1fe4b2808.aspx</guid>
      <link>http://www.cptloadtest.com/2008/11/24/Blog-Your-Code-Using-Google-Syntax-Highlighter.aspx</link>
      <pubDate>Mon, 24 Nov 2008 15:41:50 GMT</pubDate>
      <description>&lt;p&gt;
&lt;a href="http://code.google.com/p/syntaxhighlighter/"&gt;Google Syntax Highlighter&lt;/a&gt; is
a simple tool that allows bloggers to easily display code in a format that is familiar
end users. The tool renders the code in a very consumable fashion that includes colored
syntax highlighting, line highlighting, and line numbers.
&lt;/p&gt;
&lt;pre class="csharp:nocontrols" name="code"&gt;/*
This is an example of how Google
Syntax Highlighter can highlight and display syntax
to you, the end user
*/
public void HelloWorld()
{
  // I have some comments
  Console.WriteLine("Hello, World!");
}&lt;/pre&gt;
&lt;p&gt;
It is purely a client-side tool, as all of the processing is done strictly within
the browser through JavaScript. There is no server-side processing. Since it is all
JavaScript, you don't need special Copy/Paste plugins and macros installed to your
favorite IDE or your blog authoring tool. (I am leery of random plugins and installing
them into the software that I use to feed my family.) To including code in your blog
post, copy your code from Visual Studio, Notepad, Flash, Firebug, or any tool that
displays text, and paste it in to your post. As of v1.5.1, Google Syntax Highlighter
supports C, C++, C#, CSS, Delphi, HTML, Java, JavaScript, PHP, Pascal, Python, Ruby,
SQL, VB, VB.NET, XML, XSLT, and all of this is just what comes out of the box.
&lt;/p&gt;
&lt;h3&gt;Setting Up Syntax Highlighter
&lt;/h3&gt;
&lt;p&gt;
To get Syntax Highlighter running on your blog, &lt;a href="http://code.google.com/p/syntaxhighlighter/downloads/list"&gt;download&lt;/a&gt; the
latest version of the RAR archive and extract the code. The archive contains a parent
folder, &lt;em&gt;dp.SyntaxHighlighter&lt;/em&gt;, with three child folders:
&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;dp.SyntaxHighlighter
  \Scripts         //Production-ready (Compressed) scripts
  \Styles          //CSS
  \Uncompressed    //Human-readable (Uncompressed/Debug) scripts&lt;/pre&gt;&lt;/blockquote&gt; 
&lt;p&gt;
Once the archive is extracted, upload &lt;em&gt;dp.SyntaxHighlighter&lt;/em&gt; to your blog.
Feel free to rename the folder if you like, though I did not. It is not necessary
to upload the &lt;em&gt;Uncompressed&lt;/em&gt; folder and its files; they are best used for debugging
or for viewing the code, as the files in the &lt;em&gt;Scripts&lt;/em&gt; folder have been compressed
to reduce bandwidth by having most of their whitespace removed.
&lt;/p&gt;
&lt;p&gt;
After you have uploaded the files, you will need to add script and style references
to your site's HTML. This is code is not for your posts, but rather for your blog
template. In DasBlog, I place this code in the &amp;lt;HEAD&amp;gt; block of my &lt;em&gt;homeTemplate.blogtemplate&lt;/em&gt; file.
Remember to change the file paths to match the path to where you uploaded the code.
&lt;/p&gt;
&lt;pre class="html:nocontrols:nogutter" name="code"&gt;&amp;lt;link type="text/css" rel="stylesheet"
  href="dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css"&amp;gt;&amp;lt;/link&amp;gt;
&amp;lt;script language="javascript" src="dp.SyntaxHighlighter/Scripts/shCore.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushCSharp.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushXml.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script language="javascript"&amp;gt;
window.onload = function () {
  dp.SyntaxHighlighter.ClipboardSwf = 'dp.SyntaxHighlighter/Scripts/clipboard.swf';
  dp.SyntaxHighlighter.HighlightAll('code');
}
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;
To make the tool most efficient, including minimizing the code download by the client
browser, highlighting is only enabled for the languages that you specify. The highlighting
rules for each language is available through a file referred to as a Brush. The code
sample above enables only C# and XML/HTML by including the core file, &lt;em&gt;shCore.js&lt;/em&gt;,
the C# brush, &lt;em&gt;shBrushCSharp.js&lt;/em&gt; and the XML/HTML brush, &lt;em&gt;shBrushXml.js&lt;/em&gt;.
A unique brush file is available for each of the supported languages, and only the
core file is required. These brushes are located in your &lt;em&gt;Scripts&lt;/em&gt; directory
(the human-readable version is in the &lt;em&gt;Uncompressed&lt;/em&gt; folder). Include only
the brushes that you like; if you forgot a language brush, the code will still display
on your page, but as unformatted text.
&lt;/p&gt;
&lt;pre&gt;&amp;lt;!-- Unformatted HTML Code / No Brush --&amp;gt;
&amp;lt;p id="greeting"&amp;gt;Hi, mom &amp;amp; dad!&amp;lt;/p&amp;gt;&lt;/pre&gt;&lt;pre class="html:nogutter:nocontrols" name="code"&gt;&amp;lt;!-- Formatted HTML Code --&amp;gt;
&amp;lt;p id="greeting"&amp;gt;Hi, mom &amp;amp; dad!&amp;lt;/p&amp;gt;&lt;/pre&gt;
&lt;h3&gt;Making Syntax Highlighter Go
&lt;/h3&gt;
&lt;p&gt;
Now that the application is deployed to the site, how does it get applied to a post?
Paste the code into the HTML view of your post, inside of a &amp;lt;PRE&amp;gt; tag. Create
a &lt;em&gt;name&lt;/em&gt; attribute on your tag with a value of &lt;em&gt;code&lt;/em&gt;, and a &lt;em&gt;class&lt;/em&gt; attribute
set to the language and options you are using.
&lt;/p&gt;
&lt;pre class="html:nocontrols:nogutter" name="code"&gt;&amp;lt;pre name="code" class="c-sharp"&amp;gt;
  public void HelloWorld()
  {
    Console.WriteLine("Hello, World!");
  }
&amp;lt;/pre&amp;gt;&lt;/pre&gt;
&lt;p&gt;
One catch is the code must be first made HTML-safe. All angle-brackets, &lt;em&gt;&amp;lt;tag&amp;gt;&lt;/em&gt;,
must be converted to their HTML equivalent, &lt;em&gt;&amp;amp;lt;tag&amp;amp;gt;&lt;/em&gt;, as well
as ampersands, &lt;em&gt;&amp;amp;&lt;/em&gt; to &lt;em&gt;&amp;amp;amp;&lt;/em&gt;. I also find it helpful if your
code-indentation uses two-spaces, rather than tabs.
&lt;/p&gt;
&lt;pre class="html:nocontrols" name="code"&gt;&amp;lt;!-- Pre-converted code --&amp;gt;
&amp;lt;p&amp;gt;Hi, mom &amp;amp; dad!&amp;lt;/p&amp;gt;&lt;/pre&gt;&lt;pre class="html:nocontrols" name="code"&gt;&amp;lt;!-- Converted code --&amp;gt;
&amp;lt;pre name="code" class="html"&amp;gt;
  &amp;amp;lt;p&amp;amp;gt;Hi, mom &amp;amp;amp; dad!&amp;amp;lt;/p&amp;amp;gt;
&amp;lt;/pre&amp;gt;&lt;/pre&gt;
&lt;p&gt;
The &lt;em&gt;class&lt;/em&gt; attribute is made up of both language and option aliases. These
aliases consist of one language followed by your desired options, all in a colon delimited
list.
&lt;/p&gt;
&lt;p&gt;
class="language[:option[:option[:option]]]"
&lt;/p&gt;
&lt;p&gt;
The value of language is any of Syntax Highlighter's defined language aliases, such
as &lt;em&gt;c#&lt;/em&gt;, &lt;em&gt;csharp&lt;/em&gt;, or &lt;em&gt;c-sharp&lt;/em&gt; for C#, or &lt;em&gt;rb&lt;/em&gt;, &lt;em&gt;ruby&lt;/em&gt;, &lt;em&gt;rails&lt;/em&gt;,
or &lt;em&gt;ror&lt;/em&gt; for Ruby. See: &lt;a href="http://code.google.com/p/syntaxhighlighter/wiki/Languages"&gt;full
list&lt;/a&gt; of available languages.
&lt;/p&gt;
&lt;p&gt;
Options allow for such things as turning off the plain text / copy / about controls
(&lt;em&gt;nocontrols&lt;/em&gt;), turning off the line number gutter (&lt;em&gt;nogutter&lt;/em&gt;), or
specifying the number of the first line (&lt;em&gt;firstline[n]&lt;/em&gt;). A JavaScript code
block with no controls header, and starting the line numbering at 34 would have a &lt;em&gt;class&lt;/em&gt; attribute
value of &lt;em&gt;class="js:nocontrols:linenumber[34]"&lt;/em&gt;. See: &lt;a href="http://code.google.com/p/syntaxhighlighter/wiki/Configuration"&gt;full
list&lt;/a&gt; of available options.
&lt;/p&gt;
&lt;h3&gt;Extending Syntax Highlighter
&lt;/h3&gt;
&lt;p&gt;
Because Google Syntax Highlighter is entirely in JavaScript, you have access to all
of the code. Edit it however you like to suit your needs. Additionally, brushes are
very easy to create, and include little more than a list of a highlighted language's
keywords in a string and an array of language aliases. Creating a brush for ActionScript
or QBasic would not take much time. Language brushes exist in the wild for &lt;a href="http://nevstokes.com/includes/syntax/scripts/shBrushPerl.js"&gt;Perl&lt;/a&gt;, &lt;a href="http://pcnorb.blogspot.com/2008/10/shbrushbatch-for-google.html"&gt;DOS
Batch&lt;/a&gt;, and &lt;a href="http://blog.tech-cats.com/2007/10/syntax-highlighting-for-coldfusion.html"&gt;ColdFusion&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
In a future post I plan on discussing Brush Creation in depth through creating a brush
for ActionScript.
&lt;/p&gt;
&lt;h3&gt;Comparing Syntax Highlighter to Others
&lt;/h3&gt;
&lt;p&gt;
I am a fan of this tool, though that should be obvious considering it is what I use
on this blog. I like how readable the code is, how extendable it is, and how easy
it is to use. I don't like its compatibility--or lack thereof--with RSS; since all
of the work is done in JavaScript, and RSS doesn't do JavaScript, there is no syntax
highlighting, numbers, or options within a feed, though the code formatting is still
maintained. Other tools, like the &lt;em&gt;&lt;a href="http://www.jtleigh.com/people/colin/software/CopySourceAsHtml/"&gt;CopySourceAsHtml&lt;/a&gt;&lt;/em&gt; plugin
for Visual Studio or &lt;em&gt;&lt;a href="http://lvildosola.blogspot.com/2007/02/code-snippet-plugin-for-windows-live.html"&gt;Insert
Code Snippet&lt;/a&gt;&lt;/em&gt; for Windows Live Writer convert your code into formatted HTML,
where all of the syntax highlighting is applied through HTML attributes and embedded
CSS. Their methods are much easier than Syntax Highlighter, since there are no stylesheets
or JavaScript files to include in your HTML, and you don't have to worry about making
your code HTML-safe. Also, their method works in RSS feeds. However, there isn't the
same level of control. Through Syntax Highlighter's extendibility, I can theme my
code views, such as if I wanted them to look like my personal Visual Studio theme.
Through Syntax Highlighter, I can also make changes at a later time, and those changes
will immediately reflected in all past posts, whereas making modifications to the
HTML/embedded CSS pattern is much more difficult.
&lt;/p&gt;
&lt;h3&gt;Final Thoughts
&lt;/h3&gt;
&lt;p&gt;
I like CopySourceAsHtml in Visual Studio. I used it for years on this blog. But I
code in more languages than VB.Net or C#, and the plugin isn't available within the
Flash or LoadRunner IDE. I was also frustrated with pasting my code in, only to find
that it was too wide for my blog theme's margins, and would have to go back to Visual
Studio, change my line endings, and repeat the process. I'm sticking with Google Syntax
Highlighter. It works for all of my languages (as soon as I finish writing my ActionScript
brush), and when my line endings are too long, I simply change my HTML. And in my
HTML, my code still looks like code, rather than a mess of embedded style. I have
to sacrifice RSS formatting, but as a presentation developer that is very particular
about his HTML, I am glad for the customization and control.
&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:5e03f5f4-120c-4ce0-96ea-32867691f7e7" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/SyntaxHighlighter" rel="tag"&gt;SyntaxHighlighter&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Syntax%20Highlighter" rel="tag"&gt;Syntax
Highlighter&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Google%20Code" rel="tag"&gt;Google
Code&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=417c2df3-d32c-436c-8c5c-46e1fe4b2808" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,417c2df3-d32c-436c-8c5c-46e1fe4b2808.aspx</comments>
      <category>Blogging</category>
      <category>JavaScript</category>
      <category>Programming</category>
      <category>Reviews</category>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=69b08e29-c468-4517-8503-bb188c4e3888</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,69b08e29-c468-4517-8503-bb188c4e3888.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,69b08e29-c468-4517-8503-bb188c4e3888.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=69b08e29-c468-4517-8503-bb188c4e3888</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A few months ago I switched my blogging engine from WordPress to DasBlog, and was
left with a pile of broken post links. The WordPress format of formatting URLs, such
as <a href="http://www.cptloadtest.com/?p=56">cptloadtest.com/?p=56</a>, no longer
applied; DasBlog has its own way of building the URL: <a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx">cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx</a>.
Other people, with links to my posts on their own blogs, and search engines, with
search results pointing to the old format, no longer directed people to the proper
page. Fortunately, the old WordPress way directed users to the domain root, so they
saw the main page instead of a 404, but what I really needed was a way to get users
to the content they came for. But, I wanted a way that didn't involve customizing
DasBlog code.
</p>
        <p>
          <a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx">Part
1</a> discusses some client-side options for redirecting traffic. As a developer,
I would only need to add some quick JavaScript or HTML to my pages to reroute traffic,
but I wanted a better way. I wanted Google's links to be updated, rather than just
for the link to correctly route. I want a solution that worked without JavaScript.
I wanted a solution that didn't download the page twice, as any client-side processor
would do. I wanted the HTTP 301.
</p>
        <p>
HTTP 301, Move Permanently, is a server-side redirection of traffic. No client-side
processing is involved. And Google recognizes that this is a permanent redirect, as
it's name implies, so the Google result link is updated to the new URL. But since
this is a server-side process, and I don't have full access to IIS settings with my
hosting provider, I needed some code.
</p>
        <pre class="csharp:nocontrols" name="code">response.StatusCode = 301;
response.AddHeader("Location", "http://www.cptloadtest.com");
response.End();</pre>
        <blockquote>
          <p>
You may have noticed that, unlike the title of this blog post, I did not use a URL
rewrite. HTTP 301 (and 302) redirects are HTTP Response Codes that are returned to
the client browser, and the client then requests the new URL. A URL Rewrite leaves
the original URL in place, and renders a different page instead, without visibility
to the client browser or end-user. If I were to URL rewrite my blog from page1.aspx
to page2.aspx, the URL in your address bar would still list page1.aspx, even though
the content was from page2.aspx. The end-user (and the search engine) never know about
the URL for page2.aspx. However, with a HTTP redirect, the content and the address
bar would both be page2.aspx.
</p>
        </blockquote>
        <p>
I ran through Google to see if anyone had solved this problem in the past. I came
across a <a href="http://www.hanselman.com/blog/PermanentRedirectsWithHTTP301.aspx">Scott
Hanselman post</a> on HTTP 301, which mentions a fantastic <a href="http://www.pluralsight.com/community/blogs/fritz/archive/2004/07/21/1651.aspx">drop-in
redirect module</a> by <a href="http://www.pluralsight.com/community/blogs/fritz/">Fritz
Onion</a>. I was elated when I found this module, and it was very easy to implement.
Drop the assembly into your application's bin, add a few lines into the web.config,
and enjoy redirection bliss. The module also supports both HTTP 302 and HTTP 301 redirects
through the "permanent" attribute in the redirection rules.
</p>
        <pre class="xml:nocontrols" name="code">&lt;?xml version="1.0"?&gt;
&lt;configuration&gt;
  &lt;configSections&gt;
    &lt;section name="redirections"
      type="Pluralsight.Website.XmlSerializerSectionHandler, redirectmodule" /&gt;
  &lt;/configSections&gt;
  &lt;!-- Redirect Rules --&gt;
  &lt;redirections type="Pluralsight.Website.redirections, redirectmodule"&gt;
    &lt;!-- Wordpress Post Redirects //--&gt;
    &lt;add targetUrl="/default\.aspx\?p=86"
      destinationUrl="/2007/09/22/ManagingMultipleEnvironmentConfigurationsThroughNAnt.aspx"
      permanent="true" /&gt;
    &lt;add targetUrl="/default\.aspx\?p=74"
      destinationUrl="/2007/02/09/Flash8DepthManagerBaffledByThoseWithoutDepth.aspx"
      permanent="true" /&gt;
    &lt;add targetUrl="/default\.aspx\?p=72"
      destinationUrl="/2006/10/20/IE7Released.aspx"
      permanent="true" /&gt;
    &lt;add targetUrl="/default\.aspx\?p=70"
      destinationUrl="/2006/10/17/ClearingFlashIDEWSDLCache.aspx"
      permanent="true" /&gt;
    &lt;add targetUrl="/default\.aspx\?p=69"
      destinationUrl="/2006/10/10/CruiseControlNetV11ReleasedOct1.aspx"
      permanent="true" /&gt;

    &lt;!-- ...More Redirects --&gt;
  &lt;/redirections&gt;
  &lt;system.web&gt;
    &lt;httpModules&gt;
      &lt;add name="RedirectModule"
        type="Pluralsight.Website.RedirectModule, redirectmodule" /&gt;
    &lt;/httpModules&gt;
  &lt;/system.web&gt;
&lt;/configuration&gt;</pre>
        <p>
The entire implementation took only a few minutes. It seemed like it took longer to
upload the changes to the blog than it did to make the local edits. The solution is
also very clean, as it required no modification to the existing application beyond
integrating the configuration blocks into the web.config. Blog traffic will now seamlessly
redirect from links that use the old WordPress URL to post that use the new DasBlog
URL. Search Engines also update their links, and the page ranking for each post isn't
lost into the ether just because the URL changed. All is well with the world, again.
</p>
        <p>
          <strong>Next up: </strong>
          <a href="http://www.cptloadtest.com/2008/12/04/URLRewritePart3ImprovingSEOAndTheWwwSubdomain.aspx">Part
3</a>. URL redirection also plays a role in Search Engine Optimization. In Part 3,
I will go over some ways that you can use HTTP redirects to improve your search engine
listings, as well as discuss some improvements I made to Fritz Onion's redirect module
in the name of SEO.
</p>
        <h3>URL Rewrite
</h3>
        <ul>
          <li>
Part 1: <a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx">HTTP
302, Temporarily Relocated</a></li>
          <li>
Part 2: HTTP 301, Moved Permanently 
</li>
          <li>
Part 3: <a href="http://www.cptloadtest.com/2008/12/04/URLRewritePart3ImprovingSEOAndTheWwwSubdomain.aspx">Improving
SEO and the 'www' subdomain</a></li>
        </ul>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:3f1baf1f-daae-4ec5-b4e1-96bdabb5dd96" style="margin: 0px; padding: 0px; display: inline;">Technorati
Tags: <a href="http://technorati.com/tags/HTTP%20301" rel="tag">HTTP 301</a>,<a href="http://technorati.com/tags/HTTP%20302" rel="tag">HTTP
302</a>,<a href="http://technorati.com/tags/ASP.Net" rel="tag">ASP.Net</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=69b08e29-c468-4517-8503-bb188c4e3888" />
      </body>
      <title>URL Rewrite, Part 2: HTTP 301, Moved Permanently</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,69b08e29-c468-4517-8503-bb188c4e3888.aspx</guid>
      <link>http://www.cptloadtest.com/2008/11/11/URL-Rewrite-Part-2-HTTP-301-Moved-Permanently.aspx</link>
      <pubDate>Tue, 11 Nov 2008 17:36:34 GMT</pubDate>
      <description>&lt;p&gt;
A few months ago I switched my blogging engine from WordPress to DasBlog, and was
left with a pile of broken post links. The WordPress format of formatting URLs, such
as &lt;a href="http://www.cptloadtest.com/?p=56"&gt;cptloadtest.com/?p=56&lt;/a&gt;, no longer
applied; DasBlog has its own way of building the URL: &lt;a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx"&gt;cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx&lt;/a&gt;.
Other people, with links to my posts on their own blogs, and search engines, with
search results pointing to the old format, no longer directed people to the proper
page. Fortunately, the old WordPress way directed users to the domain root, so they
saw the main page instead of a 404, but what I really needed was a way to get users
to the content they came for. But, I wanted a way that didn't involve customizing
DasBlog code.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx"&gt;Part
1&lt;/a&gt; discusses some client-side options for redirecting traffic. As a developer,
I would only need to add some quick JavaScript or HTML to my pages to reroute traffic,
but I wanted a better way. I wanted Google's links to be updated, rather than just
for the link to correctly route. I want a solution that worked without JavaScript.
I wanted a solution that didn't download the page twice, as any client-side processor
would do. I wanted the HTTP 301.
&lt;/p&gt;
&lt;p&gt;
HTTP 301, Move Permanently, is a server-side redirection of traffic. No client-side
processing is involved. And Google recognizes that this is a permanent redirect, as
it's name implies, so the Google result link is updated to the new URL. But since
this is a server-side process, and I don't have full access to IIS settings with my
hosting provider, I needed some code.
&lt;/p&gt;
&lt;pre class="csharp:nocontrols" name="code"&gt;response.StatusCode = 301;
response.AddHeader("Location", "http://www.cptloadtest.com");
response.End();&lt;/pre&gt;
&lt;blockquote&gt; 
&lt;p&gt;
You may have noticed that, unlike the title of this blog post, I did not use a URL
rewrite. HTTP 301 (and 302) redirects are HTTP Response Codes that are returned to
the client browser, and the client then requests the new URL. A URL Rewrite leaves
the original URL in place, and renders a different page instead, without visibility
to the client browser or end-user. If I were to URL rewrite my blog from page1.aspx
to page2.aspx, the URL in your address bar would still list page1.aspx, even though
the content was from page2.aspx. The end-user (and the search engine) never know about
the URL for page2.aspx. However, with a HTTP redirect, the content and the address
bar would both be page2.aspx.
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
I ran through Google to see if anyone had solved this problem in the past. I came
across a &lt;a href="http://www.hanselman.com/blog/PermanentRedirectsWithHTTP301.aspx"&gt;Scott
Hanselman post&lt;/a&gt; on HTTP 301, which mentions a fantastic &lt;a href="http://www.pluralsight.com/community/blogs/fritz/archive/2004/07/21/1651.aspx"&gt;drop-in
redirect module&lt;/a&gt; by &lt;a href="http://www.pluralsight.com/community/blogs/fritz/"&gt;Fritz
Onion&lt;/a&gt;. I was elated when I found this module, and it was very easy to implement.
Drop the assembly into your application's bin, add a few lines into the web.config,
and enjoy redirection bliss. The module also supports both HTTP 302 and HTTP 301 redirects
through the "permanent" attribute in the redirection rules.
&lt;/p&gt;
&lt;pre class="xml:nocontrols" name="code"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;section name="redirections"
      type="Pluralsight.Website.XmlSerializerSectionHandler, redirectmodule" /&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;!-- Redirect Rules --&amp;gt;
  &amp;lt;redirections type="Pluralsight.Website.redirections, redirectmodule"&amp;gt;
    &amp;lt;!-- Wordpress Post Redirects //--&amp;gt;
    &amp;lt;add targetUrl="/default\.aspx\?p=86"
      destinationUrl="/2007/09/22/ManagingMultipleEnvironmentConfigurationsThroughNAnt.aspx"
      permanent="true" /&amp;gt;
    &amp;lt;add targetUrl="/default\.aspx\?p=74"
      destinationUrl="/2007/02/09/Flash8DepthManagerBaffledByThoseWithoutDepth.aspx"
      permanent="true" /&amp;gt;
    &amp;lt;add targetUrl="/default\.aspx\?p=72"
      destinationUrl="/2006/10/20/IE7Released.aspx"
      permanent="true" /&amp;gt;
    &amp;lt;add targetUrl="/default\.aspx\?p=70"
      destinationUrl="/2006/10/17/ClearingFlashIDEWSDLCache.aspx"
      permanent="true" /&amp;gt;
    &amp;lt;add targetUrl="/default\.aspx\?p=69"
      destinationUrl="/2006/10/10/CruiseControlNetV11ReleasedOct1.aspx"
      permanent="true" /&amp;gt;

    &amp;lt;!-- ...More Redirects --&amp;gt;
  &amp;lt;/redirections&amp;gt;
  &amp;lt;system.web&amp;gt;
    &amp;lt;httpModules&amp;gt;
      &amp;lt;add name="RedirectModule"
        type="Pluralsight.Website.RedirectModule, redirectmodule" /&amp;gt;
    &amp;lt;/httpModules&amp;gt;
  &amp;lt;/system.web&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;p&gt;
The entire implementation took only a few minutes. It seemed like it took longer to
upload the changes to the blog than it did to make the local edits. The solution is
also very clean, as it required no modification to the existing application beyond
integrating the configuration blocks into the web.config. Blog traffic will now seamlessly
redirect from links that use the old WordPress URL to post that use the new DasBlog
URL. Search Engines also update their links, and the page ranking for each post isn't
lost into the ether just because the URL changed. All is well with the world, again.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Next up: &lt;/strong&gt;&lt;a href="http://www.cptloadtest.com/2008/12/04/URLRewritePart3ImprovingSEOAndTheWwwSubdomain.aspx"&gt;Part
3&lt;/a&gt;. URL redirection also plays a role in Search Engine Optimization. In Part 3,
I will go over some ways that you can use HTTP redirects to improve your search engine
listings, as well as discuss some improvements I made to Fritz Onion's redirect module
in the name of SEO.
&lt;/p&gt;
&lt;h3&gt;URL Rewrite
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
Part 1: &lt;a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx"&gt;HTTP
302, Temporarily Relocated&lt;/a&gt; 
&lt;/li&gt;
&lt;li&gt;
Part 2: HTTP 301, Moved Permanently 
&lt;/li&gt;
&lt;li&gt;
Part 3: &lt;a href="http://www.cptloadtest.com/2008/12/04/URLRewritePart3ImprovingSEOAndTheWwwSubdomain.aspx"&gt;Improving
SEO and the 'www' subdomain&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:3f1baf1f-daae-4ec5-b4e1-96bdabb5dd96" style="margin: 0px; padding: 0px; display: inline;"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/HTTP%20301" rel="tag"&gt;HTTP 301&lt;/a&gt;,&lt;a href="http://technorati.com/tags/HTTP%20302" rel="tag"&gt;HTTP
302&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASP.Net" rel="tag"&gt;ASP.Net&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=69b08e29-c468-4517-8503-bb188c4e3888" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,69b08e29-c468-4517-8503-bb188c4e3888.aspx</comments>
      <category>ASP.Net</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=8e086b43-7342-4790-acfd-0b35ae0451c7</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,8e086b43-7342-4790-acfd-0b35ae0451c7.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,8e086b43-7342-4790-acfd-0b35ae0451c7.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8e086b43-7342-4790-acfd-0b35ae0451c7</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
A few months ago I switched my blogging engine from WordPress to DasBlog. Though I
do feel that WordPress is a more mature engine, with a more robust feature set and
a better plug-in community, I wanted a site that was built on .NET. Being a .NET developer,
I wanted something I could tinker with,  modify, and adjust to my liking.
</p>
        <h3>Redirecting WordPress URL Format to DasBlog
</h3>
        <p>
One of the pain points of the switch was with the differences in how the two blogging
engines generated their URLs. As an example, my post on the <a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx">Collapse
All macro for the Visual Studio Solution Explorer</a>, originally written in WordPress,
went from a URL of <a href="http://www.cptloadtest.com/?p=56">cptloadtest.com/?p=56</a> to <a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx">cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx</a>.
A few sites, such as <a href="http://www.chinhdo.com/20070920/top-11-visual-studio-2005-ide-tips-and-tricks-to-make-you-a-more-productive-developer/">Chinhdo.com</a>,
link to the post's old URL, which without effort to put a redirect in place would
return HTTP 404: File Not Found under the new engine.
</p>
        <p>
Enter URL redirects. I needed a way to translate one URL into another. More specifically,
since WordPress retrieves all of its posts by query string (using the 'p' key), I
needed to translate a specific query string key/value pair into a URL. But, I didn't
want to have to recompile any code.
</p>
        <p>
There are a view client-side redirecting options available:
</p>
        <h3>Meta Refresh
</h3>
        <pre class="html:nocontrols" name="code">&lt;meta http-equiv="refresh" content="0;url=http://www.cptloadtest.com/"&gt;</pre>
        <p>
The Old-School HTML way of redirecting a page. Nothing but HTML is needed. Only access
to the base HTML page is required. Place the above HTML within your &lt;HEAD&gt; tag,
reformatting the content value with "X;url=myURL", where X is the number of seconds
to wait before initiating the redirect, and myURL is the destination URL. Any browsers
will obey Meta-Refresh, regardless of JavaScript's enabled setting, but the simple
implementation brings with it simple features. Meta-Refresh will redirect any request
the page, regardless of the query string, and there is no simple way to enable it
only for the specific key/value query string pair. Because all WordPress requests
are to the domain root--a single page--and referenced by query string, this would
not work for my needs. If the old request was instead to a unique former page, such
as /post56.html, I could go create a new copy of post56.html as just a stub, and have
each page Meta-Refresh to the post's new location. But even if this did apply, it's
too much work to create 56 stub pages for 56 former posts.
</p>
        <h3>JavaScript Redirect
</h3>
        <pre class="javascript:nocontrols" name="code">&lt;script type="text/javascript"&gt;
&lt;!--
window.location = "http://www.cptloadtest.com/"
//--&gt;
&lt;/script&gt;</pre>
        <p>
This one requires JavaScript to work. Since the query string is on the domain root,
the request is serving up Default.aspx and applying the query string to it. DasBlog
doesn't observe the "p" query string key, so it will not perform any action against
it, but the query string is still available to client-side scripts. I can add JavaScript
code to perform regular expression matches on the URL (window.location), and upon
match rewrite the old URL to the new and redirect. It's relatively simple to create
new match patterns for each of my 56 posts, and I can place all of my new client-side
code atop Default.aspx.
</p>
        <pre class="javascript:nocontrols" name="code">var oldPath = "/?p=56";
var newPath = "/2006/05/31/VSNetMacroCollapseAll.aspx";
if (document.URL.indexOf(oldPath) &gt; 0)
{
  window.location.replace(document.URL.replace(oldPath, newPath));
}</pre>
        <p>
However, since the patterns are in client-side code, they are visible to end-users
who view source. Users will also see page-flicker, as the Default.aspx is served up
using the old URL, only to be redirected and refreshed under the new URL; a side-effect
of downloading the page twice is that my bandwidth is also doubled for that single
request, since users downloaded the page twice.
</p>
        <h3>What it all means
</h3>
        <p>
All of the options above result in functionality similar a HTTP 302, otherwise known
as a Temporary Redirect. This class of redirect is meant for simple forwarding or
consolidation that is either of temporary nature or part of intended functional implementation.
An example of where this would be used is if after one page is finished processing,
another should be returned, such as if authentication is complete on a login page
and the client should be redirected to a home page or landing page. With a 302, the
original page is still a valid page, and users should still go to it in the future,
but under certain scenarios there is an alternate page should be used.
</p>
        <p>
The alternative to a 302 is a HTTP 301, otherwise known as Moved or a Permanent Redirect.
The 301 is for files which have permanently changed locations and come with an implied
"please update your links" notice. The HTTP 301 is ultimately what I was looking for.
cptloadtest.com/?p=56 is a defunct URL that will never again see light of day; users,
web sites, and (most importantly) search engines should update their references to
the new DasBlog format of the post's URL. Client-side coding doesn't have the ability
to create an HTTP 301, so it was beginning to look like I may either have to modify
DasBlog code to get my 301s or live without. But, I found a way; this site now has
all of the 301 goodness I craved, while keeping the DasBlog code pure.
</p>
        <p>
It's all about HTTP Modules.
</p>
        <p>
In <a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx">Part
2</a>, I will go over how to use HTTP Modules to implement both HTTP 301 and HTTP
302 redirects, all with simply dropping a file into your application bin and adding
a new section to your web.config. No compile required.
</p>
        <h3>URL Rewrite
</h3>
        <ul>
          <li>
Part 1: HTTP 302, Temporarily Relocated 
</li>
          <li>
Part 2: <a href="http://www.cptloadtest.com/2008/11/11/URLRewritePart2HTTP301MovedPermanently.aspx">HTTP
301, Moved Permanently</a></li>
          <li>
Part 3: <a href="http://www.cptloadtest.com/2008/12/04/URLRewritePart3ImprovingSEOAndTheWwwSubdomain.aspx">Improving
SEO and the 'www' subdomain</a></li>
        </ul>
        <div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:92bfc308-01b6-42cf-9a1e-c8cef5065b89" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati
Tags: <a href="http://technorati.com/tags/HTTP%20302" rel="tag">HTTP 302</a>,<a href="http://technorati.com/tags/URL%20Redirects" rel="tag">URL
Redirects</a></div>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=8e086b43-7342-4790-acfd-0b35ae0451c7" />
      </body>
      <title>URL Rewrite, Part 1: HTTP 302, Temporarily Relocated</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,8e086b43-7342-4790-acfd-0b35ae0451c7.aspx</guid>
      <link>http://www.cptloadtest.com/2008/11/06/URL-Rewrite-Part-1-HTTP-302-Temporarily-Relocated.aspx</link>
      <pubDate>Thu, 06 Nov 2008 15:01:33 GMT</pubDate>
      <description>&lt;p&gt;
A few months ago I switched my blogging engine from WordPress to DasBlog. Though I
do feel that WordPress is a more mature engine, with a more robust feature set and
a better plug-in community, I wanted a site that was built on .NET. Being a .NET developer,
I wanted something I could tinker with,&amp;nbsp; modify, and adjust to my liking.
&lt;/p&gt;
&lt;h3&gt;Redirecting WordPress URL Format to DasBlog
&lt;/h3&gt;
&lt;p&gt;
One of the pain points of the switch was with the differences in how the two blogging
engines generated their URLs. As an example, my post on the &lt;a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx"&gt;Collapse
All macro for the Visual Studio Solution Explorer&lt;/a&gt;, originally written in WordPress,
went from a URL of &lt;a href="http://www.cptloadtest.com/?p=56"&gt;cptloadtest.com/?p=56&lt;/a&gt; to &lt;a href="http://www.cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx"&gt;cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx&lt;/a&gt;.
A few sites, such as &lt;a href="http://www.chinhdo.com/20070920/top-11-visual-studio-2005-ide-tips-and-tricks-to-make-you-a-more-productive-developer/"&gt;Chinhdo.com&lt;/a&gt;,
link to the post's old URL, which without effort to put a redirect in place would
return HTTP 404: File Not Found under the new engine.
&lt;/p&gt;
&lt;p&gt;
Enter URL redirects. I needed a way to translate one URL into another. More specifically,
since WordPress retrieves all of its posts by query string (using the 'p' key), I
needed to translate a specific query string key/value pair into a URL. But, I didn't
want to have to recompile any code.
&lt;/p&gt;
&lt;p&gt;
There are a view client-side redirecting options available:
&lt;/p&gt;
&lt;h3&gt;Meta Refresh
&lt;/h3&gt;
&lt;pre class="html:nocontrols" name="code"&gt;&amp;lt;meta http-equiv="refresh" content="0;url=http://www.cptloadtest.com/"&amp;gt;&lt;/pre&gt;
&lt;p&gt;
The Old-School HTML way of redirecting a page. Nothing but HTML is needed. Only access
to the base HTML page is required. Place the above HTML within your &amp;lt;HEAD&amp;gt; tag,
reformatting the content value with "X;url=myURL", where X is the number of seconds
to wait before initiating the redirect, and myURL is the destination URL. Any browsers
will obey Meta-Refresh, regardless of JavaScript's enabled setting, but the simple
implementation brings with it simple features. Meta-Refresh will redirect any request
the page, regardless of the query string, and there is no simple way to enable it
only for the specific key/value query string pair. Because all WordPress requests
are to the domain root--a single page--and referenced by query string, this would
not work for my needs. If the old request was instead to a unique former page, such
as /post56.html, I could go create a new copy of post56.html as just a stub, and have
each page Meta-Refresh to the post's new location. But even if this did apply, it's
too much work to create 56 stub pages for 56 former posts.
&lt;/p&gt;
&lt;h3&gt;JavaScript Redirect
&lt;/h3&gt;
&lt;pre class="javascript:nocontrols" name="code"&gt;&amp;lt;script type="text/javascript"&amp;gt;
&amp;lt;!--
window.location = "http://www.cptloadtest.com/"
//--&amp;gt;
&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;
This one requires JavaScript to work. Since the query string is on the domain root,
the request is serving up Default.aspx and applying the query string to it. DasBlog
doesn't observe the "p" query string key, so it will not perform any action against
it, but the query string is still available to client-side scripts. I can add JavaScript
code to perform regular expression matches on the URL (window.location), and upon
match rewrite the old URL to the new and redirect. It's relatively simple to create
new match patterns for each of my 56 posts, and I can place all of my new client-side
code atop Default.aspx.
&lt;/p&gt;
&lt;pre class="javascript:nocontrols" name="code"&gt;var oldPath = "/?p=56";
var newPath = "/2006/05/31/VSNetMacroCollapseAll.aspx";
if (document.URL.indexOf(oldPath) &amp;gt; 0)
{
  window.location.replace(document.URL.replace(oldPath, newPath));
}&lt;/pre&gt;
&lt;p&gt;
However, since the patterns are in client-side code, they are visible to end-users
who view source. Users will also see page-flicker, as the Default.aspx is served up
using the old URL, only to be redirected and refreshed under the new URL; a side-effect
of downloading the page twice is that my bandwidth is also doubled for that single
request, since users downloaded the page twice.
&lt;/p&gt;
&lt;h3&gt;What it all means
&lt;/h3&gt;
&lt;p&gt;
All of the options above result in functionality similar a HTTP 302, otherwise known
as a Temporary Redirect. This class of redirect is meant for simple forwarding or
consolidation that is either of temporary nature or part of intended functional implementation.
An example of where this would be used is if after one page is finished processing,
another should be returned, such as if authentication is complete on a login page
and the client should be redirected to a home page or landing page. With a 302, the
original page is still a valid page, and users should still go to it in the future,
but under certain scenarios there is an alternate page should be used.
&lt;/p&gt;
&lt;p&gt;
The alternative to a 302 is a HTTP 301, otherwise known as Moved or a Permanent Redirect.
The 301 is for files which have permanently changed locations and come with an implied
"please update your links" notice. The HTTP 301 is ultimately what I was looking for.
cptloadtest.com/?p=56 is a defunct URL that will never again see light of day; users,
web sites, and (most importantly) search engines should update their references to
the new DasBlog format of the post's URL. Client-side coding doesn't have the ability
to create an HTTP 301, so it was beginning to look like I may either have to modify
DasBlog code to get my 301s or live without. But, I found a way; this site now has
all of the 301 goodness I craved, while keeping the DasBlog code pure.
&lt;/p&gt;
&lt;p&gt;
It's all about HTTP Modules.
&lt;/p&gt;
&lt;p&gt;
In &lt;a href="http://www.cptloadtest.com/2008/11/06/URLRewritePart1HTTP302TemporarilyRelocated.aspx"&gt;Part
2&lt;/a&gt;, I will go over how to use HTTP Modules to implement both HTTP 301 and HTTP
302 redirects, all with simply dropping a file into your application bin and adding
a new section to your web.config. No compile required.
&lt;/p&gt;
&lt;h3&gt;URL Rewrite
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
Part 1: HTTP 302, Temporarily Relocated 
&lt;li&gt;
Part 2: &lt;a href="http://www.cptloadtest.com/2008/11/11/URLRewritePart2HTTP301MovedPermanently.aspx"&gt;HTTP
301, Moved Permanently&lt;/a&gt; 
&lt;li&gt;
Part 3: &lt;a href="http://www.cptloadtest.com/2008/12/04/URLRewritePart3ImprovingSEOAndTheWwwSubdomain.aspx"&gt;Improving
SEO and the 'www' subdomain&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:92bfc308-01b6-42cf-9a1e-c8cef5065b89" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati
Tags: &lt;a href="http://technorati.com/tags/HTTP%20302" rel="tag"&gt;HTTP 302&lt;/a&gt;,&lt;a href="http://technorati.com/tags/URL%20Redirects" rel="tag"&gt;URL
Redirects&lt;/a&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=8e086b43-7342-4790-acfd-0b35ae0451c7" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,8e086b43-7342-4790-acfd-0b35ae0451c7.aspx</comments>
      <category>ASP.Net</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=31b3c96d-5f73-4a20-bc3c-c155b5238071</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,31b3c96d-5f73-4a20-bc3c-c155b5238071.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,31b3c96d-5f73-4a20-bc3c-c155b5238071.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=31b3c96d-5f73-4a20-bc3c-c155b5238071</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, I was writing unit tests for a web application built on Castle ActiveRecord.
My goal was to mock ActiveRecord's data store, rather than use a Microsoft SQL Server
database for testing. SQL Server backing just would not fit my needs, where a mock
data store would serve much better: 
</p>
        <ul>
          <li>
I did not want a SQL Server installation to be a requirement for me, the other developers,
and my Continuous Integration server. 
</li>
          <li>
I wanted something fast. I didn't want to have to wait for SQL Server to build / tear
down my schema. 
</li>
          <li>
I wanted something isolated, so the other developers, and my CI server, and I wouldn't
have contention over the same database, but didn't want to have to deal with independent
SQL Server instances for everyone.</li>
        </ul>
        <p>
Essentially what I wanted was a local, in-memory database that could be quickly initialized
and destroyed specifically for my tests. The resolution was using SQLite for ADO.Net,
using an in-memory SQLite instance. <a href="http://brian.genisio.org/2008/07/active-record-mock-framework.html">Brian
Genisio</a> has a fantastic write-up on mocking the data store for Castle ActiveRecord
using this SQLite for ADO.Net. The post made my day, since I was looking for a way
to do this, and he had already done all of the work &lt;grin/&gt;. I encourage you
to read <a href="http://brian.genisio.org/2008/07/active-record-mock-framework.html">his
post</a> first, as the rest of this post assumes you have already done so.
</p>
        <p>
Brian's post was a great help to me; I made a few enhancements to what he started
to make it fit my needs even more. 
</p>
        <p>
My updated version of Brian's ActiveRecordMockConnectionProvider class:
</p>
        <pre class="csharp:nocontrols" name="code">using System;
using System.Collections;
using System.Data;
using System.Reflection;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
using Castle.ActiveRecord.Framework.Config;
using NHibernate.Connection;

namespace ActiveRecordTestHelper
{
  public class ActiveRecordMockConnectionProvider : DriverConnectionProvider
  {
    private static IDbConnection _connection;

    private static IConfigurationSource MockConfiguration
    {
      get
      {
        var properties = new Hashtable
            {
              {"hibernate.connection.driver_class",
                "NHibernate.Driver.SQLite20Driver"},
              {"hibernate.dialect", "NHibernate.Dialect.SQLiteDialect"},
              {"hibernate.connection.provider", ConnectionProviderLocator},
              {"hibernate.connection.connection_string",
                "Data Source=:memory:;Version=3;New=True;"}
            };

        var source = new InPlaceConfigurationSource();
        source.Add(typeof (ActiveRecordBase), properties);

        return source;
      }
    }

    private static string ConnectionProviderLocator
    {
      get { return String.Format("{0}, {1}", TypeOfEnclosingClass.FullName,
                                    EnclosingAssemblyName.Split(',')[0]); }
    }

    private static Type TypeOfEnclosingClass
    {
      get { return MethodBase.GetCurrentMethod().DeclaringType; }
    }

    private static string EnclosingAssemblyName
    {
      get { return Assembly.GetAssembly(TypeOfEnclosingClass).FullName; }
    }

    public override IDbConnection GetConnection()
    {
      if (_connection == null)
        _connection = base.GetConnection();

      return _connection;
    }

    public override void CloseConnection(IDbConnection conn) {}

    /// &lt;summary&gt;
    /// Destroys the connection that is kept open in order to keep the
    /// in-memory database alive. Destroying the connection will destroy
    /// all of the data stored in the mock database. Call this method when
    /// the test is complete.
    /// &lt;/summary&gt;
    public static void ExplicitlyDestroyConnection()
    {
      if (_connection != null)
      {
        _connection.Close();
        _connection = null;
      }
    }

    /// &lt;summary&gt;
    /// Initializes ActiveRecord and the Database that ActiveRecord uses to
    /// store the data. Call this method before the test executes.
    /// &lt;/summary&gt;
    /// &lt;param name="useDynamicConfiguration"&gt;
    /// Use reflection to build configuration, rather than the Configuration
    /// file.
    /// &lt;/param&gt;
    /// &lt;param name="types"&gt;
    /// A list of ActiveRecord types that will be created in the database
    /// &lt;/param&gt;
    public static void InitializeActiveRecord(bool useDynamicConfiguration,
                                              params Type[] types)
    {
      ActiveRecordStarter.ResetInitializationFlag();
      IConfigurationSource configurationSource = useDynamicConfiguration
                                       ? MockConfiguration
                                       : ActiveRecordSectionHandler.Instance;
      ActiveRecordStarter.Initialize(configurationSource, types);
      ActiveRecordStarter.CreateSchema();
    }

    /// &lt;summary&gt;
    /// Initializes ActiveRecord and the Database that ActiveRecord uses to
    /// store the data based. Configuration is dynamically generated using
    /// reflection. Call this method before the test executes.
    /// &lt;/summary&gt;
    /// &lt;param name="types"&gt;
    /// A list of ActiveRecord types that will be created in the database
    /// &lt;/param&gt;
    [Obsolete("Use InitializeActiveRecord(bool, params Type[])")]
    public static void InitializeActiveRecord(params Type[] types)
    {
      InitializeActiveRecord(true, types);
    }
  }
}
</pre>
        <p>
In my class I have overloaded the method InitializeActiveRecord to include the boolean
parameter useDynamicConfiguration, governing if the configuration is dynamically built
using Reflection or if the configuration in your app.config is used instead. If the
parameter is not specified, it default to false (Use app.config).
</p>
        <p>
Why? Brian's original code, as is, is meant to be dropped in as a new class within
your test assembly, and uses reflection to dynamically determine the provider information,
including the fully-qualified class name and assembly of the new DriverConnectionProvider.
Reflection makes for little effort for me when I want to drop in the class into a
new test assembly. Drop it in and go; no need to even modify the app.config. However,
if I want to switch my provider back to SQL Server or some other platform, I have
to modify the code and recompile.
</p>
        <p>
My modifications remove the restriction of configuration in compiled code, allow configuration
to be placed in app.config, while preserving the existing functionality for backward
compatibility. By allowing app.config-based configuration, users can quickly switch
back-and-forth between SQLite and SQL Server databases without having to modify and
recompile the application. To use this customized ActiveRecordMockConnectionProvider
class without dynamic configuration, add the following code to the configuration block
of your test's app.config.
</p>
        <pre class="xml:nocontrols:nogutter" name="code">&lt;activerecord&gt;
  &lt;config&gt;
    &lt;add key="hibernate.connection.driver_class"
      value="NHibernate.Driver.SQLite20Driver" /&gt;
    &lt;add key="hibernate.dialect" value="NHibernate.Dialect.SQLiteDialect" /&gt;
    &lt;add key="hibernate.connection.provider"
      value="ActiveRecordTestHelper.ActiveRecordMockConnectionProvider, ActiveRecordTestHelper" /&gt;
    &lt;add key="hibernate.connection.connection_string"
      value="Data Source=:memory:;Version=3;New=True;" /&gt;
  &lt;/config&gt;
&lt;/activerecord&gt;</pre>
        <p>
The catch is that you will need to know the fully-qualified class and assembly information
for your provider (Line 6, above). This means you will have to modify it for every
test assembly. To get around this, compile the code into a separate assembly (I called
mine 'ActiveRecordTestHelper.dll'), and reference this new assembly in your test assembly.
By using a separate assembly, you no longer need to modify the activerecord configuration
block for every instance, and can reuse the same block everywhere the new assembly
is referenced.
</p>
        <p>
And to switch over from in-memory SQLite to SQL Server, just comment out the SQLite
block and uncomment the SQL Server block (or whatever other provider you are using).
</p>
        <blockquote>
          <p>
            <b>Download:</b>
            <a href="http://www.cptloadtest.com/content/binary/ActiveRecordMockConnectionProvider.zip">ActiveRecordMockConnectionProvider.zip</a>
            <br />
Includes:
</p>
          <ul>
            <li>
Source code for the <em>ActiveRecordMockConnectionProvider</em> class 
</li>
            <li>
Sample Class that uses the new provider 
</li>
            <li>
Sample <em>app.config</em> containing the ActiveRecord block using the provider. 
</li>
            <li>
Compiled versions of <em>ActiveRecordTestHelper.dll</em></li>
          </ul>
          <p>
As always, this code is provided with no warranties or guarantees. Use at your own
risk. Your mileage may vary.<br />
And thanks again to Brian Genisio.
</p>
        </blockquote>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=31b3c96d-5f73-4a20-bc3c-c155b5238071" />
      </body>
      <title>Unit Testing ActiveRecord Applications using Mock Databases</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,31b3c96d-5f73-4a20-bc3c-c155b5238071.aspx</guid>
      <link>http://www.cptloadtest.com/2008/10/30/Unit-Testing-ActiveRecord-Applications-Using-Mock-Databases.aspx</link>
      <pubDate>Thu, 30 Oct 2008 14:10:01 GMT</pubDate>
      <description>&lt;p&gt;
Recently, I was writing unit tests for a web application built on Castle ActiveRecord.
My goal was to mock ActiveRecord's data store, rather than use a Microsoft SQL Server
database for testing. SQL Server backing just would not fit my needs, where a mock
data store would serve much better: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
I did not want a SQL Server installation to be a requirement for me, the other developers,
and my Continuous Integration server. 
&lt;li&gt;
I wanted something fast. I didn't want to have to wait for SQL Server to build / tear
down my schema. 
&lt;li&gt;
I wanted something isolated, so the other developers, and my CI server, and I wouldn't
have contention over the same database, but didn't want to have to deal with independent
SQL Server instances for everyone.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Essentially what I wanted was a local, in-memory database that could be quickly initialized
and destroyed specifically for my tests. The resolution was using SQLite for ADO.Net,
using an in-memory SQLite instance. &lt;a href="http://brian.genisio.org/2008/07/active-record-mock-framework.html"&gt;Brian
Genisio&lt;/a&gt; has a fantastic write-up on mocking the data store for Castle ActiveRecord
using this SQLite for ADO.Net. The post made my day, since I was looking for a way
to do this, and he had already done all of the work &amp;lt;grin/&amp;gt;. I encourage you
to read &lt;a href="http://brian.genisio.org/2008/07/active-record-mock-framework.html"&gt;his
post&lt;/a&gt; first, as the rest of this post assumes you have already done so.
&lt;/p&gt;
&lt;p&gt;
Brian's post was a great help to me; I made a few enhancements to what he started
to make it fit my needs even more. 
&lt;/p&gt;
&lt;p&gt;
My updated version of Brian's ActiveRecordMockConnectionProvider class:
&lt;/p&gt;
&lt;pre class="csharp:nocontrols" name="code"&gt;using System;
using System.Collections;
using System.Data;
using System.Reflection;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
using Castle.ActiveRecord.Framework.Config;
using NHibernate.Connection;

namespace ActiveRecordTestHelper
{
  public class ActiveRecordMockConnectionProvider : DriverConnectionProvider
  {
    private static IDbConnection _connection;

    private static IConfigurationSource MockConfiguration
    {
      get
      {
        var properties = new Hashtable
            {
              {"hibernate.connection.driver_class",
                "NHibernate.Driver.SQLite20Driver"},
              {"hibernate.dialect", "NHibernate.Dialect.SQLiteDialect"},
              {"hibernate.connection.provider", ConnectionProviderLocator},
              {"hibernate.connection.connection_string",
                "Data Source=:memory:;Version=3;New=True;"}
            };

        var source = new InPlaceConfigurationSource();
        source.Add(typeof (ActiveRecordBase), properties);

        return source;
      }
    }

    private static string ConnectionProviderLocator
    {
      get { return String.Format("{0}, {1}", TypeOfEnclosingClass.FullName,
                                    EnclosingAssemblyName.Split(',')[0]); }
    }

    private static Type TypeOfEnclosingClass
    {
      get { return MethodBase.GetCurrentMethod().DeclaringType; }
    }

    private static string EnclosingAssemblyName
    {
      get { return Assembly.GetAssembly(TypeOfEnclosingClass).FullName; }
    }

    public override IDbConnection GetConnection()
    {
      if (_connection == null)
        _connection = base.GetConnection();

      return _connection;
    }

    public override void CloseConnection(IDbConnection conn) {}

    /// &amp;lt;summary&amp;gt;
    /// Destroys the connection that is kept open in order to keep the
    /// in-memory database alive. Destroying the connection will destroy
    /// all of the data stored in the mock database. Call this method when
    /// the test is complete.
    /// &amp;lt;/summary&amp;gt;
    public static void ExplicitlyDestroyConnection()
    {
      if (_connection != null)
      {
        _connection.Close();
        _connection = null;
      }
    }

    /// &amp;lt;summary&amp;gt;
    /// Initializes ActiveRecord and the Database that ActiveRecord uses to
    /// store the data. Call this method before the test executes.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="useDynamicConfiguration"&amp;gt;
    /// Use reflection to build configuration, rather than the Configuration
    /// file.
    /// &amp;lt;/param&amp;gt;
    /// &amp;lt;param name="types"&amp;gt;
    /// A list of ActiveRecord types that will be created in the database
    /// &amp;lt;/param&amp;gt;
    public static void InitializeActiveRecord(bool useDynamicConfiguration,
                                              params Type[] types)
    {
      ActiveRecordStarter.ResetInitializationFlag();
      IConfigurationSource configurationSource = useDynamicConfiguration
                                       ? MockConfiguration
                                       : ActiveRecordSectionHandler.Instance;
      ActiveRecordStarter.Initialize(configurationSource, types);
      ActiveRecordStarter.CreateSchema();
    }

    /// &amp;lt;summary&amp;gt;
    /// Initializes ActiveRecord and the Database that ActiveRecord uses to
    /// store the data based. Configuration is dynamically generated using
    /// reflection. Call this method before the test executes.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name="types"&amp;gt;
    /// A list of ActiveRecord types that will be created in the database
    /// &amp;lt;/param&amp;gt;
    [Obsolete("Use InitializeActiveRecord(bool, params Type[])")]
    public static void InitializeActiveRecord(params Type[] types)
    {
      InitializeActiveRecord(true, types);
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;
In my class I have overloaded the method InitializeActiveRecord to include the boolean
parameter useDynamicConfiguration, governing if the configuration is dynamically built
using Reflection or if the configuration in your app.config is used instead. If the
parameter is not specified, it default to false (Use app.config).
&lt;/p&gt;
&lt;p&gt;
Why? Brian's original code, as is, is meant to be dropped in as a new class within
your test assembly, and uses reflection to dynamically determine the provider information,
including the fully-qualified class name and assembly of the new DriverConnectionProvider.
Reflection makes for little effort for me when I want to drop in the class into a
new test assembly. Drop it in and go; no need to even modify the app.config. However,
if I want to switch my provider back to SQL Server or some other platform, I have
to modify the code and recompile.
&lt;/p&gt;
&lt;p&gt;
My modifications remove the restriction of configuration in compiled code, allow configuration
to be placed in app.config, while preserving the existing functionality for backward
compatibility. By allowing app.config-based configuration, users can quickly switch
back-and-forth between SQLite and SQL Server databases without having to modify and
recompile the application. To use this customized ActiveRecordMockConnectionProvider
class without dynamic configuration, add the following code to the configuration block
of your test's app.config.
&lt;/p&gt;
&lt;pre class="xml:nocontrols:nogutter" name="code"&gt;&amp;lt;activerecord&amp;gt;
  &amp;lt;config&amp;gt;
    &amp;lt;add key="hibernate.connection.driver_class"
      value="NHibernate.Driver.SQLite20Driver" /&amp;gt;
    &amp;lt;add key="hibernate.dialect" value="NHibernate.Dialect.SQLiteDialect" /&amp;gt;
    &amp;lt;add key="hibernate.connection.provider"
      value="ActiveRecordTestHelper.ActiveRecordMockConnectionProvider, ActiveRecordTestHelper" /&amp;gt;
    &amp;lt;add key="hibernate.connection.connection_string"
      value="Data Source=:memory:;Version=3;New=True;" /&amp;gt;
  &amp;lt;/config&amp;gt;
&amp;lt;/activerecord&amp;gt;&lt;/pre&gt;
&lt;p&gt;
The catch is that you will need to know the fully-qualified class and assembly information
for your provider (Line 6, above). This means you will have to modify it for every
test assembly. To get around this, compile the code into a separate assembly (I called
mine 'ActiveRecordTestHelper.dll'), and reference this new assembly in your test assembly.
By using a separate assembly, you no longer need to modify the activerecord configuration
block for every instance, and can reuse the same block everywhere the new assembly
is referenced.
&lt;/p&gt;
&lt;p&gt;
And to switch over from in-memory SQLite to SQL Server, just comment out the SQLite
block and uncomment the SQL Server block (or whatever other provider you are using).
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;b&gt;Download:&lt;/b&gt; &lt;a href="http://www.cptloadtest.com/content/binary/ActiveRecordMockConnectionProvider.zip"&gt;ActiveRecordMockConnectionProvider.zip&lt;/a&gt;
&lt;br&gt;
Includes:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Source code for the &lt;em&gt;ActiveRecordMockConnectionProvider&lt;/em&gt; class 
&lt;li&gt;
Sample Class that uses the new provider 
&lt;li&gt;
Sample &lt;em&gt;app.config&lt;/em&gt; containing the ActiveRecord block using the provider. 
&lt;li&gt;
Compiled versions of &lt;em&gt;ActiveRecordTestHelper.dll&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
As always, this code is provided with no warranties or guarantees. Use at your own
risk. Your mileage may vary.&lt;br&gt;
And thanks again to Brian Genisio.
&lt;/p&gt;
&lt;/blockquote&gt;&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=31b3c96d-5f73-4a20-bc3c-c155b5238071" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,31b3c96d-5f73-4a20-bc3c-c155b5238071.aspx</comments>
      <category>Programming</category>
      <category>Testing</category>
      <category>Tools</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=b653e6d4-37a9-445d-b3d6-44a668d37b6f</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,b653e6d4-37a9-445d-b3d6-44a668d37b6f.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,b653e6d4-37a9-445d-b3d6-44a668d37b6f.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=b653e6d4-37a9-445d-b3d6-44a668d37b6f</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
At the <a href="http://www.devlink.net/">devLink Technical Conference</a>, one of
the Open Spaces focused on Computer Science curriculum at universities, and what things
that the developer community would CRUD on the CompSci tradition. Though I did not
have opportunity to participate in the discussion—I was facilitating an Open Space
on Continuous Integration, next door—I do have one proposal: "Writing." For Computer
Scientists—a traditionally introverted and communication-challenged group—programming
in English (substitute with your native language) should be paramount. Communicating
to humans is part of our job description, and we must be able to do so effectively
and using their language, whether it be for status updates, business justifications,
SOWs, proposals, or just another email. Developers need to communicate effectively;
write well rather than write good. We must be right like a writer.
</p>
        <p>
We programmers should write like we code. The written word should be concise, to the
point, just like code. Coders do not frivolously use fancy namespaces and complicated
classes so that their code looks smart, as it has the opposite effect by resulting
in bloated, inefficient, unmaintainable systems. Big words implemented frivolously
for the sake of sounding smart perform the opposite function, and likewise result
in bloated, inefficient, unmaintanable text. We avoid power robbers in our code, such
as using string builders rather than underperforming string concatenations, and should
avoid similar performance kills in our writing. Additionally, using the wrong keyword
in code, or misusing grammatical marks in our code, results in compiler errors or
runtime errors. The written word—a language void of any compiler benefits—throws runtime
exceptions on execution when it is improperly authored, much like JavaScript or XSL.
</p>
        <blockquote>“Vigorous writing is concise. A sentence should contain no unnecessary
words, a paragraph no unnecessary sentences, for the same reason that a drawing should
have no unnecessary lines and a machine no unnecessary parts. This requires not that
the writer make all sentences short or avoid all detail and treat subjects only in
outline, but that every word tell.” — William Strunk</blockquote>
        <p>
But like a programming language, English is simply a matter of keywords and laws.
We must learn the rules of the system; we must learn its syntax; we must learn how
to test and validate our code before shipping it off to a client or to production.
Approaching the English language like we approach a programming language would also
provide an effective learning mechanism for us developer-types. This would make an
effective course at university: "Writing : For Programmers." Learn English like we
learn any other language—approach it using our virtues—as what works for us may not
be the same path that works for an English major.
</p>
        <p>
Throughout my career, I have noticed a few areas that are typically mis-coded. I have
included a few items below that every developer should be aware of to help learn English's
keywords, its laws, and to provide opportunities to improve end-user experience.
</p>
        <p>
        </p>
        <h3>Knowing the Language at an Elementary Level
</h3>
        <ol>
          <li>
            <strong>Homonyms</strong> : words that sound the same but can mean different things.
This is often a challenge for people new to English, but even veterans get confused.
Everyone should learn the difference, and make proper use a habit. And proof read,
as spell check will not catch misuse of homonyms. This applies to:</li>
        </ol>
        <ul>
          <li>
Their / There / They're</li>
          <li>
To / Too / Two</li>
          <li>
Your / You're</li>
          <li>
Its / It's</li>
          <li>
Hear / Here</li>
          <li>
Threw / Through</li>
          <li>
Write / Right<br /></li>
        </ul>
        <li>
          <strong>
            <em>Irregardless</em>
          </strong> is not a word.</li>
        <li>
          <strong>
            <em>Who</em> vs. <em>Whom</em></strong> : <em>Who</em>, the subject, is doing
the acting, and <em>whom</em>, the object, is being acted upon. The shortcut is to
use <em>who</em> and <em>whom</em> as you would <em>he</em> and <em>him</em>. (Remember
that <em>him</em> and <em>whom</em> both end in "m".) &lt;Who did what to whom for
how many jellybeans? He did that to him for five jellybeans.&gt;</li>
        <li>
          <strong>
            <em>Me</em> vs. <em>I</em></strong> : Follow the same rules as for <em>who</em> vs. <em>whom</em>,
above. The <em>subject</em> is doing the acting, and the <em>object</em> is being
acted upon. Subject pronouns are <em>I</em>, <em>he</em>, <em>she</em>, <em>we</em>, <em>they</em>,
and <em>who</em>. Object pronouns are <em>me</em>, <em>him</em>, <em>her</em>, <em>us</em>, <em>them</em>,
and <em>whom</em>. &lt;Sally gave me five dollars. I used to money to buy lunch.&gt;</li>
        <li>
          <strong>
            <em>Than</em> vs. <em>Then</em></strong> : A comparison (<em>than</em>) vs.
a measure of time (<em>then</em>). In code, <em>than</em> is used when describing
a comparison operator; the '&gt;' operator is a greater-<em>than</em> operator. In
code, time sequences are an <em>if...then</em> statement. &lt;Apples are better than
oranges. I will eat my apple first, then I will eat my orange.&gt;<br /></li>
        <h3>Knowing the Language at a High School Level
</h3>
        <ol>
          <li>
            <strong>Power Robbers</strong> : Never use <em>due to the fact that</em>. It weakens
your sentence. Use <em>because</em>.</li>
          <li>
            <strong>Contractions</strong> : In formal writing (e.g. Proposals, SOWs), avoid contractions.
Contractions are for casual writing. Think along the lines of a Debug Build versus
a Release Build.</li>
          <li>
            <strong>
              <em>Simply</em> &amp; <em>Obviously</em></strong> : Avoid using <em>simply</em> and <em>obviously</em> as
it may be both to you, but neither to your audience. If it was simple or obvious,
then you didn't need to write it.</li>
          <li>
            <strong>Use one space</strong> after a sentence, not two. A PC is not a typewriter.
On a typewriter, with fixed-width fonts, two spaces are preferred, but on a PC, True
Type fonts will properly space "&lt;dot&gt;&lt;space&gt;" for you. Don't believe me?
Open up any book and look at the spaces between sentences. Microsoft Word has an option
to indicate this for you under grammar preferences.</li>
          <li>
            <strong>
              <em>Effect</em> vs. <em>Affect</em></strong> : <em>Effect</em> is the result, <em>affect</em> is
the action. Noun and verb. &lt;Poor engine performance is the effect of ignored maintenance.
Ignoring maintenance affects engine performance.&gt;<br /></li>
        </ol>
        <h3>Knowing the Language at a Collegiate Level
</h3>
        <ol>
          <li>
            <strong>Lists</strong> : Just like when defining an array, use a comma after every
item in a list except the last. This includes before "and." &lt;I like red, white,
and blue.&gt;</li>
          <li>
            <strong>
              <em>i.e.</em> vs. <em>e.g.</em></strong> : The first is <em>in other words</em> and
the second is <em>for example</em>, though this does not do much for clarity. Essentially, <em>i.e.</em> is
a complete, clarifying list, while <em>e.g.</em> is an incomplete list of examples.
&lt;I watch the three stooges (i.e., Larry, Curly, and Moe). I like all four-player
card games (e.g., Euchre, Spades, and Hearts).&gt;</li>
          <li>
            <strong>Semicolons</strong> : Semicolons are used to separate two independent yet
related clauses that could be broken into separate sentences. &lt;The water is very
hot; I hope I don't burn myself.&gt; Also, use semicolons to separate items in a list
where the items contain commas. &lt;When the cards were dealt, Jack had a straight;
Sally had two nines, two fives, and a queen; and George had a full house.&gt;<br /></li>
        </ol>
        <p>
Be mindful of your native language. It is the one you use the most, even more than
C#, or Ruby, or Java. If you don't already own a copy, pick up <em><a href="http://www.amazon.com/gp/product/0205313426/?tag=cptloadte-20">The
Elements of Style</a></em> by Strunk &amp; White; if you do own a copy, either have
it at your desk so you can use it, or give it to someone who will. Effectively communicating
with humans, using their rules, will help you have better testing, better design,
better requirements, and have a better job. Become an effective English developer,
and it will help you be a more effective developer, overall.
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=b653e6d4-37a9-445d-b3d6-44a668d37b6f" />
      </body>
      <title>Right like a Writer</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,b653e6d4-37a9-445d-b3d6-44a668d37b6f.aspx</guid>
      <link>http://www.cptloadtest.com/2008/09/11/Right-Like-A-Writer.aspx</link>
      <pubDate>Thu, 11 Sep 2008 19:30:33 GMT</pubDate>
      <description>&lt;p&gt;
At the &lt;a href="http://www.devlink.net/"&gt;devLink Technical Conference&lt;/a&gt;, one of
the Open Spaces focused on Computer Science curriculum at universities, and what things
that the developer community would CRUD on the CompSci tradition. Though I did not
have opportunity to participate in the discussion—I was facilitating an Open Space
on Continuous Integration, next door—I do have one proposal: "Writing." For Computer
Scientists—a traditionally introverted and communication-challenged group—programming
in English (substitute with your native language) should be paramount. Communicating
to humans is part of our job description, and we must be able to do so effectively
and using their language, whether it be for status updates, business justifications,
SOWs, proposals, or just another email. Developers need to communicate effectively;
write well rather than write good. We must be right like a writer.
&lt;/p&gt;
&lt;p&gt;
We programmers should write like we code. The written word should be concise, to the
point, just like code. Coders do not frivolously use fancy namespaces and complicated
classes so that their code looks smart, as it has the opposite effect by resulting
in bloated, inefficient, unmaintainable systems. Big words implemented frivolously
for the sake of sounding smart perform the opposite function, and likewise result
in bloated, inefficient, unmaintanable text. We avoid power robbers in our code, such
as using string builders rather than underperforming string concatenations, and should
avoid similar performance kills in our writing. Additionally, using the wrong keyword
in code, or misusing grammatical marks in our code, results in compiler errors or
runtime errors. The written word—a language void of any compiler benefits—throws runtime
exceptions on execution when it is improperly authored, much like JavaScript or XSL.
&lt;/p&gt;
&lt;blockquote&gt;“Vigorous writing is concise. A sentence should contain no unnecessary
words, a paragraph no unnecessary sentences, for the same reason that a drawing should
have no unnecessary lines and a machine no unnecessary parts. This requires not that
the writer make all sentences short or avoid all detail and treat subjects only in
outline, but that every word tell.” — William Strunk&lt;/blockquote&gt; 
&lt;p&gt;
But like a programming language, English is simply a matter of keywords and laws.
We must learn the rules of the system; we must learn its syntax; we must learn how
to test and validate our code before shipping it off to a client or to production.
Approaching the English language like we approach a programming language would also
provide an effective learning mechanism for us developer-types. This would make an
effective course at university: "Writing : For Programmers." Learn English like we
learn any other language—approach it using our virtues—as what works for us may not
be the same path that works for an English major.
&lt;/p&gt;
&lt;p&gt;
Throughout my career, I have noticed a few areas that are typically mis-coded. I have
included a few items below that every developer should be aware of to help learn English's
keywords, its laws, and to provide opportunities to improve end-user experience.&lt;p&gt;
&lt;h3&gt;Knowing the Language at an Elementary Level
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Homonyms&lt;/strong&gt; : words that sound the same but can mean different things.
This is often a challenge for people new to English, but even veterans get confused.
Everyone should learn the difference, and make proper use a habit. And proof read,
as spell check will not catch misuse of homonyms. This applies to:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;
Their / There / They're&lt;/li&gt;
&lt;li&gt;
To / Too / Two&lt;/li&gt;
&lt;li&gt;
Your / You're&lt;/li&gt;
&lt;li&gt;
Its / It's&lt;/li&gt;
&lt;li&gt;
Hear / Here&lt;/li&gt;
&lt;li&gt;
Threw / Through&lt;/li&gt;
&lt;li&gt;
Write / Right&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Irregardless&lt;/em&gt;&lt;/strong&gt; is not a word.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Who&lt;/em&gt; vs. &lt;em&gt;Whom&lt;/em&gt;&lt;/strong&gt; : &lt;em&gt;Who&lt;/em&gt;, the subject, is doing
the acting, and &lt;em&gt;whom&lt;/em&gt;, the object, is being acted upon. The shortcut is to
use &lt;em&gt;who&lt;/em&gt; and &lt;em&gt;whom&lt;/em&gt; as you would &lt;em&gt;he&lt;/em&gt; and &lt;em&gt;him&lt;/em&gt;. (Remember
that &lt;em&gt;him&lt;/em&gt; and &lt;em&gt;whom&lt;/em&gt; both end in "m".) &amp;lt;Who did what to whom for
how many jellybeans? He did that to him for five jellybeans.&amp;gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Me&lt;/em&gt; vs. &lt;em&gt;I&lt;/em&gt;&lt;/strong&gt; : Follow the same rules as for &lt;em&gt;who&lt;/em&gt; vs. &lt;em&gt;whom&lt;/em&gt;,
above. The &lt;em&gt;subject&lt;/em&gt; is doing the acting, and the &lt;em&gt;object&lt;/em&gt; is being
acted upon. Subject pronouns are &lt;em&gt;I&lt;/em&gt;, &lt;em&gt;he&lt;/em&gt;, &lt;em&gt;she&lt;/em&gt;, &lt;em&gt;we&lt;/em&gt;, &lt;em&gt;they&lt;/em&gt;,
and &lt;em&gt;who&lt;/em&gt;. Object pronouns are &lt;em&gt;me&lt;/em&gt;, &lt;em&gt;him&lt;/em&gt;, &lt;em&gt;her&lt;/em&gt;, &lt;em&gt;us&lt;/em&gt;, &lt;em&gt;them&lt;/em&gt;,
and &lt;em&gt;whom&lt;/em&gt;. &amp;lt;Sally gave me five dollars. I used to money to buy lunch.&amp;gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Than&lt;/em&gt; vs. &lt;em&gt;Then&lt;/em&gt;&lt;/strong&gt; : A comparison (&lt;em&gt;than&lt;/em&gt;) vs.
a measure of time (&lt;em&gt;then&lt;/em&gt;). In code, &lt;em&gt;than&lt;/em&gt; is used when describing
a comparison operator; the '&amp;gt;' operator is a greater-&lt;em&gt;than&lt;/em&gt; operator. In
code, time sequences are an &lt;em&gt;if...then&lt;/em&gt; statement. &amp;lt;Apples are better than
oranges. I will eat my apple first, then I will eat my orange.&amp;gt;&lt;br&gt;
&lt;/li&gt;&gt;
&lt;h3&gt;Knowing the Language at a High School Level
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Power Robbers&lt;/strong&gt; : Never use &lt;em&gt;due to the fact that&lt;/em&gt;. It weakens
your sentence. Use &lt;em&gt;because&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contractions&lt;/strong&gt; : In formal writing (e.g. Proposals, SOWs), avoid contractions.
Contractions are for casual writing. Think along the lines of a Debug Build versus
a Release Build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Simply&lt;/em&gt; &amp;amp; &lt;em&gt;Obviously&lt;/em&gt;&lt;/strong&gt; : Avoid using &lt;em&gt;simply&lt;/em&gt; and &lt;em&gt;obviously&lt;/em&gt; as
it may be both to you, but neither to your audience. If it was simple or obvious,
then you didn't need to write it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use one space&lt;/strong&gt; after a sentence, not two. A PC is not a typewriter.
On a typewriter, with fixed-width fonts, two spaces are preferred, but on a PC, True
Type fonts will properly space "&amp;lt;dot&amp;gt;&amp;lt;space&amp;gt;" for you. Don't believe me?
Open up any book and look at the spaces between sentences. Microsoft Word has an option
to indicate this for you under grammar preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Effect&lt;/em&gt; vs. &lt;em&gt;Affect&lt;/em&gt;&lt;/strong&gt; : &lt;em&gt;Effect&lt;/em&gt; is the result, &lt;em&gt;affect&lt;/em&gt; is
the action. Noun and verb. &amp;lt;Poor engine performance is the effect of ignored maintenance.
Ignoring maintenance affects engine performance.&amp;gt;&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Knowing the Language at a Collegiate Level
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lists&lt;/strong&gt; : Just like when defining an array, use a comma after every
item in a list except the last. This includes before "and." &amp;lt;I like red, white,
and blue.&amp;gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;i.e.&lt;/em&gt; vs. &lt;em&gt;e.g.&lt;/em&gt;&lt;/strong&gt; : The first is &lt;em&gt;in other words&lt;/em&gt; and
the second is &lt;em&gt;for example&lt;/em&gt;, though this does not do much for clarity. Essentially, &lt;em&gt;i.e.&lt;/em&gt; is
a complete, clarifying list, while &lt;em&gt;e.g.&lt;/em&gt; is an incomplete list of examples.
&amp;lt;I watch the three stooges (i.e., Larry, Curly, and Moe). I like all four-player
card games (e.g., Euchre, Spades, and Hearts).&amp;gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semicolons&lt;/strong&gt; : Semicolons are used to separate two independent yet
related clauses that could be broken into separate sentences. &amp;lt;The water is very
hot; I hope I don't burn myself.&amp;gt; Also, use semicolons to separate items in a list
where the items contain commas. &amp;lt;When the cards were dealt, Jack had a straight;
Sally had two nines, two fives, and a queen; and George had a full house.&amp;gt;&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Be mindful of your native language. It is the one you use the most, even more than
C#, or Ruby, or Java. If you don't already own a copy, pick up &lt;em&gt;&lt;a href="http://www.amazon.com/gp/product/0205313426/?tag=cptloadte-20"&gt;The
Elements of Style&lt;/a&gt;&lt;/em&gt; by Strunk &amp;amp; White; if you do own a copy, either have
it at your desk so you can use it, or give it to someone who will. Effectively communicating
with humans, using their rules, will help you have better testing, better design,
better requirements, and have a better job. Become an effective English developer,
and it will help you be a more effective developer, overall.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=b653e6d4-37a9-445d-b3d6-44a668d37b6f" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,b653e6d4-37a9-445d-b3d6-44a668d37b6f.aspx</comments>
      <category>Business</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=05ff8148-029e-40d7-9fa1-2583ba42830b</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,05ff8148-029e-40d7-9fa1-2583ba42830b.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,05ff8148-029e-40d7-9fa1-2583ba42830b.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=05ff8148-029e-40d7-9fa1-2583ba42830b</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Many .Net developers that have experience in presentation-layer development have previous
exposure to this one, but to those who haven’t, I must share: Request.ApplicationPath
is evil! Request.Application path should never be used. Ever. I hate it!
</p>
        <p>
It’s misgivings are most commonly exposed when concatenating strings to the end of
it to create a URL of some sort.
</p>
        <blockquote>
          <p>
sURL = Request.ApplicationPath &amp; “/someDirectory/somePage.aspx”
</p>
        </blockquote>
        <p>
This is evil. Neither will work in all situations due to the method’s inconsistency
with trailing slashes.
</p>
        <p>
If the application root is in a sub-directory, say “http://server/myRoot/index.aspx”,
then the appPath is “/myRoot”. Note: there is no slash at the end, and the above sURL
gets a value of “/myRoot/someDirectory/somePage.aspx”.
</p>
        <p>
If the application root is not in a sub-directory, say “http://server/index.aspx”,
then the appPath is “/”. Note: there is a slash at the end, and the above sURL gets
a value or “//someDirectory/somePage.aspx”. In this case, rather than requesting “http://server/someDirectory/somePage.aspx”,
wonderful Internet Explorer requests “http://somedirectory/somePage.aspx”. (I don’t
fault IE for this. I commend it. It is actually one of the few cases where IE doesn’t
kludge together a band-aid for Developer mistakes.)
</p>
        <p>
So, don’t use Request.ApplicationPath. Ever. With no exception. You could make a method,
perhaps MyUtilities.ApplicationPath, that checks to see if the return contains a trailing
‘/’, and if it does, give it the axe. This will turn your domain-root appPath to an
empty string. Use your new method rather than Request.ApplicationPath, and all will
be well with the world. <strong>But, don’t do it!</strong> Don’t make a new method.
That just continues the evilness.
</p>
        <p>
Use <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuicontrolclassresolveurltopic.asp">Page.ResolveURL</a>(”~/someDirectory/somePage.aspx”)
or the counterpart Control.ResolveURL if you want it to be relative to the control’s
location. This is the only scenario you should use. ApplicationPath is evil!
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=05ff8148-029e-40d7-9fa1-2583ba42830b" />
      </body>
      <title>Request.ApplicationPath is evil!</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,05ff8148-029e-40d7-9fa1-2583ba42830b.aspx</guid>
      <link>http://www.cptloadtest.com/2006/07/26/RequestApplicationPath-Is-Evil.aspx</link>
      <pubDate>Wed, 26 Jul 2006 12:19:23 GMT</pubDate>
      <description>&lt;p&gt;
Many .Net developers that have experience in presentation-layer development have previous
exposure to this one, but to those who haven’t, I must share: Request.ApplicationPath
is evil! Request.Application path should never be used. Ever. I hate it!
&lt;/p&gt;
&lt;p&gt;
It’s misgivings are most commonly exposed when concatenating strings to the end of
it to create a URL of some sort.
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;
sURL = Request.ApplicationPath &amp;amp; “/someDirectory/somePage.aspx”
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
This is evil. Neither will work in all situations due to the method’s inconsistency
with trailing slashes.
&lt;/p&gt;
&lt;p&gt;
If the application root is in a sub-directory, say “http://server/myRoot/index.aspx”,
then the appPath is “/myRoot”. Note: there is no slash at the end, and the above sURL
gets a value of “/myRoot/someDirectory/somePage.aspx”.
&lt;/p&gt;
&lt;p&gt;
If the application root is not in a sub-directory, say “http://server/index.aspx”,
then the appPath is “/”. Note: there is a slash at the end, and the above sURL gets
a value or “//someDirectory/somePage.aspx”. In this case, rather than requesting “http://server/someDirectory/somePage.aspx”,
wonderful Internet Explorer requests “http://somedirectory/somePage.aspx”. (I don’t
fault IE for this. I commend it. It is actually one of the few cases where IE doesn’t
kludge together a band-aid for Developer mistakes.)
&lt;/p&gt;
&lt;p&gt;
So, don’t use Request.ApplicationPath. Ever. With no exception. You could make a method,
perhaps MyUtilities.ApplicationPath, that checks to see if the return contains a trailing
‘/’, and if it does, give it the axe. This will turn your domain-root appPath to an
empty string. Use your new method rather than Request.ApplicationPath, and all will
be well with the world. &lt;strong&gt;But, don’t do it!&lt;/strong&gt; Don’t make a new method.
That just continues the evilness.
&lt;/p&gt;
&lt;p&gt;
Use &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuicontrolclassresolveurltopic.asp"&gt;Page.ResolveURL&lt;/a&gt;(”~/someDirectory/somePage.aspx”)
or the counterpart Control.ResolveURL if you want it to be relative to the control’s
location. This is the only scenario you should use. ApplicationPath is evil!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=05ff8148-029e-40d7-9fa1-2583ba42830b" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,05ff8148-029e-40d7-9fa1-2583ba42830b.aspx</comments>
      <category>ASP.Net</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=8cbaa378-4e19-4a01-b005-78de6bcf4121</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,8cbaa378-4e19-4a01-b005-78de6bcf4121.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,8cbaa378-4e19-4a01-b005-78de6bcf4121.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8cbaa378-4e19-4a01-b005-78de6bcf4121</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Most of our Visual Studio solutions contain hundreds of files (classes) organized
neatly into dozens of folders (namespaces), but despite all of this organization the
vertical content size of the Solution Explorer can get quite large. Finding a particular
file when the majority of the tree is expanded is tedious and time-consuming, considering
it should be a simple effort of less than five seconds. Fortunately, all of this is
solved by the click of a button (assigned to handy macro).
</p>
        <p>
The most useful macro for Visual Studio that I have ever encountered (and in the running
for most useful VS tool, period) is the CollapseAll macro authored by one current
and one former colleague, Dennis Burton and Mike Shields. In a quick XP effort, Dennis
and Mike created a handy macro that recursively collapses the entire Solution Explorer
tree down to just the solution and its projects.
</p>
        <p>
With the tree collapsed, it is easy to find that desired file.
</p>
        <p>
The macro is functional in all versions of Visual Studio for the Microsoft.Net framework,
including Visual Studio 2003, Visual Studio 2005, and Visual Studio 2008.<br /></p>
        <p>
          <strong>CollapseAll Macro for Microsoft Visual Studio</strong>
          <br />
Dennis Burton &amp; Mike Shields | <em>Published with Permission</em></p>
        <pre name="code" class="vb">Imports System
Imports EnvDTE
Imports System.Diagnostics

Public Module CollapseAll
    Sub CollapseAll()
        ' Get the the Solution Explorer tree
        Dim UIHSolutionExplorer As UIHierarchy
        UIHSolutionExplorer = DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Object()
        ' Check if there is any open solution
        If (UIHSolutionExplorer.UIHierarchyItems.Count = 0) Then
            ' MsgBox("Nothing to collapse. You must have an open solution.")
            Return
        End If
        ' Get the top node (the name of the solution)
        Dim UIHSolutionRootNode As UIHierarchyItem
        UIHSolutionRootNode = UIHSolutionExplorer.UIHierarchyItems.Item(1)
        UIHSolutionExplorer = Nothing
        UIHSolutionRootNode.DTE.SuppressUI = True
        ' Collapse each project node
        Dim UIHItem As UIHierarchyItem
        For Each UIHItem In UIHSolutionRootNode.UIHierarchyItems
            'UIHItem.UIHierarchyItems.Expanded = False
            If UIHItem.UIHierarchyItems.Expanded Then
                Collapse(UIHItem)
            End If
        Next
        ' Select the solution node, or else when you click
        ' on the solution window
        ' scrollbar, it will synchronize the open document
        ' with the tree and pop
        ' out the corresponding node which is probably not what you want.
        UIHSolutionRootNode.Select(vsUISelectionType.vsUISelectionTypeSelect)
        UIHSolutionRootNode.DTE.SuppressUI = False
        UIHSolutionRootNode = Nothing
    End Sub

    Private Sub Collapse(ByVal item As UIHierarchyItem)
        For Each eitem As UIHierarchyItem In item.UIHierarchyItems
            If eitem.UIHierarchyItems.Expanded AndAlso eitem.UIHierarchyItems.Count &gt; 0 Then
                Collapse(eitem)
            End If
        Next
        item.UIHierarchyItems.Expanded = False
    End Sub
End Module
</pre>
        <p>
          <em>Based on code from <a href="http://www.codeproject.com/macro/collapseall.asp">Edwin
Evans</a></em>
        </p>
        <p>
Here, the macro is so popular that it is a part of our default developer’s build for
every new machine, and is conveniently assigned to a toolbar button. The default button
icon list contains an Up Arrow (in the Change Button Image menu when customizing the
toolbar) that seems quite appropriate. That little button has saved us all from a
lot of pain, five seconds at a time.
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=8cbaa378-4e19-4a01-b005-78de6bcf4121" />
      </body>
      <title>Visual Studio Macro: Solution Explorer Collapse All</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,8cbaa378-4e19-4a01-b005-78de6bcf4121.aspx</guid>
      <link>http://www.cptloadtest.com/2006/05/31/Visual-Studio-Macro-Solution-Explorer-Collapse-All.aspx</link>
      <pubDate>Wed, 31 May 2006 14:19:55 GMT</pubDate>
      <description>&lt;p&gt;
Most of our Visual Studio solutions contain hundreds of files (classes) organized
neatly into dozens of folders (namespaces), but despite all of this organization the
vertical content size of the Solution Explorer can get quite large. Finding a particular
file when the majority of the tree is expanded is tedious and time-consuming, considering
it should be a simple effort of less than five seconds. Fortunately, all of this is
solved by the click of a button (assigned to handy macro).
&lt;/p&gt;
&lt;p&gt;
The most useful macro for Visual Studio that I have ever encountered (and in the running
for most useful VS tool, period) is the CollapseAll macro authored by one current
and one former colleague, Dennis Burton and Mike Shields. In a quick XP effort, Dennis
and Mike created a handy macro that recursively collapses the entire Solution Explorer
tree down to just the solution and its projects.
&lt;/p&gt;
&lt;p&gt;
With the tree collapsed, it is easy to find that desired file.
&lt;/p&gt;
&lt;p&gt;
The macro is functional in all versions of Visual Studio for the Microsoft.Net framework,
including Visual Studio 2003, Visual Studio 2005, and Visual Studio 2008.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;CollapseAll Macro for Microsoft Visual Studio&lt;/strong&gt;
&lt;br&gt;
Dennis Burton &amp;amp; Mike Shields | &lt;em&gt;Published with Permission&lt;/em&gt;
&lt;/p&gt;
&lt;pre name="code" class="vb"&gt;Imports System
Imports EnvDTE
Imports System.Diagnostics

Public Module CollapseAll
    Sub CollapseAll()
        ' Get the the Solution Explorer tree
        Dim UIHSolutionExplorer As UIHierarchy
        UIHSolutionExplorer = DTE.Windows.Item(Constants.vsext_wk_SProjectWindow).Object()
        ' Check if there is any open solution
        If (UIHSolutionExplorer.UIHierarchyItems.Count = 0) Then
            ' MsgBox("Nothing to collapse. You must have an open solution.")
            Return
        End If
        ' Get the top node (the name of the solution)
        Dim UIHSolutionRootNode As UIHierarchyItem
        UIHSolutionRootNode = UIHSolutionExplorer.UIHierarchyItems.Item(1)
        UIHSolutionExplorer = Nothing
        UIHSolutionRootNode.DTE.SuppressUI = True
        ' Collapse each project node
        Dim UIHItem As UIHierarchyItem
        For Each UIHItem In UIHSolutionRootNode.UIHierarchyItems
            'UIHItem.UIHierarchyItems.Expanded = False
            If UIHItem.UIHierarchyItems.Expanded Then
                Collapse(UIHItem)
            End If
        Next
        ' Select the solution node, or else when you click
        ' on the solution window
        ' scrollbar, it will synchronize the open document
        ' with the tree and pop
        ' out the corresponding node which is probably not what you want.
        UIHSolutionRootNode.Select(vsUISelectionType.vsUISelectionTypeSelect)
        UIHSolutionRootNode.DTE.SuppressUI = False
        UIHSolutionRootNode = Nothing
    End Sub

    Private Sub Collapse(ByVal item As UIHierarchyItem)
        For Each eitem As UIHierarchyItem In item.UIHierarchyItems
            If eitem.UIHierarchyItems.Expanded AndAlso eitem.UIHierarchyItems.Count &amp;gt; 0 Then
                Collapse(eitem)
            End If
        Next
        item.UIHierarchyItems.Expanded = False
    End Sub
End Module
&lt;/pre&gt;
&lt;p&gt;
&lt;em&gt;Based on code from &lt;a href="http://www.codeproject.com/macro/collapseall.asp"&gt;Edwin
Evans&lt;/a&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Here, the macro is so popular that it is a part of our default developer’s build for
every new machine, and is conveniently assigned to a toolbar button. The default button
icon list contains an Up Arrow (in the Change Button Image menu when customizing the
toolbar) that seems quite appropriate. That little button has saved us all from a
lot of pain, five seconds at a time.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=8cbaa378-4e19-4a01-b005-78de6bcf4121" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,8cbaa378-4e19-4a01-b005-78de6bcf4121.aspx</comments>
      <category>Programming</category>
      <category>Tools</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=8edeeedc-5cb5-494c-bf06-231c52933fd6</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,8edeeedc-5cb5-494c-bf06-231c52933fd6.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,8edeeedc-5cb5-494c-bf06-231c52933fd6.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=8edeeedc-5cb5-494c-bf06-231c52933fd6</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Recently, here at the ranch, we have been experiencing a few issues with Internet
Explorer’s javascript functionality. It’s not that IE is doing anything wrong, but
rather that it performs unexpectedly. When opening a new window in javascript [window.open()],
the height and width dimensions are relative to the size of the canvas / stage / content
area (depending on what discipline you are from), all commonly referred to as innerHeight
and innerWidth. However, when you execute a resize function in javascript [window.resizeTo()],
the height and width dimensions are relative to the size of the entire window, including
any chrome, commonly referred to as outerHeight and outerWidth.
</p>
        <p>
Thus, if you create a window (500px x 300px), then resize it to (505px x 305px), the
window will actually get <em>smaller</em>, since the chrome adds more than 5 pixels
to height and width.
</p>
        <p>
The problem: SCOs (Courseware) can be of any size, depending on the specifications,
requirements, and whims of the original clients and developers. To keep courses in
their most visual-appealing state, we need to size the content window to precise innerHeight
and innerWidth pixel dimensions. Due to our site’s design, the link that launches
the Course Shell window has no idea what the size of the SCO is. The Course Shell
(LMS) knows how big the SCO is, but it is loaded into the Course Shell window, which
is obviously done <i>after</i> the window is created and initially sized. We need
a way to size the window to content-dimensions after the window is created.
</p>
        <p>
The catch: Internet Explorer has no native support for innerHeight and innerWidth,
let alone a way to resize to those dimensions. Furthermore, the difference between
the inner- and outer-dimensions due to window chrome can change from OS to OS and
from theme to theme. For example, in Windows XP’s default “bubbly” themes, the title
and status bars are much taller than in Windows “Classic” themes. Internet Explorer
has no native way to identify the difference in inner- and outer-dimensions, making
it difficult to resize to an inner size using an outer size command.
</p>
        <p>
I hacked together some (perhaps mediocre, but still effective) javascript to resize
a window to its inner dimensions rather than the outer dimensions, regardless of the
amount of chrome that the OS adds.
</p>
        <p>
          <strong>HTML</strong>
        </p>
        <pre name="code" class="html">&lt;div id="resizeReference"
    style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; z-index: -1;"&gt;
    &amp;nbsp;
&lt;/div&gt;</pre>
        <p>
          <strong>Javascript</strong>
        </p>
        <pre name="code" class="js">function resizeWindow(iWidth, iHeight){
    var resizeRef = document.getElementById('resizeReference');
    var iOuterWidth = iWidth + 10;
    var iOuterHeight = iHeight + 29;
 
    if (resizeRef) {
        var iPreWidth = resizeRef.offsetWidth;
        var iPreHeight = resizeRef.offsetHeight;
        window.resizeTo(iPreWidth,iPreHeight);
        var iPostWidth = resizeRef.offsetWidth;
        var iPostHeight = resizeRef.offsetHeight;
        iOuterWidth = iWidth + (iPreWidth-iPostWidth);
        iOuterHeight = iHeight + (iPreHeight-iPostHeight);
    }
    window.resizeTo(iOuterWidth, iOuterHeight);
}</pre>
        <p>
The HTML tag creates a hidden DIV whose height and width match the window. This provides
innerHeight and innerWidth. The JS takes the dimensions of that DIV and resizes the
window to those measured dimensions. Since this transfers the inner-dimensions to
the outer-dimensions, this provides the exact size of the window chrome. We can now
resize to the input parameter height and width, plus the height and width of window
chrome, to give us a resize to inner-dimensions.
</p>
        <p>
Execute resizeWindow no sooner than below the closing Body tag, so that the DIV is
rendered.
</p>
        <p>
It is a bit of a hack, but it works for now.
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=8edeeedc-5cb5-494c-bf06-231c52933fd6" />
      </body>
      <title>Resizing IE to innerHeight and innerWidth</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,8edeeedc-5cb5-494c-bf06-231c52933fd6.aspx</guid>
      <link>http://www.cptloadtest.com/2006/05/02/Resizing-IE-To-InnerHeight-And-InnerWidth.aspx</link>
      <pubDate>Tue, 02 May 2006 14:23:23 GMT</pubDate>
      <description>&lt;p&gt;
Recently, here at the ranch, we have been experiencing a few issues with Internet
Explorer’s javascript functionality. It’s not that IE is doing anything wrong, but
rather that it performs unexpectedly. When opening a new window in javascript [window.open()],
the height and width dimensions are relative to the size of the canvas / stage / content
area (depending on what discipline you are from), all commonly referred to as innerHeight
and innerWidth. However, when you execute a resize function in javascript [window.resizeTo()],
the height and width dimensions are relative to the size of the entire window, including
any chrome, commonly referred to as outerHeight and outerWidth.
&lt;/p&gt;
&lt;p&gt;
Thus, if you create a window (500px x 300px), then resize it to (505px x 305px), the
window will actually get &lt;em&gt;smaller&lt;/em&gt;, since the chrome adds more than 5 pixels
to height and width.
&lt;/p&gt;
&lt;p&gt;
The problem: SCOs (Courseware) can be of any size, depending on the specifications,
requirements, and whims of the original clients and developers. To keep courses in
their most visual-appealing state, we need to size the content window to precise innerHeight
and innerWidth pixel dimensions. Due to our site’s design, the link that launches
the Course Shell window has no idea what the size of the SCO is. The Course Shell
(LMS) knows how big the SCO is, but it is loaded into the Course Shell window, which
is obviously done &lt;i&gt;after&lt;/i&gt; the window is created and initially sized. We need
a way to size the window to content-dimensions after the window is created.
&lt;/p&gt;
&lt;p&gt;
The catch: Internet Explorer has no native support for innerHeight and innerWidth,
let alone a way to resize to those dimensions. Furthermore, the difference between
the inner- and outer-dimensions due to window chrome can change from OS to OS and
from theme to theme. For example, in Windows XP’s default “bubbly” themes, the title
and status bars are much taller than in Windows “Classic” themes. Internet Explorer
has no native way to identify the difference in inner- and outer-dimensions, making
it difficult to resize to an inner size using an outer size command.
&lt;/p&gt;
&lt;p&gt;
I hacked together some (perhaps mediocre, but still effective) javascript to resize
a window to its inner dimensions rather than the outer dimensions, regardless of the
amount of chrome that the OS adds.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;HTML&lt;/strong&gt;
&lt;/p&gt;
&lt;pre name="code" class="html"&gt;&amp;lt;div id="resizeReference"
    style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; z-index: -1;"&amp;gt;
    &amp;amp;nbsp;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;p&gt;
&lt;strong&gt;Javascript&lt;/strong&gt;
&lt;/p&gt;
&lt;pre name="code" class="js"&gt;function resizeWindow(iWidth, iHeight){
    var resizeRef = document.getElementById('resizeReference');
    var iOuterWidth = iWidth + 10;
    var iOuterHeight = iHeight + 29;
 
    if (resizeRef) {
        var iPreWidth = resizeRef.offsetWidth;
        var iPreHeight = resizeRef.offsetHeight;
        window.resizeTo(iPreWidth,iPreHeight);
        var iPostWidth = resizeRef.offsetWidth;
        var iPostHeight = resizeRef.offsetHeight;
        iOuterWidth = iWidth + (iPreWidth-iPostWidth);
        iOuterHeight = iHeight + (iPreHeight-iPostHeight);
    }
    window.resizeTo(iOuterWidth, iOuterHeight);
}&lt;/pre&gt;
&lt;p&gt;
The HTML tag creates a hidden DIV whose height and width match the window. This provides
innerHeight and innerWidth. The JS takes the dimensions of that DIV and resizes the
window to those measured dimensions. Since this transfers the inner-dimensions to
the outer-dimensions, this provides the exact size of the window chrome. We can now
resize to the input parameter height and width, plus the height and width of window
chrome, to give us a resize to inner-dimensions.
&lt;/p&gt;
&lt;p&gt;
Execute resizeWindow no sooner than below the closing Body tag, so that the DIV is
rendered.
&lt;/p&gt;
&lt;p&gt;
It is a bit of a hack, but it works for now.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=8edeeedc-5cb5-494c-bf06-231c52933fd6" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,8edeeedc-5cb5-494c-bf06-231c52933fd6.aspx</comments>
      <category>JavaScript</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=ccfd87ed-d405-4ede-9ae3-999e231d2df9</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,ccfd87ed-d405-4ede-9ae3-999e231d2df9.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,ccfd87ed-d405-4ede-9ae3-999e231d2df9.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=ccfd87ed-d405-4ede-9ae3-999e231d2df9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
NAnt hates .Net’s resource files, or .resx. Don’t get me wrong–it handles them just
fine–but large quantities of resx will really bog it down.
</p>
        <p>
Visual Studio loves resx. The IDE will automatically create a resource file for you
when you open pages and controls in the ‘designer’ view. Back when we still used Visual
SourceSafe as our SCM, Visual Studio happily checked the file in and forgot about
it. Now, our 500+ page application has 500+ resource files. Most of these 500+ resource
files contain zero resources, making them useless, pointless, and a detriment to the
build.
</p>
        <p>
This morning I went through the build log, noting every resx that contained zero resources,
and deleted all of these useless files.
</p>
        <p>
The compile time dropped by 5 minutes.
</p>
        <p>
          <em>Moral of the story:</em> Be weary of Visual Studio. With regards to resx, VS is
a malware program that’s just filling your hard drive with junk. If you use resx,
great, but if you don’t, delete them all. NAnt will love you for it.
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=ccfd87ed-d405-4ede-9ae3-999e231d2df9" />
      </body>
      <title>NAnt slowdowns: Visual Studio, the .resx machine</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,ccfd87ed-d405-4ede-9ae3-999e231d2df9.aspx</guid>
      <link>http://www.cptloadtest.com/2006/02/15/NAnt-Slowdowns-Visual-Studio-The-Resx-Machine.aspx</link>
      <pubDate>Wed, 15 Feb 2006 16:31:31 GMT</pubDate>
      <description>&lt;p&gt;
NAnt hates .Net’s resource files, or .resx. Don’t get me wrong–it handles them just
fine–but large quantities of resx will really bog it down.
&lt;/p&gt;
&lt;p&gt;
Visual Studio loves resx. The IDE will automatically create a resource file for you
when you open pages and controls in the ‘designer’ view. Back when we still used Visual
SourceSafe as our SCM, Visual Studio happily checked the file in and forgot about
it. Now, our 500+ page application has 500+ resource files. Most of these 500+ resource
files contain zero resources, making them useless, pointless, and a detriment to the
build.
&lt;/p&gt;
&lt;p&gt;
This morning I went through the build log, noting every resx that contained zero resources,
and deleted all of these useless files.
&lt;/p&gt;
&lt;p&gt;
The compile time dropped by 5 minutes.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Moral of the story:&lt;/em&gt; Be weary of Visual Studio. With regards to resx, VS is
a malware program that’s just filling your hard drive with junk. If you use resx,
great, but if you don’t, delete them all. NAnt will love you for it.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=ccfd87ed-d405-4ede-9ae3-999e231d2df9" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,ccfd87ed-d405-4ede-9ae3-999e231d2df9.aspx</comments>
      <category>ASP.Net</category>
      <category>Continuous Integration</category>
      <category>NAnt</category>
      <category>Programming</category>
      <category>Task Automation</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=185d4fd2-87ca-49d8-b7f9-b06b3068559e</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,185d4fd2-87ca-49d8-b7f9-b06b3068559e.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,185d4fd2-87ca-49d8-b7f9-b06b3068559e.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=185d4fd2-87ca-49d8-b7f9-b06b3068559e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
“It compiles! Ship it!”
</p>
        <p>
Microsoft has sent Visual Studio 2005 to the printers. That brings .Net 2.0 to the
table in all of its glory. The official release date is still November 7, and though
it is available now to all of us MSDN subscribers (though the site is too flooded
to ping, let alone download), there is still some question on if the media will be
ready in time to go in all of the pretty little VS05 boxes at your local Microsoft
store.
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=185d4fd2-87ca-49d8-b7f9-b06b3068559e" />
      </body>
      <title>Visual Studio 2005 goes gold</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,185d4fd2-87ca-49d8-b7f9-b06b3068559e.aspx</guid>
      <link>http://www.cptloadtest.com/2005/10/28/Visual-Studio-2005-Goes-Gold.aspx</link>
      <pubDate>Fri, 28 Oct 2005 17:40:03 GMT</pubDate>
      <description>&lt;p&gt;
“It compiles! Ship it!”
&lt;/p&gt;
&lt;p&gt;
Microsoft has sent Visual Studio 2005 to the printers. That brings .Net 2.0 to the
table in all of its glory. The official release date is still November 7, and though
it is available now to all of us MSDN subscribers (though the site is too flooded
to ping, let alone download), there is still some question on if the media will be
ready in time to go in all of the pretty little VS05 boxes at your local Microsoft
store.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=185d4fd2-87ca-49d8-b7f9-b06b3068559e" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,185d4fd2-87ca-49d8-b7f9-b06b3068559e.aspx</comments>
      <category>ASP.Net</category>
      <category>Programming</category>
      <category>Tools</category>
      <category>Visual Studio</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=4bf11370-eed0-41d9-92c8-d4c90bfd1e0e</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,4bf11370-eed0-41d9-92c8-d4c90bfd1e0e.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,4bf11370-eed0-41d9-92c8-d4c90bfd1e0e.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=4bf11370-eed0-41d9-92c8-d4c90bfd1e0e</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
The default settings of NUnit, TestRunner, and Test Driven Development all want different
copies of the app.config at different locations. If ProjectName creates ProjectName.dll,
then NUnit wants ProjectName.config, TR wants ProjectName.dll.config, and TDD wants
TargetDir\ProjectName.dll.config. This is a lot of work to put in the post-build event
of every unit test project, and can be even more work when another testing tool comes
along that wants yet a new config filename. The best way to manage all of these file
copies is through a common post-build event call.
</p>
        <p>
Many probably opt for a NAnt script, but we found that passing in the required paths
can sometimes cause NAnt to get confused, and it won’t properly parse the parameter
listing. So, we went with a command file, instead.
</p>
        <p>
          <strong>CopyConfigs.cmd</strong>
        </p>
        <div style="border: 1px solid rgb(51, 51, 51); padding: 7px; background: white none repeat scroll 0% 50%; font-size: 80%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
          <p style="margin: 0px;">
            <span style="color: green;">rem for nunit</span>
          </p>
          <p style="margin: 0px;">
            <span style="color: blue;">copy</span> “%~1App.config” “%~1%~2.config”
</p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: green;">rem for testrunner</span>
          </p>
          <p style="margin: 0px;">
            <span style="color: blue;">copy</span> “%~1App.config” “%~1%~2.dll.config”
</p>
          <p style="margin: 0px;">
 
</p>
          <p style="margin: 0px;">
            <span style="color: green;">rem for testdrivendevelopment</span>
          </p>
          <p style="margin: 0px;">
            <span style="color: blue;">copy</span> “%~1App.config” “%~3.config”
</p>
        </div>
        <p>
          <strong>VS.Net Post Build Event</strong>
        </p>
        <div style="border: 1px solid rgb(51, 51, 51); padding: 7px; background: white none repeat scroll 0% 50%; font-size: 80%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
          <p style="margin: 0px;">
            <span style="color: blue;">call</span> “C:\MyPath\CopyConfigs.cmd” “$(ProjectDir)”
“$(ProjectName) “$(TargetPath)”
</p>
        </div>
        <p>
VS.Net already includes a series of NAnt-like properties for project names, project
directories, target [assembly] filenames, etc; these come in handy for creating a
universal script. Placing the path references in quotes allows for spaces and other
characters (Except more quotes) in the path. Executing the command file through a
call allows us a little more versatility with the argument references (%~1 removes
the surrounding quotes from the argument value, allowing us to append a few together
without jacking the subsequent path).
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=4bf11370-eed0-41d9-92c8-d4c90bfd1e0e" />
      </body>
      <title>Managing app.config for testing tools</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,4bf11370-eed0-41d9-92c8-d4c90bfd1e0e.aspx</guid>
      <link>http://www.cptloadtest.com/2005/08/08/Managing-Appconfig-For-Testing-Tools.aspx</link>
      <pubDate>Mon, 08 Aug 2005 17:48:20 GMT</pubDate>
      <description>&lt;p&gt;
The default settings of NUnit, TestRunner, and Test Driven Development all want different
copies of the app.config at different locations. If ProjectName creates ProjectName.dll,
then NUnit wants ProjectName.config, TR wants ProjectName.dll.config, and TDD wants
TargetDir\ProjectName.dll.config. This is a lot of work to put in the post-build event
of every unit test project, and can be even more work when another testing tool comes
along that wants yet a new config filename. The best way to manage all of these file
copies is through a common post-build event call.
&lt;/p&gt;
&lt;p&gt;
Many probably opt for a NAnt script, but we found that passing in the required paths
can sometimes cause NAnt to get confused, and it won’t properly parse the parameter
listing. So, we went with a command file, instead.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;CopyConfigs.cmd&lt;/strong&gt;
&lt;/p&gt;
&lt;div style="border: 1px solid rgb(51, 51, 51); padding: 7px; background: white none repeat scroll 0% 50%; font-size: 80%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: green;"&gt;rem for nunit&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;copy&lt;/span&gt; “%~1App.config” “%~1%~2.config”
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: green;"&gt;rem for testrunner&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;copy&lt;/span&gt; “%~1App.config” “%~1%~2.dll.config”
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: green;"&gt;rem for testdrivendevelopment&lt;/span&gt;
&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;copy&lt;/span&gt; “%~1App.config” “%~3.config”
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;strong&gt;VS.Net Post Build Event&lt;/strong&gt;
&lt;/p&gt;
&lt;div style="border: 1px solid rgb(51, 51, 51); padding: 7px; background: white none repeat scroll 0% 50%; font-size: 80%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;
&lt;p style="margin: 0px;"&gt;
&lt;span style="color: blue;"&gt;call&lt;/span&gt; “C:\MyPath\CopyConfigs.cmd” “$(ProjectDir)”
“$(ProjectName) “$(TargetPath)”
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
VS.Net already includes a series of NAnt-like properties for project names, project
directories, target [assembly] filenames, etc; these come in handy for creating a
universal script. Placing the path references in quotes allows for spaces and other
characters (Except more quotes) in the path. Executing the command file through a
call allows us a little more versatility with the argument references (%~1 removes
the surrounding quotes from the argument value, allowing us to append a few together
without jacking the subsequent path).
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=4bf11370-eed0-41d9-92c8-d4c90bfd1e0e" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,4bf11370-eed0-41d9-92c8-d4c90bfd1e0e.aspx</comments>
      <category>ASP.Net</category>
      <category>Programming</category>
      <category>Task Automation</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=4f0ceb20-3f16-487c-aab3-1773030be95a</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,4f0ceb20-3f16-487c-aab3-1773030be95a.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,4f0ceb20-3f16-487c-aab3-1773030be95a.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=4f0ceb20-3f16-487c-aab3-1773030be95a</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Scott Hanselman is my new hero. He is filling the hole—the one thing preventing Watir
from becoming real competitor in the automated functional test market: script recording.
Watch out Mercury; by creating <a href="http://www.hanselman.com/blog/IntroducingWatirMakerRecordingForRubybasedWatir.aspx">WatirMaker</a>,
Scott is opening the flood gates, and Watir is going to come pouring through.
</p>
        <p>
This changes everything.
</p>
        <p>
I started out my career as a developer, but as I noted in an earlier blog, I get much
more enjoyment from breaking things than I do building things, so I jumped ship. With
my development experience I can delve in to making some rather wicked scripts for
QTP, LoadRunner, and lately, Watir. However, my testers don’t share my skill set.
My biggest hurdle in ousting QTP and making Watir our standard is the lack of recording;
I can not expect every tester to start coding away in Ruby. It should come as no surprise
that when I opened <a href="http://www.hanselman.com/blog/">Scott’s blog</a> this
morning, I was so excited that I nearly wet myself.
</p>
        <p>
It is a work in progress, but soon Scott hopes to have a fully functional recording
tool for Watir. With WatirMaker, my testers can hit a button and start clicking away
in IE; the tool will happily watch like a little kid on the sidelines, learning every
move. My testers can all adopt Watir with open arms, and we can wave goodbye to that
Mercury maintenance contract.
</p>
        <p>
The only thing left to say is: “Scott…thanks!”
</p>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=4f0ceb20-3f16-487c-aab3-1773030be95a" />
      </body>
      <title>WatirMaker: GUI recording for Watir</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,4f0ceb20-3f16-487c-aab3-1773030be95a.aspx</guid>
      <link>http://www.cptloadtest.com/2005/07/27/WatirMaker-GUI-Recording-For-Watir.aspx</link>
      <pubDate>Wed, 27 Jul 2005 17:55:50 GMT</pubDate>
      <description>&lt;p&gt;
Scott Hanselman is my new hero. He is filling the hole—the one thing preventing Watir
from becoming real competitor in the automated functional test market: script recording.
Watch out Mercury; by creating &lt;a href="http://www.hanselman.com/blog/IntroducingWatirMakerRecordingForRubybasedWatir.aspx"&gt;WatirMaker&lt;/a&gt;,
Scott is opening the flood gates, and Watir is going to come pouring through.
&lt;/p&gt;
&lt;p&gt;
This changes everything.
&lt;/p&gt;
&lt;p&gt;
I started out my career as a developer, but as I noted in an earlier blog, I get much
more enjoyment from breaking things than I do building things, so I jumped ship. With
my development experience I can delve in to making some rather wicked scripts for
QTP, LoadRunner, and lately, Watir. However, my testers don’t share my skill set.
My biggest hurdle in ousting QTP and making Watir our standard is the lack of recording;
I can not expect every tester to start coding away in Ruby. It should come as no surprise
that when I opened &lt;a href="http://www.hanselman.com/blog/"&gt;Scott’s blog&lt;/a&gt; this
morning, I was so excited that I nearly wet myself.
&lt;/p&gt;
&lt;p&gt;
It is a work in progress, but soon Scott hopes to have a fully functional recording
tool for Watir. With WatirMaker, my testers can hit a button and start clicking away
in IE; the tool will happily watch like a little kid on the sidelines, learning every
move. My testers can all adopt Watir with open arms, and we can wave goodbye to that
Mercury maintenance contract.
&lt;/p&gt;
&lt;p&gt;
The only thing left to say is: “Scott…thanks!”
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=4f0ceb20-3f16-487c-aab3-1773030be95a" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,4f0ceb20-3f16-487c-aab3-1773030be95a.aspx</comments>
      <category>Programming</category>
      <category>Testing</category>
      <category>Tools</category>
      <category>Watir</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=3de55271-4364-4ef3-ae9a-d1d11113ed56</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,3de55271-4364-4ef3-ae9a-d1d11113ed56.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,3de55271-4364-4ef3-ae9a-d1d11113ed56.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=3de55271-4364-4ef3-ae9a-d1d11113ed56</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Scott Hanselman has a good post today about the HttpOnly cookie attribute. It secures
the cookie from access via the DOM. “The value of this property is questionable since
any sniffer or Fiddler could easily remove it. That said, it could slow down the average
script kiddie for 15 seconds.”
</p>
        <p>
Read Scott’s <a href="http://www.hanselman.com/blog/HttpOnlyCookiesOnASPNET11.aspx">full
blog entry</a>.
</p>
        <p>
Here’s the meat-and-potatoes of what Scott came up with; it’s for your global.asax:
</p>
        <pre name="code" class="csharp:nocontrols">protected void Application_EndRequest(Object sender, EventArgs e)
{
    foreach(string cookie in Response.Cookies)
    {
        const string HTTPONLY = ";HttpOnly";
        string path = Response.Cookies[cookie].Path;
        if (path.EndsWith(HTTPONLY) == false)
        {
            //force HttpOnly to be added to the cookie
            Response.Cookies[cookie].Path += HTTPONLY;
        }
    }
}</pre>
        <img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=3de55271-4364-4ef3-ae9a-d1d11113ed56" />
      </body>
      <title>“HttpOnly Cookies on ASP.NET 1.1″ - a little added security</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,3de55271-4364-4ef3-ae9a-d1d11113ed56.aspx</guid>
      <link>http://www.cptloadtest.com/2005/07/22/HttpOnly-Cookies-On-ASPNET-11-A-Little-Added-Security.aspx</link>
      <pubDate>Fri, 22 Jul 2005 18:01:58 GMT</pubDate>
      <description>&lt;p&gt;
Scott Hanselman has a good post today about the HttpOnly cookie attribute. It secures
the cookie from access via the DOM. “The value of this property is questionable since
any sniffer or Fiddler could easily remove it. That said, it could slow down the average
script kiddie for 15 seconds.”
&lt;/p&gt;
&lt;p&gt;
Read Scott’s &lt;a href="http://www.hanselman.com/blog/HttpOnlyCookiesOnASPNET11.aspx"&gt;full
blog entry&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Here’s the meat-and-potatoes of what Scott came up with; it’s for your global.asax:
&lt;/p&gt;
&lt;pre name="code" class="csharp:nocontrols"&gt;protected void Application_EndRequest(Object sender, EventArgs e)
{
    foreach(string cookie in Response.Cookies)
    {
        const string HTTPONLY = ";HttpOnly";
        string path = Response.Cookies[cookie].Path;
        if (path.EndsWith(HTTPONLY) == false)
        {
            //force HttpOnly to be added to the cookie
            Response.Cookies[cookie].Path += HTTPONLY;
        }
    }
}&lt;/pre&gt;&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=3de55271-4364-4ef3-ae9a-d1d11113ed56" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,3de55271-4364-4ef3-ae9a-d1d11113ed56.aspx</comments>
      <category>ASP.Net</category>
      <category>Programming</category>
    </item>
    <item>
      <trackback:ping>http://www.cptloadtest.com/Trackback.aspx?guid=9166d01a-a749-478e-95e5-4c60729aa687</trackback:ping>
      <pingback:server>http://www.cptloadtest.com/pingback.aspx</pingback:server>
      <pingback:target>http://www.cptloadtest.com/PermaLink,guid,9166d01a-a749-478e-95e5-4c60729aa687.aspx</pingback:target>
      <dc:creator>Jay Harris</dc:creator>
      <wfw:comment>http://www.cptloadtest.com/CommentView,guid,9166d01a-a749-478e-95e5-4c60729aa687.aspx</wfw:comment>
      <wfw:commentRss>http://www.cptloadtest.com/SyndicationService.asmx/GetEntryCommentsRss?guid=9166d01a-a749-478e-95e5-4c60729aa687</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Years ago, way back when the web first started to become universally popular–and I’m
talking about popular with all demographics and not just geeks like me–there was the
30KB rule, and it was a cardinal sin to break it. The entire request, including your
HTML, your images, and everything else your page contained, had to come in under 30
kilobytes. Most homes were surfing through the web on a 28.8kbps modem, which pulled
30KB in about 10 seconds. Beyond that 10 seconds, and your users were too bored, frustrated,
or confused to wait another moment, and were off to pursue the next site in your WebRing.
30KB. That was the limit. It was universally accepted. And, save a few ransom notes
on GeoCities, everyone followed it.
</p>
        <p>
Whatever happened to the 30KB rule?
</p>
        <p>
Today constantly see pages that are 100KB or more, and those are even compressed responses.
Everyone is so caught up in broadband, and developing on their 100mbps LAN, that they
forget about the little guy. What about grandma? My poor grandma still surfs the internet
with a good ol’ 57.6kbps modem. And even if she could pull off that speed (US restrictions
limit to 53, max) it would still take 20 seconds to yank that monster through the
pipe. My poor grandma shouldn’t have to wait that long.
</p>
        <p>
Often times if I wade through the muck that makes up the offending request, I see
60KB style sheets, references to JS files that contain functions not even used in
this page, big honkin’ j-pegs, useless JavaScript comment blocks that easily pile
on a few K, and my nemesis: ViewState. (I hate ViewState. ViewState hates me. It’s
a good relationship.)
</p>
        <p>
My company is making an application, and the primary audience is a bunch o’ satellite
offices stuck in the 20th century. They plug in to a whopping dual ISDN which maxes
out at a whopping 128kbps. That’s 16KB/sec for you young folk. That 100KB page will
take 7 seconds to pull across the wire. Toss that fact in to the 10-second rule, and
you only have 3 seconds to process the request. I have visions of little ones and
zeros flying towards the light screaming “We’re not gonna make it!!”
</p>
        <p>
Get a haircut. Trim those bushes. Bring that response size down a few K. Here’s a
few ways to tame the beast:
</p>
        <h3>Reduce ViewState
</h3>
        <blockquote>“Remember that ViewState is evil.”</blockquote>
        <p>
It adds a big, encrypted string to a hidden form variable in your HTML. However, this
beast gets bigger with every web control that you have. Explicitly turn off viewstate
on every control that does not use it, or better yet, turn of viewstate for the entire
page. Of course, realize that the not-dot-net crowd is laughing at you while you do
it.
</p>
        <h3>Eliminate Comments in Release Code
</h3>
        <blockquote>“keep your comments to yourself.”</blockquote>
        <p>
It is great to comment your code. It is fabulous. Every developer should bow to you
if you comment your code, because not enough do it themselves. However, unless it
is compiled code or in code-behind that isn’t sent to the client, it has to go. You
can keep your comments in the version stored in SVN, VSS, or whatever your favorite
source control tool is, but your release code should contain no client-side comments.
Your client doesn’t read them, their browser doesn’t care about them, and all it does
is slow everything down, so give them the axe. Your network administrator will love
you for it, too.
</p>
        <h3>Optimize Images
</h3>
        <blockquote>“Phenomenal, Artistic Imagery, Itty-Bitty Living Space.”</blockquote>
        <p>
Compress your images. Get them as small as your image editor can get them (small:
file size, not small: pixel size) without degrading the image beyond acceptable levels.
And if you use a GIF, lower the number of colors (which will lower the number of bytes).
When your images get smaller, people get happy.
</p>
        <h3>Eliminate Whitespace
</h3>
        <blockquote>“One Program: One Line of Code.”</blockquote>
        <p>
This is a cheap trick to squeeze out those last few bytes. If you have a news article
that’s 9 pages long, open it up in notepad and turn off word-wrap, it becomes one
big long line that stretches out forever and is impossible to read. But, your browser
could care less. Take out all of the horizontal white space that you use to make your
code readable, and then take out all the line breaks to make your HTML one big line,
and your browser couldn’t tell the difference. However, you just chopped a few more
bits.
</p>
        <h3>Enable Compression
</h3>
        <blockquote>“GZip it, and GZip it good.”</blockquote>
        <p>
If all else fails, and you’ve gotten your pages as whittled down as you can, and they
are still big, compress it. Then again, even if they are small, compress it. It will
add a few more CPU cycles on both ends to compress and decompress the response, but
the time lost is greatly countered by the time saved in data transfer. Typical compression
is around 40%, which takes that 100KB file down to 60KB, and saves my grandma nearly
8 seconds. She’ll give you a kiss and squeeze your cheeks for that one.
</p>blockquote“keep&gt;
<img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=9166d01a-a749-478e-95e5-4c60729aa687" /></body>
      <title>What happened to 30 KB?</title>
      <guid isPermaLink="false">http://www.cptloadtest.com/PermaLink,guid,9166d01a-a749-478e-95e5-4c60729aa687.aspx</guid>
      <link>http://www.cptloadtest.com/2005/07/18/What-Happened-To-30-KB.aspx</link>
      <pubDate>Mon, 18 Jul 2005 18:10:35 GMT</pubDate>
      <description>&lt;p&gt;
Years ago, way back when the web first started to become universally popular–and I’m
talking about popular with all demographics and not just geeks like me–there was the
30KB rule, and it was a cardinal sin to break it. The entire request, including your
HTML, your images, and everything else your page contained, had to come in under 30
kilobytes. Most homes were surfing through the web on a 28.8kbps modem, which pulled
30KB in about 10 seconds. Beyond that 10 seconds, and your users were too bored, frustrated,
or confused to wait another moment, and were off to pursue the next site in your WebRing.
30KB. That was the limit. It was universally accepted. And, save a few ransom notes
on GeoCities, everyone followed it.
&lt;/p&gt;
&lt;p&gt;
Whatever happened to the 30KB rule?
&lt;/p&gt;
&lt;p&gt;
Today constantly see pages that are 100KB or more, and those are even compressed responses.
Everyone is so caught up in broadband, and developing on their 100mbps LAN, that they
forget about the little guy. What about grandma? My poor grandma still surfs the internet
with a good ol’ 57.6kbps modem. And even if she could pull off that speed (US restrictions
limit to 53, max) it would still take 20 seconds to yank that monster through the
pipe. My poor grandma shouldn’t have to wait that long.
&lt;/p&gt;
&lt;p&gt;
Often times if I wade through the muck that makes up the offending request, I see
60KB style sheets, references to JS files that contain functions not even used in
this page, big honkin’ j-pegs, useless JavaScript comment blocks that easily pile
on a few K, and my nemesis: ViewState. (I hate ViewState. ViewState hates me. It’s
a good relationship.)
&lt;/p&gt;
&lt;p&gt;
My company is making an application, and the primary audience is a bunch o’ satellite
offices stuck in the 20th century. They plug in to a whopping dual ISDN which maxes
out at a whopping 128kbps. That’s 16KB/sec for you young folk. That 100KB page will
take 7 seconds to pull across the wire. Toss that fact in to the 10-second rule, and
you only have 3 seconds to process the request. I have visions of little ones and
zeros flying towards the light screaming “We’re not gonna make it!!”
&lt;/p&gt;
&lt;p&gt;
Get a haircut. Trim those bushes. Bring that response size down a few K. Here’s a
few ways to tame the beast:
&lt;/p&gt;
&lt;h3&gt;Reduce ViewState
&lt;/h3&gt;
&lt;blockquote&gt;“Remember that ViewState is evil.”&lt;/blockquote&gt; 
&lt;p&gt;
It adds a big, encrypted string to a hidden form variable in your HTML. However, this
beast gets bigger with every web control that you have. Explicitly turn off viewstate
on every control that does not use it, or better yet, turn of viewstate for the entire
page. Of course, realize that the not-dot-net crowd is laughing at you while you do
it.
&lt;/p&gt;
&lt;h3&gt;Eliminate Comments in Release Code
&lt;/h3&gt;
&lt;blockquote&gt;“keep your comments to yourself.”&lt;/blockquote&gt; 
&lt;p&gt;
It is great to comment your code. It is fabulous. Every developer should bow to you
if you comment your code, because not enough do it themselves. However, unless it
is compiled code or in code-behind that isn’t sent to the client, it has to go. You
can keep your comments in the version stored in SVN, VSS, or whatever your favorite
source control tool is, but your release code should contain no client-side comments.
Your client doesn’t read them, their browser doesn’t care about them, and all it does
is slow everything down, so give them the axe. Your network administrator will love
you for it, too.
&lt;/p&gt;
&lt;h3&gt;Optimize Images
&lt;/h3&gt;
&lt;blockquote&gt;“Phenomenal, Artistic Imagery, Itty-Bitty Living Space.”&lt;/blockquote&gt; 
&lt;p&gt;
Compress your images. Get them as small as your image editor can get them (small:
file size, not small: pixel size) without degrading the image beyond acceptable levels.
And if you use a GIF, lower the number of colors (which will lower the number of bytes).
When your images get smaller, people get happy.
&lt;/p&gt;
&lt;h3&gt;Eliminate Whitespace
&lt;/h3&gt;
&lt;blockquote&gt;“One Program: One Line of Code.”&lt;/blockquote&gt; 
&lt;p&gt;
This is a cheap trick to squeeze out those last few bytes. If you have a news article
that’s 9 pages long, open it up in notepad and turn off word-wrap, it becomes one
big long line that stretches out forever and is impossible to read. But, your browser
could care less. Take out all of the horizontal white space that you use to make your
code readable, and then take out all the line breaks to make your HTML one big line,
and your browser couldn’t tell the difference. However, you just chopped a few more
bits.
&lt;/p&gt;
&lt;h3&gt;Enable Compression
&lt;/h3&gt;
&lt;blockquote&gt;“GZip it, and GZip it good.”&lt;/blockquote&gt; 
&lt;p&gt;
If all else fails, and you’ve gotten your pages as whittled down as you can, and they
are still big, compress it. Then again, even if they are small, compress it. It will
add a few more CPU cycles on both ends to compress and decompress the response, but
the time lost is greatly countered by the time saved in data transfer. Typical compression
is around 40%, which takes that 100KB file down to 60KB, and saves my grandma nearly
8 seconds. She’ll give you a kiss and squeeze your cheeks for that one.
&lt;/p&gt;blockquote“keep&gt;
&lt;img width="0" height="0" src="http://www.cptloadtest.com/aggbug.ashx?id=9166d01a-a749-478e-95e5-4c60729aa687" /&gt;</description>
      <comments>http://www.cptloadtest.com/CommentView,guid,9166d01a-a749-478e-95e5-4c60729aa687.aspx</comments>
      <category>Programming</category>
      <category>Usability</category>
    </item>
  </channel>
</rss>