<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>jo.se/f pfleger</title><link>http://feeds.feedburner.com/josefpfleger</link><description>Josef Pfleger's Blog</description><atom:link href="https://example.com/f.rss" rel="self"></atom:link><language>en-us</language><lastBuildDate>Mon, 02 Jun 2014 17:49:56 +0200</lastBuildDate><item><title>ForceCORS Workaround</title><link>http://www-jo.se/f.pfleger/forcecors-workaround</link><description>
&lt;p&gt;The latest Firefox &lt;a href="https://support.mozilla.org/en-US/kb/what-happened-to-the-add-on-bar"&gt;no longer has an add-on bar&lt;/a&gt; which also caused the &lt;a href="http://www-jo.se/f.pfleger/forcecors"&gt;ForceCORS&lt;/a&gt; button to disappear. Github user &lt;a href="https://github.com/lissyx"&gt;lissyx&lt;/a&gt; was quick to fork it and rewrite the extension to fit the new Mozilla SDK but as we tried to submit the update to the Mozilla add-on site it got rejected due to security considerations. I'll now try to find a way to bring it back to the official add-on site by making a few changes requested by Mozilla but until then, here's a workaround:&lt;/p&gt;
&lt;h2&gt;Download the Addon Bar addon&lt;/h2&gt;
&lt;p&gt;Since a lot of people miss the add-on bar, a new add-on called &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/the-addon-bar/"&gt;the addon bar (restored)&lt;/a&gt; brings back the add-on bar : ) If you add this add-on, the ForceCORS button becomes visible again without configuration. You can use the customize menu to move the button elsewhere but you need to keep this addon installed to keep it there.&lt;/p&gt;
&lt;h2&gt;Install ForceCORS manually&lt;/h2&gt;
&lt;p&gt;If you've lost the ForceCORS extension after it was removed from the Mozilla add-on site, you can re-install it manually by downloading the XPI-file &lt;a href="http://cdn.www-jo.se/f.pfleger/msc/forcecors-workaround/forcecors@ocact.us.xpi"&gt;here&lt;/a&gt; and then opening it in Firefox.&lt;/p&gt;
&lt;p&gt;Thanks everyone for reporting and discussing the issues - please continue to do so &lt;a href="https://github.com/jo5ef/Force-CORS"&gt;here&lt;/a&gt;. I'll try to get it back to an official add-on as soon as I can.&lt;/p&gt;
</description><pubDate>Mon, 02 Jun 2014 17:49:56 +0200</pubDate><guid>http://www-jo.se/f.pfleger/forcecors-workaround</guid></item><item><title>Expanding My Horizon</title><link>http://www-jo.se/f.pfleger/expanded-horizon</link><description>
&lt;p&gt;It's been a while since I last blogged on my blog. One of the many things I've been up to recently is learning how to fly. As a member of a local aeroclub I can now take an airplane to the sky and literally expand my horizon!&lt;/p&gt;
&lt;p&gt;To find out exactly how much expandin' is really possible, I hacked together some Javascript that allows me to enter different cruise speeds (in knots) and endurances (in hours) and overlays it on Google Maps. Here's a screenshot:&lt;/p&gt;
&lt;p&gt;&lt;img alt="range screenshot" src="https://cdn.www-jo.se/f.pfleger/msc/expanded-horizon/range.png" /&gt;&lt;/p&gt;
&lt;p&gt;Needless to say this is a very rough estimate as it doesn't take any air space restrictions, terrain, weather, climbs or descents into consideration, but it's still fun to enter different aircraft's performance characteristics and imagine where they would take me :)&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cdn.www-jo.se/f.pfleger/msc/range.html"&gt;Try it out!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was the first time I used the Google Maps API and I have to say that it is really simple and easy to use. It works well and the documentation is good.&lt;/p&gt;
</description><pubDate>Sat, 18 May 2013 18:57:32 +0200</pubDate><guid>http://www-jo.se/f.pfleger/expanded-horizon</guid></item><item><title>Taking Notes</title><link>http://www-jo.se/f.pfleger/notebook</link><description>
&lt;p&gt;Something I never did as a student was taking notes. I just didn't think it was cool. But things change and I now take &lt;em&gt;a lot of&lt;/em&gt; notes. Most of them I take at work during meetings, interviews, trainings etc but my notebook is also full of spontaneous ideas, scribbles, numbers, code snippets, stack traces, quotes and other things.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Obviously&lt;/em&gt; I don't carry around a pen and something made out of paper all day long. I type &lt;a href="http://data.typeracer.com/pit/profile?user=jo5ef&amp;amp;universe=accuracy"&gt;fast enough&lt;/a&gt; to protect the trees and read and write my notes digitally. When I started digital note-taking, I looked at &lt;a href="http://www.evernote.com/"&gt;evernote&lt;/a&gt; and its type of software and was shocked by the feature overload in some of these tools.&lt;/p&gt;
&lt;p&gt;Here's what I need from a note-taking application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a (big) &lt;em&gt;plaintext&lt;/em&gt;box to enter my note&lt;/li&gt;
&lt;li&gt;store a timestamp for each note&lt;/li&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;search&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it. No video, no Facebook, no Foursquare, no Twitter. &lt;a href="http://www.google.com/notebook"&gt;Google Notebook&lt;/a&gt; called tags 'labels' and had richtext but was otherwise exactly what I wanted. It also worked on every device that supported HTML and I used it every single day. And then this happened:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="https://cdn.www-jo.se/f.pfleger/msc/notebook/google-notebook.png" /&gt;&lt;/p&gt;
&lt;p&gt;This sucked. I guess when a Google application gets less than five million users they say &lt;em&gt;"noone is using this"&lt;/em&gt; and just turn it off. And sure enough it was in read-only mode a few days later. Coming back from &lt;a href="http://www.google.com/events/developerday/2011/"&gt;#gdd11&lt;/a&gt;, I decided to give the &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt; a try and implemented my own notebook within a few hours:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot" src="https://cdn.www-jo.se/f.pfleger/msc/notebook/notebook-screenshot.png" /&gt;&lt;/p&gt;
&lt;p&gt;Nothing fancy but it does everything Google Notebook did for me. It works and I've used it every day since. Feel free to use it with your own Google account:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://notebook-ocactus.appspot.com/"&gt;https://notebook-ocactus.appspot.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, the codez are on github, in case you need another GAE sample :)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jo5ef/notebook"&gt;https://github.com/jo5ef/notebook&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;
</description><pubDate>Sat, 17 Dec 2011 21:05:30 +0100</pubDate><guid>http://www-jo.se/f.pfleger/notebook</guid></item><item><title>A Memory Leak brought to you by XmlSerializer</title><link>http://www-jo.se/f.pfleger/memoryleak</link><description>
&lt;p&gt;We ran into an interesting memory leak the other day. When one of my colleagues analyzed the memory dump from production, he saw an unusual amount of types in 
&lt;code&gt;*.GeneratedAssembly.*&lt;/code&gt; namespaces, one instance each:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0:007&amp;gt; !dumpheap -stat
Statistics:
              MT    Count    TotalSize Class Name
000007ff0024da98        1           24 System.Xml.Serialization.TempAssemblyCache
000007ff002474f8        1           24 System.Xml.Serialization.Configuration.RootedPathValidator
...
000007ff00441d98        1           40 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract
000007ff004412c8        1           40 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract
000007ff004407f8        1           40 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract
000007ff003ef9b0        1           40 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract
000007ff003eeee0        1           40 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializerContract
... and more
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;He also found the method &lt;code&gt;XmlSerializer.GenerateTempAssembly&lt;/code&gt; in call stacks and soon thereafter the explanation &lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=VS.100).aspx"&gt;online&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To increase performance, the XML serialization infrastructure dynamically generates assemblies to serialize and deserialize specified types. The 
infrastructure finds and reuses those assemblies. This behavior occurs only when using the following constructors:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;XmlSerializer.XmlSerializer(Type)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;XmlSerializer.XmlSerializer(Type, String)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If you use any of the other constructors, multiple versions of the same assembly are generated and never unloaded, which results in a memory leak and poor 
performance. The easiest solution is to use one of the previously mentioned two constructors. Otherwise, you must cache the assemblies in a Hashtable, as 
shown in the following example.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=VS.100).aspx"&gt;&lt;em&gt;from MSDN&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Turned out we were (indirectly) using one of the &lt;code&gt;XmlSerializer&lt;/code&gt; constructors that cause this documented memory leak. This also popped up in &lt;a href="http://blogs.msdn.com/b/tess/archive/2006/02/15/532804.aspx"&gt;many&lt;/a&gt; &lt;a href="http://social.msdn.microsoft.com/Forums/ar/netfxbcl/thread/052e4512-ec4f-4c6f-b903-4ab942b7294a"&gt;other&lt;/a&gt; &lt;a href="http://www.google.com/?q=xmlserializer%20memory%20leak"&gt;places&lt;/a&gt; online and can be easily reproduced with a few lines of code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class Brick { }

while(true)
{
    var s = new XmlSerializer(typeof(Brick), new Type[] {});
    s.Serialize(Stream.Null, new Brick { });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Isn't that some very fine memory leaking code? Not only is it eating up memory, it is also generating, loading (and deleting) &lt;code&gt;*.dll&lt;/code&gt; files in your temp-path 
(e.g. &lt;code&gt;C:\Users\josef\AppData\Local\Temp&lt;/code&gt;) and is therefore incredibly slow. The Hanselman &lt;a href="http://www.hanselman.com/blog/HOWTODebugIntoANETXmlSerializerGeneratedAssembly.aspx"&gt;already taught us&lt;/a&gt; how we can make the generated code visible:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
   &amp;lt;system.diagnostics&amp;gt;
      &amp;lt;switches&amp;gt;
         &amp;lt;add name="XmlSerialization.Compilation" value="1" /&amp;gt;
      &amp;lt;/switches&amp;gt;
   &amp;lt;/system.diagnostics&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this switch set to &lt;code&gt;1&lt;/code&gt;, the C# code for each generated assembly will be written into &lt;code&gt;*.cs&lt;/code&gt; files so if you run the code above, your temp-dir will be flooded:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\josef\AppData\Local\Temp&amp;gt;dir *.cs
 Volume in drive C has no label.
 Volume Serial Number is ####-####

 Directory of C:\Users\josef\AppData\Local\Temp

10/26/2011  05:11 PM             9,260 0r2upaee.0.cs
10/26/2011  05:11 PM             9,260 0wvlt0sz.0.cs
10/26/2011  05:11 PM             9,260 12x20ris.0.cs
10/26/2011  05:11 PM             9,260 1bsq04ge.0.cs
10/26/2011  05:11 PM             9,260 1wvkuolg.0.cs
10/26/2011  05:11 PM             9,260 1y4yyetd.0.cs
10/26/2011  05:11 PM             9,260 20yixjrc.0.cs
10/26/2011  05:11 PM             9,243 23qz4yru.0.cs
10/26/2011  05:11 PM             9,260 2vt3hznp.0.cs
...
         101 File(s)        926,038 bytes
           0 Dir(s)  91,353,591,808 bytes free
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The recommended way to get around this issue is to use one of the two &lt;em&gt;safe&lt;/em&gt; constructors (see above) if you can, or cache the &lt;code&gt;XmlSerializer&lt;/code&gt; instances by yourself. We went for the latter.&lt;/p&gt;
</description><pubDate>Wed, 26 Oct 2011 18:16:57 +0200</pubDate><guid>http://www-jo.se/f.pfleger/memoryleak</guid></item><item><title>Force CORS Firefox Extension</title><link>http://www-jo.se/f.pfleger/forcecors</link><description>
&lt;p&gt;I've created a very simple extension for Firefox that adds the Cross Origin Resource Sharing (&lt;a href="http://www.w3.org/TR/cors/"&gt;CORS&lt;/a&gt;) &lt;code&gt;Access-Control-&lt;/code&gt; HTTP headers to all responses before they're processed by the browser. This essentially disables the browser's same origin policy and allows cross domain calls even if the web server does not support CORS.&lt;/p&gt;
&lt;p&gt;The default setting adds the following headers to &lt;em&gt;every&lt;/em&gt; response:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be customized in the &lt;code&gt;forcecors.headers&lt;/code&gt; setting via &lt;code&gt;about:config&lt;/code&gt;, the values are separated by spaces &lt;em&gt;(and yes, you may add arbitrary, cors-unrelated headers :)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Force CORS is going to be very helpful for my numerous Javascript/HTML5 hacks (diagnostic scripts, little helpers, mashups, etc.) that load data from websites I don't control :)&lt;/p&gt;
&lt;p&gt;The code is available on &lt;a href="https://github.com/jo5ef/Force-CORS"&gt;github&lt;/a&gt;, feel free to fork it.&lt;/p&gt;
&lt;p&gt;And here's the link to Mozilla's "AMO":&lt;/p&gt;
&lt;p&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/forcecors/"&gt;https://addons.mozilla.org/en-US/firefox/addon/forcecors/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Oh, and a warning: Force CORS circumvents the browser's same origin policy, so be careful (i.e. don't use it if you don't know what you're doing).&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Update&lt;/h2&gt;
&lt;p&gt;There's &lt;a href="http://www-jo.se/f.pfleger/forcecors-workaround"&gt;a problem&lt;/a&gt; with the Mozilla add-on site.&lt;/p&gt;
</description><pubDate>Mon, 01 Aug 2011 02:05:22 +0200</pubDate><guid>http://www-jo.se/f.pfleger/forcecors</guid></item><item><title>Cannot add graphics to virtual machine</title><link>http://www-jo.se/f.pfleger/libvirt-bug</link><description>
&lt;p&gt;I use &lt;a href="http://libvirt.org"&gt;libvirt&lt;/a&gt; and &lt;a href="http://www.linux-kvm.org/"&gt;kvm&lt;/a&gt; to run two virtual machines (a linux and a windows guest) on a debian host. Both guests run without a &lt;code&gt;&amp;lt;graphics/&amp;gt;&lt;/code&gt; section in their config because I use &lt;code&gt;ssh&lt;/code&gt; and &lt;code&gt;rdp&lt;/code&gt; to admin these systems.&lt;/p&gt;
&lt;p&gt;Last night I broke the network for the windows guest while upgrading the host from &lt;a href="http://www.debian.org/releases/lenny/"&gt;lenny&lt;/a&gt; to &lt;a href="http://www.debian.org/releases/squeeze/"&gt;squeeze&lt;/a&gt; so I wanted to temporarily enable &lt;code&gt;&amp;lt;graphics type='vnc'/&amp;gt;&lt;/code&gt; for troubleshooting. I &lt;code&gt;virsh edit&lt;/code&gt; the windows domain and added the following line to the &lt;code&gt;&amp;lt;devices/&amp;gt;&lt;/code&gt; section in its config:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;graphics type='vnc' listen='0.0.0.0:0'/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, saving the config always resulted in the following error message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;virsh # edit windows
error: internal error unable to reserve PCI address 0:0:2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I tried to run &lt;code&gt;kvm&lt;/code&gt; directly by passing a &lt;code&gt;-vnc :0&lt;/code&gt; switch instead of &lt;code&gt;-nographic&lt;/code&gt; but that didn't work either:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TUNGETIFF ioctl() failed: Bad file descriptor
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Turns out I had run into a bug (&lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=692355"&gt;&lt;em&gt;"qemu: Always reserves slot 0x02 for primary VGA. (Osier Yang)"&lt;/em&gt;&lt;/a&gt;) that always took pci slot 0x02 for vga. Since my guest already had its network interface configured to that slot, things did not work out.&lt;/p&gt;
&lt;p&gt;The fix was to move around the pci slot assignments in the config and allow &lt;code&gt;&amp;lt;graphics/&amp;gt;&lt;/code&gt; to use 0x02 (irrelevant sections omitted):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;devices&amp;gt;
  &amp;lt;!-- emulator, disk, etc. omitted --&amp;gt;
  &amp;lt;controller type='ide' index='0'&amp;gt;
    &amp;lt;address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/&amp;gt;
  &amp;lt;/controller&amp;gt;
  &amp;lt;interface type='bridge'&amp;gt;
    &amp;lt;!-- mac, source, target, model, etc. omitted --&amp;gt;
    &amp;lt;address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/&amp;gt;
  &amp;lt;/interface&amp;gt;
  &amp;lt;graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0:0'/&amp;gt;
  &amp;lt;video&amp;gt;
    &amp;lt;model type='cirrus' vram='9216' heads='1'/&amp;gt;
    &amp;lt;address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/&amp;gt;
  &amp;lt;/video&amp;gt;
  &amp;lt;memballoon model='virtio'&amp;gt;
    &amp;lt;address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/&amp;gt;
  &amp;lt;/memballoon&amp;gt;
&amp;lt;/devices&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That allowed me to boot the guest and connect to it on display &lt;code&gt;:0&lt;/code&gt; via vnc.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=692355"&gt;bug&lt;/a&gt; was fixed in libvirt 0.9.2-1.el6 but since the host is on &lt;a href="http://www.debian.org/releases/squeeze/"&gt;squeeze&lt;/a&gt;, it is using &lt;a href="http://packages.debian.org/squeeze/libvirt-bin"&gt;libvirt 0.8.3-5&lt;/a&gt;.&lt;/p&gt;
</description><pubDate>Sun, 31 Jul 2011 12:22:21 +0200</pubDate><guid>http://www-jo.se/f.pfleger/libvirt-bug</guid></item><item><title>CORS and IIS</title><link>http://www-jo.se/f.pfleger/cors-and-iis</link><description>
&lt;p&gt;Last time, I &lt;a href="http://www-jo.se/f.pfleger/cors"&gt;wrote about&lt;/a&gt; Cross-Origin Resource Sharing (&lt;a href="http://www.w3.org/TR/cors/"&gt;CORS&lt;/a&gt;). This time I'll show how it can be implemented with Microsoft's Internet Information Services (IIS), ASP.Net and &lt;a href="http://www.jquery.com/"&gt;jQuery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let's assume we have two very separate web applications:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://cooking/&lt;/code&gt;, a website that is full of delicous cooking recipes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://shopping/&lt;/code&gt;, a website that allows users to make shopping lists&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, we implement &lt;code&gt;http://shopping/&lt;/code&gt; by adding &lt;code&gt;127.0.0.1 shopping&lt;/code&gt; to the hostfile and creating an empty ASP.NET web application with only one file (&lt;code&gt;list.aspx&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;%@ Page Language="C#" ContentType="application/json" %&amp;gt;
[
    { "amount": "2", "name": "Apples" },
    { "amount": "4", "name": "Bananas" },
    { "amount": "8", "name": "Cookies" }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That was fast.&lt;/p&gt;
&lt;p&gt;Now the guys from &lt;code&gt;http://cooking/&lt;/code&gt; would like to show shopping lists on their site and allow users to add ingredients for the recipe they're looking at to their list. They add the following Javascript to their recipe-detail page to retrieve a user's current shopping list:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$.ajax({
    url: 'http://shopping/list.aspx',
    dataType: 'json',
    success: function(data) {
        // render shopping list items to page
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately this call is blocked due to the &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;same origin policy&lt;/a&gt;. Luckily the girls from &lt;code&gt;http://shopping/&lt;/code&gt; want the whole world to use their shopping lists so they add an HTTP Header &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt; to their response. This can be done in the IIS Manager&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IIS6: in the Web's properties dialog under 'HTTP Headers'&lt;/li&gt;
&lt;li&gt;IIS7: in the 'HTTP Response Headers' section of the 'Features View', or web.config&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is what the response from &lt;code&gt;http://shopping/list.aspx&lt;/code&gt; looks like after the change:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
Date: Sun, 17 Jul 2011 14:21:59 GMT
Content-Length: 124

[
    { "amount": "2", "name": "Apples" },
    { "amount": "4", "name": "Bananas" },
    { "amount": "8", "name": "Cookies" }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now everybody, including the script on &lt;code&gt;http://cooking&lt;/code&gt;, is allowed to retrieve the shopping list.&lt;/p&gt;
&lt;p&gt;Additionally it should be possible for users on &lt;code&gt;http://cooking&lt;/code&gt; to click a link 'add to shopping list' while they browse the ingredients for a recipe. The cooking-guys add the following Javascript to their site and have it run when users click on these links.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$.ajax({
    type: 'POST',
    url: 'http://shopping/list.aspx',
    contentType: 'json',
    dataType: 'json',
    data: JSON.stringify({
        amount: 16,
        name: 'Dark Chocolates'
    }),
    success: function (data) {
        // render shopping list items to page
    },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will &lt;code&gt;POST&lt;/code&gt; the new item (16 Dark Chocolates) to the list but since it is a different domain, the browser will first query &lt;code&gt;Access-Control&lt;/code&gt; with an &lt;code&gt;OPTIONS&lt;/code&gt; request:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;OPTIONS http://shopping/list.aspx HTTP/1.1
Host: shopping
Origin: http://cooking
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In particular it checks for the permission to &lt;code&gt;POST&lt;/code&gt; with a header &lt;code&gt;content-type&lt;/code&gt;. Fortunately the &lt;code&gt;http://shopping&lt;/code&gt; site responds with&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Server: Microsoft-IIS/7.5
Public: OPTIONS, TRACE, GET, HEAD, POST
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST
Access-Control-Allow-Headers: Content-Type
Date: Sun, 17 Jul 2011 17:49:22 GMT
Content-Length: 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so the browser goes ahead with the original &lt;code&gt;POST&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;POST http://shopping/list.aspx HTTP/1.1
Host: shopping
Content-Type: json; charset=UTF-8
Referer: http://cooking/
Content-Length: 38
Origin: http://cooking

{"amount":16,"name":"Dark Chocolates"}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is possible that everything already works for you after configuring the two additional &lt;code&gt;Access-Control-&lt;/code&gt; headers (&lt;code&gt;-Allow-Methods&lt;/code&gt; and &lt;code&gt;-Allow-Headers&lt;/code&gt;). IIS7 has an &lt;code&gt;OPTIONSVerbHandler&lt;/code&gt; configured by default that will respond with all configured custom headers, including the &lt;code&gt;Access-Control-&lt;/code&gt; headers. In IIS6, there is no such mapping and depending on your setup it is likely that you need to explicitly allow the &lt;code&gt;OPTIONS&lt;/code&gt; verb. In IIS6 this setting is certainly not obvious but you can find it in the website's &lt;em&gt;Properties -&amp;gt; Home Directory -&amp;gt; Configuration... -&amp;gt; Mappings -&amp;gt; .aspx -&amp;gt; Verbs -&amp;gt; Limit to&lt;/em&gt;. If you're using a different handler (e.g. WCF) you'll have to add it to the appropriate mapping (e.g. '.svc'). This will allow your ASP.Net application to receive &lt;code&gt;OPTIONS&lt;/code&gt; requests. One way to handle these requests is to simply end the response in the &lt;code&gt;Global.asax&lt;/code&gt;'s &lt;code&gt;Application_BeginRequest&lt;/code&gt; method, optionally also setting the &lt;code&gt;Access-Control-&lt;/code&gt; headers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;void Application_BeginRequest(object sender, EventArgs e)
{
    var ctx = HttpContext.Current;
    if (ctx.Request.HttpMethod == "OPTIONS")
    {
        //ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
        ctx.Response.End();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some other things to look out for when it doesn't work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don't just rely on your browser plugins (&lt;a href="https://addons.mozilla.org/de/firefox/addon/firebug/"&gt;Firebug&lt;/a&gt; etc.) to find out what happened. Use a debugging proxy (e.g. &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt;, &lt;a href="http://www.charlesproxy.com/"&gt;Charles&lt;/a&gt;, etc.) or network tools (e.g. &lt;a href="http://www.wireshark.org/"&gt;Wireshark&lt;/a&gt;). There is a really fine line between request-blocked-by-browser (i.e. no request actually happened), &lt;code&gt;OPTIONS&lt;/code&gt; request problems and &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;POST&lt;/code&gt; problems. The plugins' error messages are not always helpful (e.g. '405 Method not allowed')&lt;/li&gt;
&lt;li&gt;Depending on your ajax-call setup and content type (json, xml, etc.) you might have to add the &lt;code&gt;Accept&lt;/code&gt; header to the list of &lt;code&gt;-Allow-Headers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If there is a problem with the &lt;code&gt;OPTIONS&lt;/code&gt; request, check the &lt;code&gt;&amp;lt;system.webServer&amp;gt;&amp;lt;handlers&amp;gt;&lt;/code&gt; section, there may be handlers with verb limits configured (IIS7 only)&lt;/li&gt;
&lt;li&gt;If there are still problems with the &lt;code&gt;OPTIONS&lt;/code&gt; request, check the &lt;code&gt;&amp;lt;system.web&amp;gt;&amp;lt;httpHandlers&amp;gt;&lt;/code&gt; section for custom handlers&lt;/li&gt;
&lt;li&gt;Don't forget about any firewall or security tools that are filtering requests with specific (or unknown) verbs or headers (e.g. &lt;a href="http://technet.microsoft.com/en-us/security/cc242650"&gt;UrlScan&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is the full sample code: &lt;a href="http://cdn.www-jo.se/f.pfleger/msc/cors-and-iis/cors-and-iis.zip"&gt;cors-and-iis.zip&lt;/a&gt;&lt;/p&gt;
</description><pubDate>Sun, 17 Jul 2011 20:05:47 +0200</pubDate><guid>http://www-jo.se/f.pfleger/cors-and-iis</guid></item><item><title>Cross-Origin Resource Sharing</title><link>http://www-jo.se/f.pfleger/cors</link><description>
&lt;p&gt;If you ever tried to make a request to a different domain using Javascript inside a web browser, you've probably encountered what's known as the &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;&lt;em&gt;same origin policy&lt;/em&gt;&lt;/a&gt;. This security feature basically blocks all calls that a script tries to make to an origin (protocol + host + port) that is different from its own.&lt;/p&gt;
&lt;p&gt;For communication across sub-domains, the &lt;code&gt;document.domain&lt;/code&gt; feature &lt;a href="http://www-jo.se/f.pfleger/cross-sub-domain-xml"&gt;can be used&lt;/a&gt;. Over time, a number of ways to achieve cross-domain communication have popped up but most of them are &lt;em&gt;hacks&lt;/em&gt; (fragments, &lt;code&gt;window.name&lt;/code&gt;, JSONP, etc.). While there are some libraries that abstract these hacks and choose the most appropriate method for the given browser (e.g. &lt;a href="http://easyxdm.net/wp/"&gt;easyXDM&lt;/a&gt;), it's time to start using newer technologies that provide explicit support for cross domain calls.&lt;/p&gt;
&lt;p&gt;HTML5 comes with a more generic cross-document-messaging mechanism via &lt;a href="http://www.w3.org/TR/html5/comms.html#crossDocumentMessages"&gt;&lt;code&gt;postMessage&lt;/code&gt;&lt;/a&gt; that allows scripts to send messages to other windows and documents. But there is another exciting way to explicitly allow cross-domain HTTP requests on the server side: a W3C Working Draft called &lt;a href="http://www.w3.org/TR/cors/"&gt;Cross-Origin Resource Sharing&lt;/a&gt;. The idea is extremely simple. A domain can choose to allow calls from different domains by adding &lt;code&gt;Access-Control-&lt;/code&gt; HTTP headers to its response. Example response:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK
Date: Sun, 17 Jul 2011 17:37:32 GMT
Server: Apache/2.2.16 (Debian)
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST
Access-Control-Allow-Headers: Content-Type,Accept
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows any script on any domain (&lt;code&gt;-Allow-Origin: *&lt;/code&gt;) to make requests to this server using &lt;code&gt;GET&lt;/code&gt;s and &lt;code&gt;POST&lt;/code&gt;s and some headers to specify content types (xml, json, javascript, etc.). Cool, eh?&lt;/p&gt;
&lt;p&gt;Cross-Origin Resource Sharing (CORS) allows for very fine-grained access control and is supported by &lt;a href="http://caniuse.com/#search=cors"&gt;a lot of popular browsers&lt;/a&gt; (basically everyone but Opera). Here's how you &lt;a href="http://www-jo.se/f.pfleger/cors-and-iis"&gt;implement CORS in IIS and ASP.Net&lt;/a&gt;.&lt;/p&gt;
</description><pubDate>Sun, 17 Jul 2011 20:03:39 +0200</pubDate><guid>http://www-jo.se/f.pfleger/cors</guid></item><item><title>Flash + Flex + REST = :-(</title><link>http://www-jo.se/f.pfleger/restful-flash</link><description>
&lt;p&gt;We've built the world's most beautiful web API and have done our best to comply with all &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;constraints&lt;/a&gt; for representational state transfers. It's been in production for quite some time and used by a few clients, including apps for both iPhones and Androids.&lt;/p&gt;
&lt;p&gt;As a next step, we want to make our own (&lt;em&gt;popular&lt;/em&gt;) flash application an official API client and deprecate all the custom-made feeds we've created for it in the past. Sounds awesome. Turns out, it is not awesome. When hosted in a browser, Flash has several limitations that make it very difficult to use a RESTful web service correctly. &lt;/p&gt;
&lt;h2&gt;Setting HTTP Headers is unreliable&lt;/h2&gt;
&lt;p&gt;Standard HTTP Headers cannot be used reliably because their behavior strongly depends on the combination of browser and flash player version. Example: Let's assume the API supports different request and response formats via &lt;code&gt;Content-Type&lt;/code&gt; and &lt;code&gt;Accept&lt;/code&gt; headers. Setting the request's &lt;code&gt;Accept&lt;/code&gt; header to &lt;code&gt;application/json&lt;/code&gt; will work fine in Chrome for Mac 11.0.696.57 with Flash Player 10.2.154.27 but Firefox for Mac 4.0 with Flash Player 10.1.102.64 will just send whatever &lt;code&gt;Accept&lt;/code&gt; header the browser sends with all requests (in this case &lt;code&gt;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Custom HTTP Headers only work for POSTs&lt;/h2&gt;
&lt;p&gt;Due to a &lt;a href="https://bugs.adobe.com/jira/browse/FP-209"&gt;bug&lt;/a&gt; in the Flash Player, custom HTTP headers cannot be sent with &lt;code&gt;GET&lt;/code&gt;s. This is still open at the moment, and once it is fixed, it will be another thing that strongly depends on the user's flash player version.&lt;/p&gt;
&lt;h2&gt;Methods other than GET and POST are not supported&lt;/h2&gt;
&lt;p&gt;Although this seems to be a browser limitation rather than a flash player limitation, only HTTP &lt;code&gt;GET&lt;/code&gt;s and &lt;code&gt;POST&lt;/code&gt;s are supported (&lt;a href="https://bugs.adobe.com/jira/browse/SDK-12200"&gt;tracked&lt;/a&gt; &lt;a href="https://bugs.adobe.com/jira/browse/SDK-20769"&gt;here&lt;/a&gt;). Workarounds include the (in)famous &lt;code&gt;X-Method-Override&lt;/code&gt; header, and the &lt;code&gt;_method&lt;/code&gt; url parameter with all its fans in the ruby community.&lt;/p&gt;
&lt;p&gt;In addition, apparently sometimes &lt;code&gt;POST&lt;/code&gt;s are turned into &lt;code&gt;GET&lt;/code&gt;s &lt;a href="http://verveguy.blogspot.com/2008/07/truth-about-flex-httpservice.html"&gt;under specific circumstances&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Problems with HTTP Response&lt;/h2&gt;
&lt;p&gt;There are several issues regarding the HTTP response. HTTP response headers are hidden (&lt;a href="http://bugs.adobe.com/jira/browse/FP-251"&gt;bug&lt;/a&gt;), HTTP status codes cannot be retrieved (&lt;a href="http://bugs.adobe.com/jira/browse/FP-721"&gt;not supported&lt;/a&gt;), and the body cannot be accessed for responses with status codes other than 200 (&lt;a href="http://bugs.adobe.com/jira/browse/FP-251"&gt;feature&lt;/a&gt;).&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Although all of the above sound horrific, maybe none of it will be an actual problem for our endeavor. We'll do with &lt;code&gt;GET&lt;/code&gt;s and &lt;code&gt;POST&lt;/code&gt;s, move our token from the custom HTTP header to the URL and mitigate the response format issue by defining a default response format (e.g. &lt;code&gt;application/json&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.atnan.com/2007/6/11/can-as3-do-rest-or-not"&gt;Can AS3 do REST, or not?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://verveguy.blogspot.com/2008/07/truth-about-flex-httpservice.html"&gt;The Truth about Flex HTTPService&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/q/153420/98401"&gt;Stackoverflow: Is it feasible to create a REST client with Flex?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: I'm not a flash developer (and don't want to be one :) but I see the team that is trying to use our API run into these issues.&lt;/em&gt;&lt;/p&gt;
</description><pubDate>Sat, 30 Apr 2011 13:08:09 +0200</pubDate><guid>http://www-jo.se/f.pfleger/restful-flash</guid></item><item><title>Why a WCF's WSDL works, but its inline XSDs don't</title><link>http://www-jo.se/f.pfleger/wsdlxsdfail</link><description>
&lt;p&gt;You have some extra time and are looking for a WCF related puzzle that will waste some of it? Awesome. Here's what you can do:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Create a simple WCF service, host it in IIS and change its application pool's identity to a windows user you create and only provide with the minimum set of permissions you think it needs. Then create a proxy and try to make a successful call to the service &lt;em&gt;without&lt;/em&gt; reading the rest of this post :)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Apparently if you don't grant the application pool's identity write permissions on &lt;code&gt;C:\Windows\Temp&lt;/code&gt;, &lt;a href="http://www.youtube.com/watch?v=cFods1KSWsQ"&gt;fascinating&lt;/a&gt; things happen to the service. It seems up, the &lt;code&gt;?wsdl&lt;/code&gt; works but proxies cannot be created because the XML schemas referenced within the WSDL fail to download. These are usually urls of type &lt;code&gt;?xsd=xsd0&lt;/code&gt;, &lt;code&gt;?xsd=xsd1&lt;/code&gt;, etc. Additionally, some tools (e.g. &lt;code&gt;svcutil.exe&lt;/code&gt;) and IIS get into an argument about MIME types, &lt;em&gt;HTTP code 415 'Other mime type expected, expected &lt;code&gt;application/soap+msbin1&lt;/code&gt; but got &lt;code&gt;application/soap+xml&lt;/code&gt;'&lt;/em&gt; and whatnot.&lt;/p&gt;
&lt;p&gt;Obviously the XSDs are somehow dynamically compiled and cached in &lt;code&gt;C:\Windows\Temp&lt;/code&gt; but it is certainly interesting to learn about this behavior if you encounter the aforementioned symptoms. Fortunately the fix is already &lt;a href="http://blogs.infosupport.com/blogs/raimondb/archive/2008/02/14/Unable-to-generate-a-WCF-proxy-using-svcutil-but-retreiving-the-wsdl-works_3F00_.aspx"&gt;out there&lt;/a&gt;.&lt;/p&gt;
</description><pubDate>Tue, 25 Jan 2011 00:44:53 +0100</pubDate><guid>http://www-jo.se/f.pfleger/wsdlxsdfail</guid></item><item><title>Implementing foreach-else for .Net (C#)</title><link>http://www-jo.se/f.pfleger/.net-for-else</link><description>
&lt;p&gt;I like the idea of having &lt;code&gt;else&lt;/code&gt;-branches for loops as &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt; supports them for its &lt;a href="http://docs.python.org/reference/compound_stmts.html#the-for-statement"&gt;&lt;code&gt;for&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://docs.python.org/reference/compound_stmts.html#the-while-statement"&gt;&lt;code&gt;while&lt;/code&gt;&lt;/a&gt; statements. It allows code like &lt;a href="http://docs.python.org/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops"&gt;this&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for i in range(2, n):
    if n % i == 0:
        print n, 'equals', i, '*', n / i
        break
else:
    print n, 'is a prime'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;else&lt;/code&gt; is executed &lt;em&gt;after&lt;/em&gt; the loop, &lt;em&gt;unless&lt;/em&gt; the loop is terminated by a &lt;code&gt;break&lt;/code&gt; statement. Pretty handy, I think. I've decided this is awesome enough to justify the following extension method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public static void ForEachElse&amp;lt;TSource&amp;gt;(
    this IEnumerable&amp;lt;TSource&amp;gt; source,
    Func&amp;lt;TSource, bool&amp;gt; action, Action @else)
{
    foreach (var i in source)
    {
        if (!action(i))
        {
            return;
        }
    }
    @else();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's your regular every day &lt;code&gt;foreach&lt;/code&gt; on &lt;code&gt;IEnumerable&lt;/code&gt; but allows you to specify both a "loop-action" and an "else-action" where the latter is executed &lt;em&gt;after&lt;/em&gt; the loop &lt;em&gt;unless&lt;/em&gt; you &lt;em&gt;break&lt;/em&gt; the loop by returning &lt;code&gt;false&lt;/code&gt; from the former. It's a tad clumsier than Python but still useful:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Enumerable.Range(2, n - 2).ForEachElse(i =&amp;gt;
{
    if (n % i == 0)
    {
        Console.WriteLine("{0} equals {1} * {2}", n, i, n / i);
        return false; // break
    }
    return true; // continue
},
() =&amp;gt; // else
{
    Console.WriteLine("{0} is a prime", n);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What do you think? Implementing &lt;code&gt;WhileElse&lt;/code&gt; is left as an exercise to the reader :)&lt;/p&gt;
</description><pubDate>Sun, 09 Jan 2011 01:33:08 +0100</pubDate><guid>http://www-jo.se/f.pfleger/.net-for-else</guid></item><item><title>soflair</title><link>http://www-jo.se/f.pfleger/soflair</link><description>
&lt;p&gt;Soflair is a (&lt;em&gt;very&lt;/em&gt;) simple widget for &lt;a href="http://www.android.com"&gt;Android&lt;/a&gt; that shows a user's &lt;a href="http://stackoverflow.com/users/flair"&gt;flair&lt;/a&gt; (avatar, reputation &amp;amp; badges) on any of the &lt;a href="http://stackexchange.com"&gt;stackexchange&lt;/a&gt; sites (&lt;a href="http://stackoverflow.com"&gt;stackoverflow&lt;/a&gt;, &lt;a href="http://serverfault.com"&gt;serverfault&lt;/a&gt;, &lt;a href="http://superuser.com"&gt;superuser&lt;/a&gt;, etc.). The JSON feed is polled every 60 minutes.&lt;/p&gt;
&lt;h2&gt;Screenshots&lt;/h2&gt;
&lt;p&gt;&lt;img alt="soflair screenshot" src="http://cdn.www-jo.se/f.pfleger/msc/soflair/soflair-screenshot.png" /&gt;&lt;/p&gt;
&lt;p&gt;The left screenshot shows how you configure the widget and the right shows it in action on an Android home screen.&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;p&gt;The code is available on &lt;a href="https://github.com/jo5ef/soflair"&gt;github&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Download&lt;/h2&gt;
&lt;p&gt;Please find 'soflair' in the &lt;a href="http://market.android.com/search?q=pname:org.ocactus.soflair"&gt;Android Market&lt;/a&gt; or use this QR-Code:&lt;/p&gt;
&lt;p&gt;&lt;img alt="soflair QR code" src="http://cdn.www-jo.se/f.pfleger/msc/soflair/soflair-qrcode.png" /&gt;&lt;/p&gt;
&lt;h2&gt;Supported Devices&lt;/h2&gt;
&lt;p&gt;I hope all Android, let me know if it doesn't work for you.&lt;/p&gt;
&lt;h2&gt;Changelog&lt;/h2&gt;
&lt;h3&gt;--- Version 2.8 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;moved to stackexchange api 2.2&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;--- Version 2.7 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;more room for full reputation display (rep will be truncated at 10^4 instead of 10^3)&lt;/li&gt;
&lt;li&gt;minor bugfix for invalid json responses&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;--- Version 2.6 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stackoverflow changed their 'recent'-url&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;--- Version 2.5 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;click on widget takes you to recent activity page&lt;/li&gt;
&lt;li&gt;Now displaying identicons for users without a gravatar&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;--- Version 2.4 ---&lt;/h3&gt;
&lt;p&gt;Now uses the Stackexchange API instead of the flair.json feed because the latter was turned off. You have to re-add your widget and configure a valid api-url (an example is provided).&lt;/p&gt;
&lt;h3&gt;--- Version 2.3 ---&lt;/h3&gt;
&lt;p&gt;Stackoverflow turned off the flair.json feed I was using. Unfortunately the widget responded with an ANR. Quickfix to make it stable.&lt;/p&gt;
&lt;h3&gt;--- Version 2.2 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;click on widget takes you to profile page&lt;/li&gt;
&lt;li&gt;configuration via full url -&amp;gt; &lt;em&gt;all&lt;/em&gt; stackexchange sites supported&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;--- Version 2.1 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;upgraded graphics for high resolutions (for my Nexus One :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;--- Version 1.0 ---&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Created long before this post&lt;/li&gt;
&lt;li&gt;At least now I have something to link to :)&lt;/li&gt;
&lt;/ul&gt;
</description><pubDate>Thu, 06 Jan 2011 17:27:36 +0100</pubDate><guid>http://www-jo.se/f.pfleger/soflair</guid></item><item><title>About Me</title><link>http://www-jo.se/f.pfleger/about</link><description>
&lt;p&gt;My name is Josef Pfleger and I am from Austria. I currently manage a team of software engineers at &lt;a href="http://www.bwin.com"&gt;bwin&lt;/a&gt; and live and work in Austria.&lt;/p&gt;
&lt;h2&gt;My interests&lt;/h2&gt;
&lt;p&gt;I'm interested in everything related to computers, especially software and its creation. Some of my other hobbies include flying small airplanes, scuba diving, playing the violin, snowboarding, soccer and some other sports.&lt;/p&gt;
&lt;h2&gt;Logo&lt;/h2&gt;
&lt;p&gt;I created the most awesome logo based on my initials. Here's a visual explanation:&lt;/p&gt;
&lt;p&gt;&lt;img alt="MakingOf Logo" src="http://cdn.www-jo.se/f.pfleger/msc/about/makingof_logo.png" /&gt;&lt;/p&gt;
&lt;p&gt;And here is the &lt;a href="http://cdn.www-jo.se/f.pfleger/msc/about/logo.svg"&gt;SVG&lt;/a&gt; and a picture of &lt;a href="http://cdn.www-jo.se/f.pfleger/msc/about/m&amp;amp;m_logo_1.jpg"&gt;M&amp;amp;M's&lt;/a&gt;.
And here is the LINQ to create it in ASCII art:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var r = 42; // radius

Func&amp;lt;double, int&amp;gt; f = h =&amp;gt; (int) Math.Round(h, 0);
int s = f(r * .8), i = f(r * .9), o = f(r * 1.1);

var jp = from y in Enumerable.Range(0, r * 2 + 1)
         from x in Enumerable.Range(0, r * 2 + 2)
         let d = f(Math.Sqrt(x * x + y * y - (2 * r * (x + y - r))))
         select x &amp;gt; r * 2 ? '\n' :
            (x &amp;lt; i &amp;amp;&amp;amp; (y &amp;lt; r ? d &amp;lt;= r : d &amp;lt;= s))
            || (x &amp;gt; o &amp;amp;&amp;amp; y &amp;lt; i &amp;amp;&amp;amp; d &amp;lt;= s)
            || (x &amp;gt; o &amp;amp;&amp;amp; y &amp;gt; o &amp;amp;&amp;amp; d &amp;lt;= r) ? '*' : ' ';

Console.WriteLine(jp.ToArray());
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Contact&lt;/h2&gt;
&lt;p&gt;If you need to contact me, please write me an eMail: &lt;a href="mailto:green-carrot@orange-cactus.org"&gt;green-carrot@orange-cactus.org&lt;/a&gt;. I have accounts on the most popular social networking sites but don't check these sites regularly.&lt;/p&gt;
</description><pubDate>Wed, 15 Dec 2010 15:13:24 +0100</pubDate><guid>http://www-jo.se/f.pfleger/about</guid></item><item><title>CDATA in Custom Configuration Sections</title><link>http://www-jo.se/f.pfleger/custom-config-cdata</link><description>
&lt;p&gt;Creating a custom configuration section with &lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationsection.aspx"&gt;&lt;code&gt;ConfigurationSection&lt;/code&gt;&lt;/a&gt; as described in &lt;a href="http://msdn.microsoft.com/en-us/library/2tw134k3.aspx"&gt;this MSDN article&lt;/a&gt; is less straightforward when you want to use more than just attributes (e.g. text or CDATA elements):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;section name="stats" type="X.StatsSection, X"/&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;stats&amp;gt;
        &amp;lt;sql&amp;gt;&amp;lt;![CDATA[SELECT * FROM tbl WHERE x &amp;lt; y]]&amp;gt;&amp;lt;/sql&amp;gt;
    &amp;lt;/stats&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you do as told, you'll see this exception:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;System.Configuration.ConfigurationErrorsException: The configuration section cannot contain a CDATA or text element.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fortunately, creating a custom &lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationelement.aspx"&gt;&lt;code&gt;ConfigurationElement&lt;/code&gt;&lt;/a&gt; and overriding its &lt;a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationelement.deserializeelement.aspx"&gt;&lt;code&gt;DeserializeElement&lt;/code&gt;&lt;/a&gt; method does the trick:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class StatsSection : ConfigurationSection
{
    [ConfigurationProperty("sql")]
    public SqlElement Sql { get { return this["sql"] as SqlElement; } }
}

class SqlElement : ConfigurationElement
{
    protected override void DeserializeElement(XmlReader reader, bool s)
    {
        Value = reader.ReadElementContentAs(typeof(string), null) as string;
    }

    public string Value { get; private set; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not &lt;a href="http://www.beendeleted.com/blog/2010/01/25/its-not-rocket-science/"&gt;rocket science&lt;/a&gt; but (&lt;em&gt;hopefully now less&lt;/em&gt;) difficult to find online.&lt;/p&gt;
</description><pubDate>Sun, 28 Nov 2010 17:55:55 +0100</pubDate><guid>http://www-jo.se/f.pfleger/custom-config-cdata</guid></item><item><title>Using AIDL with Eclipse and ADT</title><link>http://www-jo.se/f.pfleger/using-aidl</link><description>
&lt;p&gt;In my &lt;a href="http://www-jo.se/f.pfleger/android-package-size"&gt;Android Package Size&lt;/a&gt; post, I described how to retrieve the size of an android package. It requires the use of &lt;a href="http://developer.android.com/guide/developing/tools/aidl.html"&gt;AIDL&lt;/a&gt;, which is Android's &lt;a href="http://en.wikipedia.org/wiki/Interface_description_language"&gt;IDL&lt;/a&gt; for interprocess communication (IPC).&lt;/p&gt;
&lt;p&gt;Using Eclipse and &lt;a href="http://developer.android.com/guide/developing/eclipse-adt.html"&gt;ADT&lt;/a&gt;, working with AIDL files is very simple: When AIDL files are created or imported into the &lt;code&gt;src/&lt;/code&gt; folder, the ADT plugin automatically generates the interface definitions and stubs in the &lt;code&gt;gen/&lt;/code&gt; directory as part of the build.&lt;/p&gt;
&lt;p&gt;For example, to generate the &lt;code&gt;IPackageStatsObserver&lt;/code&gt; interface and stub for the code used in &lt;a href="http://www-jo.se/f.pfleger/android-package-size"&gt;Android Package Size&lt;/a&gt;: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download the AIDL files for &lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/content/pm/PackageStats.aidl;hb=HEAD"&gt;&lt;code&gt;PackageStats&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/content/pm/IPackageStatsObserver.aidl;hb=HEAD"&gt;&lt;code&gt;IPackageStatsObserver&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Create a new java package &lt;code&gt;android.content.pm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy or import both AIDL files to the new package&lt;/li&gt;
&lt;li&gt;The ADT plugin will generate the &lt;code&gt;IPackageStatsObserver&lt;/code&gt; interface and stub automatically in &lt;code&gt;gen/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The Android SDK also includes a (command line) compiler &lt;code&gt;aidl&lt;/code&gt; (in the &lt;code&gt;tools/&lt;/code&gt; directory) that you can use to generate the java code in case you don't use Eclipse.&lt;/p&gt;
</description><pubDate>Mon, 01 Nov 2010 10:03:18 +0100</pubDate><guid>http://www-jo.se/f.pfleger/using-aidl</guid></item><item><title>Upgrade to VS2010</title><link>http://www-jo.se/f.pfleger/migrate-to-VS2010</link><description>
&lt;p&gt;It's been exactly 11² days since Microsoft released Visual Studio 2010. Of course the fearless developer downloaded and installed every CTP and Beta version in the very millisecond it was available, but some places (i.e. &lt;em&gt;work&lt;/em&gt;) don't really welcome these additional adventures and productivity fluctuations.&lt;/p&gt;
&lt;p&gt;However, with the official release out for some time, we carefully upgraded our fairly large C# codebase from VS2008 to VS2010. Here's what we had in mind: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;upgrade our codebase to VS2010&lt;/li&gt;
&lt;li&gt;still have it work with VS2008 so not everyone on the team is forced to upgrade at the same time&lt;/li&gt;
&lt;li&gt;keep it simple (files) to avoid any crazy scm branching/merging/scripting&lt;/li&gt;
&lt;li&gt;keep the codebase at .NET 3.5, without upgrading to .NET 4.0&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don't let your first date with the VS2010 migration assistent (&lt;em&gt;wizard&lt;/em&gt;?) ruin your high hopes for the above. Try it, have a look at the result (including but not limited to)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;re-auto-generated code (designer files, proxies, etc.), including new fxcop violations if you're lucky ;)&lt;/li&gt;
&lt;li&gt;a couple of new migration files, logs and reports&lt;/li&gt;
&lt;li&gt;new sections in project files (bootstrapping and whatnot..)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... and then revert these changes and fire up your favorite editor. All you really need to do to make your project files open with both VS2008 and VS2010 is&lt;/p&gt;
&lt;h2&gt;1 Change the ToolsVersion&lt;/h2&gt;
&lt;p&gt;Change the &lt;code&gt;ToolsVersion&lt;/code&gt; attribute in the &lt;code&gt;&amp;lt;Project/&amp;gt;&lt;/code&gt; element from &lt;code&gt;3.5&lt;/code&gt; to &lt;code&gt;4.0&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Project DefaultTargets="Build"
         ToolsVersion="4.0"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2 Change the OldToolsVersion&lt;/h2&gt;
&lt;p&gt;Change the &lt;code&gt;&amp;lt;OldToolsVersion/&amp;gt;&lt;/code&gt; element from &lt;code&gt;2.0&lt;/code&gt; to &lt;code&gt;3.5&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;OldToolsVersion&amp;gt;3.5&amp;lt;/OldToolsVersion&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3 Conditional import of WebApplication.targets&lt;/h2&gt;
&lt;p&gt;If you have a WebApplication project, you need to create a conditional import for the &lt;code&gt;Microsoft.WebApplication.targets&lt;/code&gt; in order to support both paths:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Import Condition="'$(Solutions.VSVersion)' == '9.0'" Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" /&amp;gt;
&amp;lt;Import Condition="'$(Solutions.VSVersion)' == '10.0'" Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that's it. Your projects should open without any problems or migration wizard interruptions in both versions of Visual Studio. However, when you compile with VS2008 you will encounter the following warning&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Project file contains ToolsVersion="4.0", which is not supported by this version of MSBuild. Treating the project as if it had ToolsVersion="3.5".&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is obviously completely harmless and will not affect your build.&lt;/p&gt;
&lt;h2&gt;4 Create a separate solution file&lt;/h2&gt;
&lt;p&gt;Unfortunately we did not find a way to make solution files play in both studios so we ended up creating separate files &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Super.Clever.Service.sln
Super.Clever.Service.vs2010.sln
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Overall it was a very smooth transition where some team members didn't even notice that some of us were already using VS2010 :)&lt;/p&gt;
</description><pubDate>Wed, 11 Aug 2010 20:23:27 +0200</pubDate><guid>http://www-jo.se/f.pfleger/migrate-to-VS2010</guid></item><item><title>Android Package Size</title><link>http://www-jo.se/f.pfleger/android-package-size</link><description>
&lt;p&gt;Unfortunately there is currently &lt;a href="http://groups.google.com/group/android-developers/browse_thread/thread/e920aca2eac277f3"&gt;no public&lt;/a&gt; &lt;a href="http://groups.google.com/group/android-developers/browse_thread/thread/df94daae34336aad/f96a8425549c6637"&gt;api&lt;/a&gt; to retrieve size information about application packages. However, building on a technique I &lt;a href="http://www-jo.se/f.pfleger/apk-piracy"&gt;wrote about&lt;/a&gt; in the past, we can use the &lt;a href="http://developer.android.com/reference/android/content/pm/PackageManager.html"&gt;&lt;code&gt;PackageManager&lt;/code&gt;&lt;/a&gt;'s hidden &lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/content/pm/PackageManager.java;hb=HEAD"&gt;&lt;code&gt;getPackageSize&lt;/code&gt;&lt;/a&gt; method to retrieve an instance of &lt;a href="http://developer.android.com/reference/android/content/pm/PackageStats.html"&gt;&lt;code&gt;PackageStats&lt;/code&gt;&lt;/a&gt; that includes cache, code and data size information.&lt;/p&gt;
&lt;p&gt;First of all our application will need the &lt;code&gt;GET_PACKAGE_SIZE&lt;/code&gt; permission:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.GET_PACKAGE_SIZE"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;a href="http://developer.android.com/guide/developing/eclipse-adt.html"&gt;ADT&lt;/a&gt; we can &lt;a href="http://www-jo.se/f.pfleger/using-aidl"&gt;import the relevant AIDLs&lt;/a&gt; (&lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/content/pm/PackageStats.aidl;hb=HEAD"&gt;&lt;code&gt;PackageStats&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/content/pm/IPackageStatsObserver.aidl;hb=HEAD"&gt;&lt;code&gt;IPackageStatsObserver&lt;/code&gt;&lt;/a&gt;) into our project and have &lt;a href="http://developer.android.com/guide/developing/eclipse-adt.html"&gt;ADT&lt;/a&gt; generate stubs. With the stubs generated, we can simply use reflection to call the hidden &lt;a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob_plain;f=core/java/android/content/pm/PackageManager.java;hb=HEAD"&gt;&lt;code&gt;getPackageSize&lt;/code&gt;&lt;/a&gt; method and retrieve the &lt;a href="http://developer.android.com/reference/android/content/pm/PackageStats.html"&gt;&lt;code&gt;PackageStats&lt;/code&gt;&lt;/a&gt; instance in the stub's &lt;code&gt;onGetStatsCompleted&lt;/code&gt; callback method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PackageManager pm = getPackageManager();

Method getPackageSizeInfo = pm.getClass().getMethod(
    "getPackageSizeInfo", String.class, IPackageStatsObserver.class);

getPackageSizeInfo.invoke(pm, "com.android.mms", new IPackageStatsObserver.Stub() {

        @Override
        public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
            throws RemoteException {

            Log.i(TAG, "codeSize: " + pStats.codeSize);
        }
    });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this works it is obviously a &lt;em&gt;big hack&lt;/em&gt; to work around a missing piece of Android API. &lt;a href="http://www.androidguys.com/2009/12/14/code-pollution-reaching-past-the-sdk/"&gt;Reaching past the SDK&lt;/a&gt; is never a good idea, especially for public applications.&lt;/p&gt;
</description><pubDate>Thu, 08 Apr 2010 12:28:51 +0200</pubDate><guid>http://www-jo.se/f.pfleger/android-package-size</guid></item><item><title>Reload vs. Refresh in Firefox (Cache-Control)</title><link>http://www-jo.se/f.pfleger/firefox-reload</link><description>
&lt;p&gt;Do you know the difference between &lt;em&gt;load&lt;/em&gt;, &lt;em&gt;refresh&lt;/em&gt;, and &lt;em&gt;reload&lt;/em&gt; in your favorite browser? Shortcuts differ but there are roughly three different types of reloads available in most browsers, for example in Firefox:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;load&lt;/em&gt;: hit enter in the address bar; click on links&lt;/li&gt;
&lt;li&gt;&lt;em&gt;reload&lt;/em&gt;: &lt;code&gt;F5&lt;/code&gt;; &lt;code&gt;Ctrl+R&lt;/code&gt;; toolbar's refresh button; Menu -&amp;gt; Reload&lt;/li&gt;
&lt;li&gt;&lt;em&gt;hard reload&lt;/em&gt;: &lt;code&gt;Ctrl+F5&lt;/code&gt;; &lt;code&gt;Ctrl+Shift+R&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The terms &lt;em&gt;refresh&lt;/em&gt;, &lt;em&gt;reload&lt;/em&gt;, and &lt;em&gt;load&lt;/em&gt; are frequently used interchangeably and what I listed as a &lt;em&gt;hard reload&lt;/em&gt; is also known as &lt;a href="http://support.mozilla.com/en-US/forum/1/333668"&gt;&lt;em&gt;super refresh&lt;/em&gt;&lt;/a&gt; or &lt;a href="http://support.mozilla.com/en-US/kb/keyboard+shortcuts"&gt;&lt;em&gt;reload (override cache)&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All of this is not really important until you design (or test) features related to browser caching. Then you need to know what the above mean in terms of cache control. Provided the requested resource is in the browser cache and not stale, the following happens in Firefox:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;load&lt;/em&gt;: no request happens until the cached resource expires&lt;/li&gt;
&lt;li&gt;&lt;em&gt;reload&lt;/em&gt;: the request contains the &lt;code&gt;If-Modified-Since&lt;/code&gt; and &lt;code&gt;Cache-Control: max-age=0&lt;/code&gt; headers that allow the server to respond with &lt;code&gt;304 Not Modified&lt;/code&gt; if applicable&lt;/li&gt;
&lt;li&gt;&lt;em&gt;hard reload&lt;/em&gt;: the request contains the &lt;code&gt;Pragma: no-cache&lt;/code&gt; and &lt;code&gt;Cache-Control: no-cache&lt;/code&gt; headers and will bypass the cache&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although a simple concept, it has the potential to drive you into great debugging circles when you are not aware of the subtle differences between the different reload-variants :-)&lt;/p&gt;
</description><pubDate>Wed, 17 Mar 2010 20:32:00 +0100</pubDate><guid>http://www-jo.se/f.pfleger/firefox-reload</guid></item><item><title>Session State Lost in ASP.NET Web Farm</title><link>http://www-jo.se/f.pfleger/session-lost</link><description>
&lt;h2&gt;The Story.&lt;/h2&gt;
&lt;p&gt;One day (&lt;em&gt;recently&lt;/em&gt;) at work, high traffic asked for five new web servers in our existing ASP.NET Web Farm. Setup, turned on and polished, IT ops discretely told the load balancer about the fresh fish.&lt;/p&gt;
&lt;p&gt;But as soon as some of the traffic hit the five new boxes, we monitored an explosion of lost session exceptions in the event log. And it wasn't even limited to the five noob servers - the entire farm was on fire!&lt;/p&gt;
&lt;p&gt;Flabbergasted by the event, IT ops banished the deadly five from the farm and things calmed down immediately. After hours of investigating, fantasizing about race conditions, .NET, IIS, Windows bugs and debugging in a test farm, we finally found&lt;/p&gt;
&lt;h2&gt;The Problem.&lt;/h2&gt;
&lt;p&gt;Turns out &lt;a href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;325056&amp;amp;ID=KB;EN-US;325056"&gt;this very old article&lt;/a&gt; described our problem exactly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;325056&amp;amp;ID=KB;EN-US;325056"&gt;PRB: Session State Is Lost in Web Farm If You Use SqlServer or StateServer Session Mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The five new web servers had a slightly different IIS application path (&lt;code&gt;/LM/W3SVC/12/ROOT&lt;/code&gt;) configured than the rest of the bunch (&lt;code&gt;/LM/W3SVC/11/ROOT&lt;/code&gt;). Since the Stateserver combines the ASP.NET Session ID with the IIS application path to create a unique key, sessions issued for one of the five new webs could not be found when accessed through one of the other webs which is obviously extremely unfortunate in a weighted round robin load balanced web farm. Nevermind the &lt;a href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;325056&amp;amp;ID=KB;EN-US;325056"&gt;the old article&lt;/a&gt;'s &lt;em&gt;Applies To&lt;/em&gt; section, our setting was IIS6 and .NET 3.5 (32bit).&lt;/p&gt;
&lt;p&gt;Although the above incident temporarily smashed our dreams of scalability, it was awesome to come up with and discard hypotheses (our penultimate idea was a race condition) until we eventually acquired this microscopic piece of ASP.NET/IIS knowledge that none of us will ever forget :-)&lt;/p&gt;
</description><pubDate>Fri, 26 Feb 2010 23:56:57 +0100</pubDate><guid>http://www-jo.se/f.pfleger/session-lost</guid></item><item><title>Working around IE Bugs</title><link>http://www-jo.se/f.pfleger/workaround-ie-bugs</link><description>
&lt;p&gt;As someone who currently works in a team that is located close to the front end of a large web application, I am at times exposed to issues related to Internet Explorer and its numerous bugs, including (but not limited to) parsing, stylesheets, Javascript or rendering.&lt;/p&gt;
&lt;p&gt;Today, my now least favorite tester (kidding:) dropped the aforementioned type on me before I could run:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;On IE7, and only on IE7, there appears to be a white, 5 by 1 pixel line between the first and second image of the WasteTheUsersBandwidth feature. But only if you zoom in or out. The line is not visible at a regular zoom level and does not change in height at any other zoom level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Jackpot.&lt;/strong&gt; After reproducing (the bug) and issuing the appropriate WTFs, I reflected on some of the approaches I had taken in the past. In chronological order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;BFDIED (Brute Force Driven IE Development). Trial &amp;amp; Error until the 'correct' (but secret!) HTML/CSS/JS combination is found (~?h)&lt;/li&gt;
&lt;li&gt;Reduce the problem to a minimum reproducible version (&amp;gt;0.5h), 'understand' the IE bug (~?h), locate places in  respective specs and standards that 'prove' IE wrong (&amp;gt;0.5h), bash IE in emails &amp;amp; on web 2.0 (&amp;infin;h), and, eventually, if a suit asks nicely, work around the bug (&amp;lt;0.25h)&lt;/li&gt;
&lt;li&gt;Disavow the sucker. Procrastinate indefinitely and argue that there is no business value in fixing it which obviously implies its non-show-stopper status&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Number one and two are extremely frustrating and most often incredibly time consuming. Three does help developers maintain sanity but does not really solve any problems.&lt;/p&gt;
&lt;p&gt;So this time I decided to try a new ride. Well aligned with our agile methodologies, I allotted myself a creativity time box of 15 minutes before falling back on 3, 2 or 1. Because of the zoom quirk, I was convinced that it must be a rendering issue. Still, for the sake of creativity, I searched the stylesheets for &lt;code&gt;border&lt;/code&gt;, &lt;code&gt;underline&lt;/code&gt;, &lt;code&gt;1px&lt;/code&gt;, &lt;code&gt;white&lt;/code&gt;, &lt;code&gt;#FFF&lt;/code&gt;, &lt;code&gt;#FFFFFF&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bingo.&lt;/strong&gt; Turns out both &lt;code&gt;text-decoration: underline&lt;/code&gt; and &lt;code&gt;color: #FFF&lt;/code&gt; were cascaded to the elements under investigation. That, in combination with what seems to be known as the 'IE Whitespace Bug', caused our white-zoom-lines. I removed these styles and had committed my changes before the 15 minutes were up.&lt;/p&gt;
&lt;p&gt;This legendary success story taught me a lesson. Bugs (in software) are by definition illogical and irrational so maybe open-minded, non-routine approaches work better than the standard operating procedures. My next debugging session will definitely take place outside the box &lt;em&gt;first&lt;/em&gt; and followed by the default weaponry (15 minutes) &lt;em&gt;later&lt;/em&gt;.&lt;/p&gt;
</description><pubDate>Thu, 11 Feb 2010 01:34:50 +0100</pubDate><guid>http://www-jo.se/f.pfleger/workaround-ie-bugs</guid></item></channel></rss>