tag:blogger.com,1999:blog-66923542024-03-06T22:16:21.803-08:00Emil's Wicked Cool BlogHmm...Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comBlogger164125tag:blogger.com,1999:blog-6692354.post-48307567268394769272016-02-01T11:35:00.001-08:002016-02-01T11:35:44.066-08:00Moving to new siteI'll be continuing my site off the blogger platform, but retaining this site for historical purposes. Please follow me to my new home at <a href="https://emil.lerch.org/">https://emil.lerch.org/</a>. My first post goes into more detail about the move.Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-80441760568829043272014-06-13T13:50:00.001-07:002014-06-13T13:50:06.636-07:00Probing support for architecture-specific native DLLs in .NET<a href="https://c1.staticflickr.com/3/2068/2500121593_7ecf3c51a5_z.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="213" src="https://c1.staticflickr.com/3/2068/2500121593_7ecf3c51a5_z.jpg" width="320" /></a><br />
<h2>
Or...How I've tamed the Oracle beast</h2>
<div>
Over the last couple decades, very little has changed with regards to Oracle client software. Install hundreds of MB of code, update network/admin/tnsnames.ora, and finally you can make a database connection.</div>
<div>
<br /></div>
<div>
With a little (well, a lot) of elbow grease, I've made it possible for .NET applications to run as "AnyCPU" and work in 32 or 64 bit process space on either a 32 or 64 bit OS. It's still an 84MB download (mostly due to a large dll containing all of Oracle's error messages), but it's bin-deployable, and only 20MB more than the combination of installing each of Oracle's "Instant Lite" processor-specific installation packages. More importantly, since it's bin-deployed, you can have 32 and 64 bit processes running side by side on the same machine, something that's been problematic to do with full client installs.</div>
<div>
<br /></div>
<div>
The fruits of my labor are now on the the NativeProbing repository on GitHub: <a href="https://github.com/elerch/NativeProbing">https://github.com/elerch/NativeProbing</a>. The focus of the repository is not on Oracle per-se, but my goal was to achieve XCopy deployment for Oracle connectivity without massive installs or gnarly configuration.</div>
<div>
<br /></div>
<div>
.Net assemblies are loaded through the Fusion process, and typically follow a strict path through an AnyCPU chain, 64 bit chain or 32 bit chain. If using the <probing> element to alter flow and add platform-specific assemblies, the first time .NET hits an assembly not matching the underlying processor architecture you'll get a BadImageFormatException. This is especially nasty; running 32 bit on a 64 bit OS is not enough to see the exception, rather, you need to be 32 bit on a 32 bit OS with your 64 bit assemblies listed first in the <probing> directory list. Therefore you need to hook into the assembly resolution process itself similar to this process: <a href="http://stackoverflow.com/a/9951658/113225">http://stackoverflow.com/a/9951658/113225</a></div>
<div>
<br /></div>
<div>
However, native libraries contain a special challenge. A different Windows process kicks in when loading a native library, and in the case of Oracle, the .Net assemblies used load native assemblies. My code on GitHub therefore uses the SetDllDirectory kernel32.dll native function to add the correct platform-specific directory to the list of paths to check. The two techniques in concert work to automatically load the appropriate DLLs.</div>
<div>
<br /></div>
<div>
More details of my travels are on <a href="https://github.com/elerch/NativeProbing">GitHub</a>, but the bottom line is that I have code that can augment the probing pipeline to include the correct architecture specific DLLs. This can be used for any architecture-specific DLLs with matching version numbers. <a href="https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki">SQLLite</a> is a possible candidate for using a similar technique.</div>
<div>
<br /></div>
<div>
Of course, Oracle does <b>not</b> have matching version numbers, which is where part two of this story unfolds. To make Oracle.DataAcess.dll work, I had to resort to extreme measures. The details are on the <a href="https://github.com/elerch/NativeProbing/blob/master/AnyCPU/OracleDLLHacking.md">OracleDLLHacking.md</a> file in my repository, but the high level process was this: </div>
<div>
<br /></div>
<div>
<ol>
<li>Disassemble Oracle.DataAccess.dll with ildasm</li>
<li>Remove the public key token and change the version number in the IL</li>
<li>Reverse the branch logic where an exception is thrown if the assembly is "incompatible" with the native code</li>
<li>Reassemble the library with ilasm</li>
<li>Repeat for the other processor architecture</li>
</ol>
</div>
<div>
<br /></div>
<br />
<br />
<br />Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-83683555892603550382014-01-13T19:01:00.003-08:002014-01-13T19:01:44.665-08:00Visual Studio unit testing slow when NetBIOS over TCP/IP is enabled<a href="http://connect.microsoft.com/VisualStudio/feedback/details/768230/slow-running-in-test-runner">According to MS Connect</a>, this doesn't happen. People have reported it, however, in VS 2010, 2012, and I've experienced the problems in VS 2013. It's also listed at this StackOverflow question: <a href="http://connect.microsoft.com/VisualStudio/feedback/details/768230/slow-running-in-test-runner">http://connect.microsoft.com/VisualStudio/feedback/details/768230/slow-running-in-test-runner</a><br />
<br />
I've now added this handy PowerShell command to my "initialize a new machine" setup PowerShell script:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"># Disable NetBios over TCP/IP on all interfaces</span><br />
<span style="font-family: Courier New, Courier, monospace;"># to prevent weird Visual Studio slowdowns during unit tests</span><br />
<span style="font-family: Courier New, Courier, monospace;">Get-ChildItem hklm:system/currentcontrolset/services/netbt/parameters/interfaces | foreach{ $item = $_; Set-ItemProperty -Path ($item.ToString().Replace("HKEY_LOCAL_MACHINE", "hklm:")) -Name NetbiosOptions -Type DWord -Value 2 -ea "SilentlyContinue" }
</span>Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-86132419427624896232013-07-12T14:41:00.004-07:002013-07-12T14:41:45.780-07:00REST Basics<br />
<div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; font-family: Verdana, sans-serif; line-height: 150%; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKpJnFwTo7_w9hQs6LbzZ8oCDmMiiKosQeHFqpMAsANcI_I4eRqXMIU9qansablv1D9xKVirctYOkrRj32WvupBDyU74BO0c8GGHGHKadw79Q2DkKuidzryT0owf8LnOPTUSnWdQ/s1600/Fighting_kittens-400.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKpJnFwTo7_w9hQs6LbzZ8oCDmMiiKosQeHFqpMAsANcI_I4eRqXMIU9qansablv1D9xKVirctYOkrRj32WvupBDyU74BO0c8GGHGHKadw79Q2DkKuidzryT0owf8LnOPTUSnWdQ/s1600/Fighting_kittens-400.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Obligatory upper-right blog image</td></tr>
</tbody></table>
<div style="font-family: Verdana, sans-serif; line-height: 150%;">
I've created a video on the basic use of REST from a consuming developer's perspective. It covers the following:</div>
<div style="font-family: Verdana, sans-serif; line-height: 150%;">
<br /></div>
<div style="font-family: Verdana, sans-serif; line-height: 150%;">
Normal HTTP Methods:</div>
<br />
<ul>
<li><span style="font-family: Verdana, sans-serif;"><span style="line-height: 24px;">POST</span></span></li>
<li><span style="font-family: Verdana, sans-serif;"><span style="line-height: 24px;">GET</span></span></li>
<li>PUT</li>
<li>DELETE</li>
<li>PATCH</li>
</ul>
<br />
<div style="font-family: Verdana, sans-serif; line-height: 150%;">
I cover the use of PATCH to replace special-purpose functions in MVC, singular vs plural urls and search apis. I also demonstrate the use of the methods at a browser console (w/jQuery). Length - 19:23.<br />
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="315" src="//www.youtube.com/embed/NXUhDnkHOkA" width="560"></iframe>
</div>
</div>
<br />Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-42540263892047697862013-05-02T17:05:00.001-07:002013-05-02T17:05:05.570-07:00AngularJs HTML5 routing and IE9We seem to be pushing the limits of <a href="http://angularjs.org/">AngularJS</a>, and we've only started using it. The framework is very promising but definitely very new and a little rough in some areas.
<br />
<br />
<a href="http://gs.statcounter.com/#browser_version_partially_combined-US-monthly-201205-201304" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim-OTPqZCwIBBhZzsUIWeRZkTp8D6H8LKcDdQhXMTFYbR0xhpOR-EWZNzQmaaqjuxbUMFZ66jvg7tTghV6tQ65COpKIPoc0o5RDZpbLj1w_Pee9XkCJxrbPqkJykSqIq6PeS7Tkg/s320/StatCounter-browser_version_partially_combined-US-monthly-201205-201304.jpeg" /></a>We'd like to <a href="http://isolani.co.uk/blog/javascript/BreakingTheWebWithHashBangs">avoid hash urls</a> in our solutions. The backend can respond to our routes just fine, and our backend framework is able to serve up the correct content (not necessarily the same content) for any area of the application. Using HTML5 mode and the <a href="http://caniuse.com/#feat=history">history.pushState</a> api, we can get clean URLs and no 404 errors on refresh...awesome.
<br />
<br />
<b>Enter, IE9 (top light blue line)</b>. Our current browser standards are IE9+, Desktop/Android Chrome, FF, and IOS Safari. All browsers support history.pushState except IE9. The browser has had a recent significant drop in usage, but we can't ignore it quite yet. <br />
<br />
At first, we thought we could set $locationProvider.html5Mode(true) and it would either a) break in IE9 calling a function that didn't exist (but we could define as window.location.assign(url)), or b) do a browser-based redirect based on <a href="https://developer.mozilla.org/en-US/docs/DOM/window.location">window.location.assign</a>. Well, <a href="http://docs.angularjs.org/guide/dev_guide.services.$location">RTFM</a>: what it does is actually relatively painful. It falls back to hashbang syntax. This is similar to <a href="http://balupton.github.io/history.js/demo/">history.js</a>, and IMHO, is broken in the same way as that library. Now you have URLs you can't share between browsers without crazy (and slow) workarounds.<br />
<br />
I tried to work around the problem by providing a history.pushState implementation. This fooled Angular into thinking it was compliant, but caused some redirect loops and ultimately didn't work out. Next, I tried first intercepting routeChangeStart and <a href="https://github.com/angular/angular.js/issues/2109">calling event.preventDefault to no avail</a>, then locationChangeStart also without success (I'm informed <a href="http://stackoverflow.com/a/13963919/113225">this does work</a>, but for some reason I didn't see it, at least not in IE9).<br />
<br />
Finally, it hit me...since we're not programmatically changing locations (just using <a href="http://docs.angularjs.org/api/ng.directive:a">anchor tags</a>), we could simply determine if <a href="http://stackoverflow.com/a/10647429/113225">pushState is available</a> and perform the following functions if it is not:<br />
<br />
<ol>
<li><b>Avoid defining any routes with the route provider</b></li>
<li>Take our <a href="http://stackoverflow.com/a/10647429/113225"><script id='whateverroutewearecurrentlyon' type='text/ng-template'/></a> that is automatically generated on the backend for the current URL and manually add it to the ng-view element.</li>
<li>Remove the ng-view attribute (for completeness) and add an ng-controller attribute pointing to the controller for the current route.</li>
<li>Disable any pre-loading for pages other than the one on which we reside.</li>
</ol>
<div>
This technique can only work in a pretty specific set of circumstances, but I think a properly designed backend system should be able to meet the criteria:</div>
<div>
<ol>
<li>Any URL used by history.pushState actually generates appropriate content from the server.</li>
<li>The server at any URL provides the page layout and the application code. Providing the current page content in the script tag is nice (that's what we do) but it's not strictly required (#2 above could be done via Ajax).</li>
<li>The application code is light enough that you (and your users) can put up with full page loads in non-compliant browsers until users upgrade. I wouldn't want to try this technique on gmail. ;-)</li>
</ol>
<div>
I <a href="http://www.hanselman.com/blog/IdLikeToUseTheWebMyWayThankYouVeryMuchQuora.aspx">reject Quora on principal</a>, but at least now we have an answer to <a href="http://www.quora.com/AngularJS/Can-we-develop-an-AngularJS-application-which-supports-IE-7+-but-does-not-have-hash-or-hashbang-urls">"Can we develop an AngularJS application which supports IE 7+ but does not have hash or hashbang urls?"</a>. </div>
</div>
<br />
Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-72863020141050789392013-01-11T16:29:00.003-08:002013-01-11T16:29:41.224-08:00Enabling Quartz jobs in ASP.NET applications that will run despite restartWith IIS 7.5, you can now <a href="http://weblogs.asp.net/scottgu/archive/2009/09/15/auto-start-asp-net-applications-vs-2010-and-net-4-0-series.aspx">auto-start applications and have them continuously run</a>. However, implementing <a href="http://msdn.microsoft.com/en-us/library/system.web.hosting.iprocesshostpreloadclient.aspx">System.Web.Hosting.IProcessHostPreloadClient</a> means having a Process method with some significant restrictions. In a <a href="http://www.springframework.net/">Spring.Net</a> environment, the IOC Container's context is not yet started, and it will fail in <a href="http://stackoverflow.com/questions/13162545/handler-extensionlessurlhandler-integrated-4-0-has-a-bad-module-managedpipeli">rather spectacular ways</a> if you try to crank it up with a hack. Even if you manage to do this, Quartz does not start up, so your jobs still will fail to run.<br />
<br />
I spent some time on this problem and discovered that I do have access to <a href="http://msdn.microsoft.com/en-us/library/system.web.httpruntime.appdomainappvirtualpath.aspx">System.Web.HttpRuntime.AppDomainAppVirtualPath</a>, which allows us to automatically fire an initial request at the app automatically, if we're careful. This will crank up Application_Start and the rest of the Spring (and Quartz) machinery, allowing us to keep an app running 100% of the time. This initial request, however, will be thrown away, even if fired asynchronously, if initiated during the Preload() method. I ended up using a thread to get around this problem, allowing the requests to fire 500ms after the Preload method runs.<br />
<br />
In certain cases, we can't just use http://localhost/<i>yourvirtualpathhere</i>. You might have multiple sites listening to different host headers, or you might be running SSL and don't want to hit the application using localhost. To cover those cases, I devised a web.config appSettings scheme where additional URLs can be applied to Preload (space delimited). You can also specify an IP address or machine name, so the web.config can stay static but different URLs can be applied as you move through environments. Here is the code:<br />
<br />
<br />
<pre class="brush:csharp">public class Preloader : System.Web.Hosting.IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
var uris = System.Configuration.ConfigurationManager.AppSettings["AdditionalStartupUris"];
StartupApplication(AllUris(uris));
}
public void StartupApplication(IEnumerable<Uri> uris)
{
new System.Threading.Thread(o =>
{
System.Threading.Thread.Sleep(500);
foreach (var uri in (IEnumerable<Uri>)o) {
var client = new System.Net.WebClient();
client.DownloadStringAsync(uris.First());
}
}).Start(uris);
}
public IEnumerable<Uri> AllUris(string userConfiguration)
{
if (userConfiguration == null)
return GuessedUris();
return AllUris(userConfiguration.Split(' ')).Union(GuessedUris());
}
private IEnumerable<Uri> GuessedUris()
{
string path = System.Web.HttpRuntime.AppDomainAppVirtualPath;
if (path != null)
yield return new Uri("http://localhost" + path);
}
private IEnumerable<uri> AllUris(params string[] configurationParts)
{
return configurationParts
.Select(p => ParseConfiguration(p))
.Where(p => p.Item1)
.Select(p => ToUri(p.Item2))
.Where(u => u != null);
}
private Uri ToUri(string value)
{
try {
return new Uri(value);
}
catch (UriFormatException) {
return null;
}
}
private Tuple<bool string> ParseConfiguration(string part)
{
return new Tuple<bool, string>(IsRelevant(part), ParsePart(part));
}
private string ParsePart(string part)
{
// We expect IPv4 or MachineName followed by |
var portions = part.Split('|');
return portions.Last();
}
private bool IsRelevant(string part)
{
var portions = part.Split('|');
return
portions.Count() == 1 ||
portions[0] == System.Environment.MachineName ||
HostIpAddresses().Any(a => a == portions[0]);
}
private IEnumerable<string> HostIpAddresses()
{
var adaptors = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
return adaptors
.Where(a => a.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up)
.SelectMany(a => a.GetIPProperties().UnicastAddresses)
.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
.Select(a => a.Address.ToString());
}
}
</pre>
Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-8164336212497684102012-12-14T10:48:00.002-08:002012-12-30T15:19:37.522-08:00Installing Cyanogenmod 7.2 on Verizon Droid 2 Running 2.3.4<a href="http://wiki.cyanogenmod.org/wiki/Motorola_Droid_2:_Full_Update_Guide">They said it couldn't be done</a>. If you install 2.3.4 OTA update from Verizon, you were stuck with a version that was un-rootable. And rooting is the first step in getting a custom Android build on a phone. Specifically:<br />
<blockquote class="tr_bq">
There is currently (as of May 2012) no way to root a Droid 2 with this system version.</blockquote>
As a word of warning, the procedures for getting Cyanodenmod are as scary as the link above, and with 2.3.4, you're really in the deep end. Here's a summary of what I did. I'm not providing step-by-step directions for two reasons; first, if you can't get there from the summary, you're probably in over your head and you have a good chance of bricking your phone. Secondly, I am providing links to my source materials with more details. I'm also taking you through the method I went, which generally used tools rather than adb commands/doing it by hand. I purchased two of the tools...I think the $8 I spent was worth it, but go read the wiki if you want to do it the hard way.<br />
<h3>
Rooting</h3>
<div>
The rooting procedures on the Cyanogenmod wiki don't work, obviously. What you need to do is download this iso: <a href="http://www.mediafire.com/?mim304k214kl41h">http://www.mediafire.com/?mim304k214kl41h</a>. MD5 is 7baee9c34f6ef7ad0b4fa219ae387c68. The forum post regarding this is here: <a href="http://androidforums.com/droid-x-all-things-root/603489-how-root-2-3-4-4-5-621-magic-md5-does-not-require-milestone-sbf.html">http://androidforums.com/droid-x-all-things-root/603489-how-root-2-3-4-4-5-621-magic-md5-does-not-require-milestone-sbf.html</a>.</div>
<div>
<br /></div>
<div>
The ISO can be burned to a bootable CD or USB (using <a href="http://unetbootin.sourceforge.net/unetbootin-windows-latest.exe">Unetbutin</a>). I went the USB route. Once booting off the USB, the scripts on the ISO walk you through what needs to be done. This was by far the easiest part of the install.</div>
<h3>
Custom Recovery ROM and Bootloader</h3>
<div>
Not having gone down these paths before, I didn't have a conceptual understanding of how Android boot works. That turns out to be pretty important at this point, and it tripped me up for a bit.</div>
<div>
<ol>
<li>Bootloader is run, presumably by the hardware</li>
<li>Bootloader looks around, checks out everything, and loads the ROM image. Depending on the environment it can run the recovery ROM or the normal boot ROM (your phone).</li>
</ol>
<div>
So, now that the phone is rooted, we need a custom bootloader because the Android one will verify that it's the Verizon image, and we don't want that. We need a custom recovery ROM as well...one that will let us flash new Android versions. So, the next step is to install the Droid 2 Recovery Bootstrap by ClockworkMod: <a href="http://market.android.com/details?id=com.koushikdutta.droid2.bootstrap">http://market.android.com/details?id=com.koushikdutta.droid2.bootstrap</a>. Also install the ROM Manager: <a href="https://play.google.com/store/apps/details?id=com.koushikdutta.rommanager.license&feature=more_from_developer#?t=W251bGwsMSwxLDEwMiwiY29tLmtvdXNoaWtkdXR0YS5yb21tYW5hZ2VyLmxpY2Vuc2UiXQ..">https://play.google.com/store/apps/details?id=com.koushikdutta.rommanager.license&feature=more_from_developer#?t=W251bGwsMSwxLDEwMiwiY29tLmtvdXNoaWtkdXR0YS5yb21tYW5hZ2VyLmxpY2Vuc2UiXQ..</a></div>
</div>
<div>
<br /></div>
<div>
Use the ROM Manager to Flash ClockworkMod Recovery. Once that's done, install the Recovery Bootstrap (remember, we need the Bootstrap to let us get into our shiny new Recovery). I missed this part and I kept going into the Android recovery...it was very confusing.</div>
<h3>
Prepping and Hacking the Cyanogen install</h3>
<div>
Download:</div>
<div>
<ol>
<li>Cyanogen latest version: <a href="http://wiki.cyanogenmod.org/wiki/Devices_Overview#Motorola_Droid_2">http://wiki.cyanogenmod.org/wiki/Devices_Overview#Motorola_Droid_2</a>. Right now, this is 7.2.0, available at: <a href="http://get.cm/get/jenkins/2824/cm-7.2.0-droid2.zip">http://get.cm/get/jenkins/2824/cm-7.2.0-droid2.zip</a></li>
<li>Google apps (gets you the market): <a href="http://goo-inside.me/gapps/gapps-gb-20110828-signed.zip">http://goo-inside.me/gapps/gapps-gb-20110828-signed.zip</a>. That is the mirror link as the primary didn't work for me. The cyanogenmod page on this is at: <a href="http://wiki.cyanogenmod.org/wiki/Latest_Version#Google_Apps">http://wiki.cyanogenmod.org/wiki/Latest_Version#Google_Apps</a></li>
</ol>
<div>
Copy the Google apps zip file to the SD card. I don't know if this needs to be in the root directory, but Cyanogen instructions mention putting it into root. It's certainly easier, anyway.</div>
</div>
<div>
<br /></div>
<div>
<b>Don't copy the Cyanogen zip file to the SD card yet. </b>Our last step in this path is that there is a safety check in the install to verify the kernel version so it doesn't accidentally brick your phone. With 2.3.4 we're safe, but Cyanogen doesn't know this. So, you need to unzip the Cyanogen zip file above, and alter the /system/etc/check_kernel script (with a decent text editor - not notepad). Wipe out everything except the first line. Then the second line should be simply "exit 0". More details are here: <a href="http://forum.cyanogenmod.org/topic/50469-installing-cm-from-234/#entry335479">http://forum.cyanogenmod.org/topic/50469-installing-cm-from-234/#entry335479</a></div>
<div>
<br /></div>
<div>
Zip the file with the changed script and put it on your SD card from the phone. </div>
<h3>
Installing Cyanogen</h3>
<div>
Reboot the phone into ClockworkMod recovery by first powering down. Then hold power and the X key on the keyboard until it comes up. You'll see ClockworkMod come up (maybe). I remember having an issue where nothing seems to happen. If you have that problem, hit both volume keys at the same time (if that fails, just play around with volume a bit). You'll then see shiny new text from ClockworkMod recovery, and maybe even an error message. </div>
<div>
<br /></div>
<div>
At this point, it took me a while to figure out, and the ROM manager was useless for me. The directions and forums don't know a whole lot about that error message. You're <b>supposed</b> to be able to use up/down volume to arrow around the options, and power selects the option you want. However, power just made the phone go blank for me. I <b>think</b> what's happening is that the droid 2 does not have /dev/tty0 and there is a bug in the recovery ROM where the power button selects /dev/tty0 as the device when pressed. However, there is another way to navigate...</div>
<div>
<br /></div>
<div>
What I <b>finally figured out</b> is that navigation can operate with the keyboard. Slide it open, and left = up, right = down (which makes sense since you have the phone in portrait mode. Up = right, Enter = enter, and Del = back. This knows where the screen is, and I'm sure it's much more pleasant than trying to navigate around selecting files with volume keys/power.</div>
<div>
<br /></div>
<div>
With that working, you can perform the following steps:</div>
<div>
<ol>
<li>Back up your existing ROM</li>
<li>Select and install the Cyanogen ROM</li>
<li>Select and install the Google Apps ROM (I think this just unpacks apks and puts them in a special directory, but I'm not sure). I thought it was way weird I was installing two ROMs.</li>
<li>Lastly, wipe all cache/data. I don't remember if I performed factory reset - I think I did <b>not</b>. Apparently the phone will get into a "boot loop" unless this step is performed, but if you forget for some reason, you can get out of that problem: <a href="http://forum.xda-developers.com/showthread.php?t=1832130">http://forum.xda-developers.com/showthread.php?t=1832130</a></li>
</ol>
<div>
Congrats, Cyanogen is installed! It's like a brand new phone, so you'll have to sign in, install apps, yada yada.</div>
</div>
<h3>
Other thoughts</h3>
<div>
I noticed the Alt Lock button does not work after I installed. Apparently this is a special Motorola hardware key and cannot be used by Cyanogen. However, pressing Alt twice will do the same thing...I'm sure that's a default Android behavior I had no idea about. I am also missing the Motorola calendar widget terribly, but I'm sure I'll find a suitable replacement. Cyanogen is so much better/faster. They really had me at "Add Access Point" in the wireless settings. ;-)<br />
<br />
<h4>
Update</h4>
</div>
<div>
I noticed that my WiFi does not seem to connect. It connects but the advanced settings says IP address unavailable. I tried a custom kernel but to no avail. It appears to be a dhcp problem only, and I think it is a problem with cm 7.2. I have worked around the problem by using a static IP address and DNS server, but the static DNS settings in the settings don't seem to work. Instead I installed <a href="http://www.google.com/url?sa=t&rct=j&q=set%20dns%20android&source=web&cd=1&cad=rja&ved=0CDIQFjAA&url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Duk.co.mytechie.setDNS%26hl%3Den&ei=o8rgULfkEIyyqAHRvoDgAg&usg=AFQjCNH1ntGZvyswfVMGi7p1o2f_NMzBYg&sig2=v3R48xbCfBSQRE7lheDDuw&bvm=bv.1355534169,d.aWM">Set DNS</a> and that works properly. For WiFi hotspot support I installed <a href="http://www.google.com/url?sa=t&rct=j&q=barnacle%20wifi%20tether&source=web&cd=1&cad=rja&ved=0CDIQFjAA&url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dnet.szym.barnacle%26hl%3Den&ei=W8vgULidF8uLrQG2moDgDw&usg=AFQjCNEp_MFCsxl_uO7sdCVHLVCrsQXnxA&sig2=OUj3wib0TEHOEH-BHfaSgw&bvm=bv.1355534169,d.aWM">Barnacle WiFi tether</a>, but I haven't had a chance to play with it too much.</div>
Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-46255973581958055502012-05-24T07:39:00.000-07:002012-05-24T07:39:18.449-07:00The constraint for route parameter 'httpMethod' on the route with URL '{controller}/{id}' must have a string value in order to use an HttpMethodConstraint.Wow...what did that mean? Here I am, just using @Url.Action (and BeginForm and any other method that walks the route table backwards). My application is RESTful, so most routes have an HttpMethodConstraint so they only match if the method is correct.<br />
<br />
I could not wrap my head around this message and ended up using <a href="http://www.telerik.com/products/decompiler.aspx">JustDecompile</a> to pull open System.Web.Routing and had a look at the <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.httpmethodconstraint">HttpMethodConstraint</a> <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.httpmethodconstraint.match">Match</a> method. You'll note that the <a href="http://msdn.microsoft.com/en-us/library/system.web.routing.routedirection">routeDirection</a> parameter tells the object whether to match based on an incoming request (the normal case) or for Url Generation (used for Url.Action, BeginForm and the like).<br />
<br />
Pulling open the source, I found this:<br />
<br />
<br />
<pre class="brush:csharp"> switch (routeDirection1)
{
case RouteDirection.IncomingRequest:
{
ICollection<string> allowedMethods = this.AllowedMethods;
if (func == null)
{
func = (string method) => string.Equals(method, httpContext.Request.HttpMethod, StringComparison.OrdinalIgnoreCase);
}
return allowedMethods.Any<string>(func);
}
case RouteDirection.UrlGeneration:
{
if (values.TryGetValue(parameterName, out obj))
{
string str = obj as string;
if (str != null)
{
return this.AllowedMethods.Any<string>((string method) => string.Equals(method, str, StringComparison.OrdinalIgnoreCase));
}
else
{
object[] url = new object[2];
url[0] = parameterName;
url[1] = route.Url;
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, RoutingResources.HttpMethodConstraint_ParameterValueMustBeString, url));
}
}
else
{
return true;
}
}
}
</pre>
<br />
The RouteDirection.UrlGeneration case block represents what happens when the HttpMethodConstraint is asked to match for a generated Url. The InvalidOperationException represents the error message we see on the YSOD. <br />
<br />
Even this took me a bit to work through, but the bottom line is that it's finding the parameter name from the route and looking for the value of that parameter name from the input provided to it. Given the following route:
<br />
<pre class="brush:csharp"> routes.MapRoute("UpdateByPut",
"{controller}/{id}",
new { action = "Update" },
new { httpMethod = new HttpMethodConstraint("PUT") }
);
</pre>
<br />
HttpMethodConstraint will find httpMethod (this is the value of parameterName in the code above), and look for a route value of httpMethod, expecting it to be a string. If it doesn't, it will throw the exception. So, using the route above with the following code:
<br />
<br />
<pre class="brush:csharp"> @Url.Action("Show", "MyEntity", new { id = Model.Id })
</pre>
<br />
Won't work. Instead, you need this:
<br />
<br />
<pre class="brush:csharp"> @Url.Action("Show", "MyEntity", new { id = Model.Id, httpMethod = "GET" })
</pre>
<br />
Also note that the property name httpMethod in the @Url.Action line above comes from the same property name I used in routes.MapRoute within Global.asax.cs. This is one of the few times that MVC cares about the property name used on a constraint.
<br />
<br />
Once you understand what the error message is trying to tell you it's all pretty clear. You just need to be a rocket scientist the first time through.Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-23667716148105469222011-06-14T09:36:00.000-07:002011-06-14T09:36:25.535-07:00EduSpring Part 6: Crazy Error Messages and What to do about them<div>Because Spring will create most of your objects up front, a simple error in the configuration Xml can have disastrous effects. This, in my opinion, is the #1 reason people fear Spring.</div><div><br />
</div><div>Here are a few error messages I've seen, and their corresponding solutions:</div><ul><li><b>The virtual path '/currentcontext.dummy' maps to another application, which is not allowed</b>: This error message usually means you've deployed the application to a server, but forgotten to make the virtual directory an application in IIS. Spring performs a server.Transfer() call to "~/currentcontext.dummy" to get all the dependency wiring done correctly before another server.Transfer() brings the request back to the right place.</li>
<li><b>no application context for virtual path</b>: This error message tells you that there's no spring configuration setup at all.</li>
<li><b>Resource handler for the 'web' protocol is not defined</b>: This message tells you that the httpModule is not active. Add the spring.net HttpModule into the appropriate section of web.config (system.web for IIS6, system.webserver for IIS7).</li>
<li><b>Could not load type from assembly</b>: This may or may not have anything to do with Spring, so take a look a the stack trace. If you see Spring.Core (specifically Spring.Core.TypeResolution.TypeResolver.Resolve) in the trace, you can be fairly certain you misspelled a type name in the configuration.</li>
<li><b>node cannot be resolved for the specified context</b>: Spring tried to assign an object or value to a property, but the property doesn't exist on the object. It's likely you misspelled the property name, or maybe you refactored, removed the property, but forgot to update the spring configuration.</li>
</ul><div>Things to check if your dependency is showing up as null:</div><div><ul><li>Is your configuration binding the right type? For example, if your property is a string, and you're assigning a stringbuilder to it, Spring will just ignore the assignment.</li>
<li>You're missing the object definition in the spring configuration.</li>
<li>You're missing the property definition in the spring configuration.</li>
<li>Did you commit the cardinal sin of DI? Do not use new MyType()!</li>
</ul><div>Take a look through <a href="https://github.com/elerch/eduSpring/blob/master/4%20-%20Debugging%20Web%20Applications/Web.config">web.config</a> and <a href="https://github.com/elerch/eduSpring/blob/master/4%20-%20Debugging%20Web%20Applications/spring.config">spring.config</a> of the <a href="https://github.com/elerch/eduSpring/tree/master/4%20-%20Debugging%20Web%20Applications">Debugging Web Applications</a> project in the <a href="https://github.com/elerch/eduSpring">eduSpring </a>project on GitHub for troubleshooting examples. There are several errors scattered throughout the two configuration files, and the errors are fully documented.</div><div><br />
</div><div>Also note that the best way to work through the troubleshooting procedure is to correct each issue in turn, shut down the integrated web server and F5 to view the next error.</div><div><br />
</div><div>Setting up Spring.Net's verbose logging is also shown in the web.config. You might notice that the actual project references do not include anything except standard ASP.NET DLLs. Spring, Common Logging, and Log4Net must exist in the bin directory at run time, but no project references are actually required. With VS 2010 SP1 or higher, we can put these semi-dependent DLLs in a special folder called _bin_deployableAssemblies and the build procedure will copy them in place.</div><div><br />
</div><div><br />
</div><div><br />
</div><div><br />
</div></div>Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-68358757233551451292011-06-14T07:49:00.000-07:002011-06-14T07:49:55.704-07:00EduSpring Part 5: Spring.Net in an ASP.NET environment (including MVC)This post is part of a <a href="http://emilsblog.lerch.org/search/label/EduSpring">series </a>on Spring.NET. I recommend starting at the beginning if you haven't already. Also, I am walking through code in the <a href="https://github.com/elerch/eduSpring">accompanying GitHub project</a>.<br />
<br />
By now, you should have the basics of DI, IoC, and the benefits and drawbacks of the approach. Now, I'll introduce you to the architecture of Spring.NET in an ASP.NET environment. I'm sure a lot of other IoC frameworks operate in a similar manner. If not, you can add code to make them work that way. ;-)<br />
<br />
If you look at the <a href="https://github.com/elerch/eduSpring/tree/master/2%20-%20IocWithoutSpring">IocWithoutSpring </a>project, you'll see this Main function:<br />
<br />
<pre class="brush:csharp">static void Main(string[] args)
{
//These two lines are handled by the Spring.NET HttpModule
var container = new IoCContainer();
container.Initialize();
// These two lines are also handled by the HttpModule by a special
// syntax in the spring configuration
var service = new DoSomeWork();
service.Worker = container.GetObject<idosomething>("myObject");
// This is what the ASP.NET Framework would do
Console.WriteLine("The output is: " + service.DoTheWork());
}
</idosomething></pre><br />
Most of the time, creation of the IoC container itself is a single dependency that's particularly hard to get rid of without writing some reflection-style glue code. Ideally, we want our objects to be completely ignorant of this container, though. In ASP.NET, the web.config provides us with the concept of an HttpModule, which will look at every request coming from into the web server and have an opportunity to do something with it. Taking advantage of this feature, the Spring.Net team wrote an ASP.NET HttpModule that will do just that, so the first two lines of main (instantiation and initialization of the container) are handled by the ASP.NET framework. Awesome!<br />
<br />
Now our Spring.Net dictionary is populated, assuming we have a valid configuration. I'll address more about the pain points of Spring configuration later, but this very early creation of lots of objects is one of the main frustrations of people who want to use Spring.Net. The next question is, what about setting up dependencies in ASPX pages?<br />
<br />
Technically speaking, the ASP.NET framework parses an ASPX file (or MVC view) and code-generates a class. On each request, it creates an instance of this class and allows it to process the request, before destroying the object. Very stateless, but this creation and destruction of classes rubs against IoC's Dictionary<string,object> heart.<br />
<br />
If you <a href="http://blogs.msdn.com/b/oldnewthing/archive/2008/05/28/8555658.aspx">read this contract from the other side</a> (a.k.a. how would I solve this problem if I were writing Spring.Net), you can imagine yourself writing a <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.pagehandlerfactory.aspx">PageHandlerFactory</a> that can deliver the aspx page class with dependencies already injected. There are two problems you have to solve, however:<br />
<br />
<ol><li>What name do you use to look up the object?</li>
<li>How do you deal with request-specific data?</li>
</ol><div>The answer to #1 is relatively obvious if you look at the problem from the perspective of Spring. The object doesn't really have a name, so we leave that blank, and the <a href="http://msdn.microsoft.com/en-us/library/ms178116.aspx">virtual path</a> (~/page.aspx) is used as the type of the object since someone configuring the object will not know the type ASP.NET generates. The actual type name needs to be figured out by Spring. The answer to the second question runs a bit contrary to what I've been discussing so far.</div><div><br />
</div><div>In the examples so far, the initialization method of the IoC container has created all the objects in configuration and put them in its internal dictionary. However, there's no reason that the objects need to be created right away, nor do they have to be held in the dictionary. In the case of this PageHandlerFactory, objects are created and configured at the time of the request, not at initialization. However, dependencies follow the normal rules. </div>Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-31085980037620628482011-06-13T22:23:00.001-07:002011-06-13T22:24:00.439-07:00EduSpring Part 4: What is so terribly broken with Dependency Injection?Move all the CS BS to the side. This stuff doesn't work in the real world. And it's because of things that could have (and probably should have) been fixed by uber-geeks 10+ years ago with fancy CompSci PhDs. And I'm talking about .Net specifically here, although I can throw the same stones at Java. Most (but not all) other languages have the same problems I'll get on my soapbox about here.<br />
<br />
To do DI correctly, you have one of two options:<br />
<br />
<ol><li>Your class has dependencies on properties/internal fields that implement Interfaces</li>
<li>Your class has dependencies on properties/internal fields that implement base classes</li>
</ol><div>In both cases, the contracts are relatively weak. If you depend on a method that requires an object and returns an object, there are lots of things that can go wrong. And you have no way of knowing whether it will go wrong unless an until you run it - compile time checks don't help. Here's a short list of Murphy's law for a single method that takes an object parameter and returns an object:</div><div><ol><li>Do you assume anything about the return value? It might return what you expect, or might return null. Or, it could throw an exception. Generally, experience with DI will teach you good defensive coding, but it does take work...</li>
<li>Can the method handle null input values? If it errors, is it going to return null or throw an exception? If it throws, what kind of exception will it generate?</li>
<li>Is the method you're calling going to muck with the object you pass in? If it does alter properties, is that a problem? What if you're not in control of the object, and the property this dependency decides it's OK to muck with throws an exception during the set operation?</li>
</ol><div>Without some type of <a href="http://en.wikipedia.org/wiki/Design_by_contract">design by contract</a> construct built into your language of choice, these questions become just the tip of the iceberg. Glancing through the Common Language Specification for .NET, it appears that there is no built-in construct available in the platform. C# provides a MS Research Code Contract construct in .NET 4, but they feel hacky without being part of the language, and even more hacky when implemented with IoC. </div></div><div><br />
</div><div>Feel free to run through the Main method for FallaciesOfInterfaces for concrete examples of how Murphy can strike. This project will compile, but will fail at almost every step. Read through the comments and fix the code one-by-one to get a sense of how, even with an IoC container and good DI practices, everything must be tested.</div>Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-28704153987133725752011-06-13T22:05:00.000-07:002011-06-13T22:05:05.466-07:00EduSpring Part 3: What do we need an IoC for?This post is part of a <a href="http://emilsblog.lerch.org/search/label/EduSpring">series </a>on Spring.NET. I recommend starting at the beginning if you haven't already. Also, I am walking through code in the <a href="https://github.com/elerch/eduSpring">accompanying GitHub project</a>.<br />
<br />
Last time, I walked through why we might want to use dependency integration. Outside the authentication example, here are a few other examples:<br />
<br />
<ul><li>Authentication</li>
<li>Authorization</li>
<li>SMTP settings</li>
<li>Payment gateways</li>
<li>Business rules (rule engine style)</li>
<li>Branding</li>
</ul>This time, I'd like to explore how an IoC container actually does its job. By understanding how the IoC does its job, we can understand the value that it adds to our solutions. In the project "<a href="https://github.com/elerch/eduSpring/tree/master/2%20-%20IocWithoutSpring">2 - IocWithoutSpring</a>" on GitHub, you'll see a quick, hand-coded IoC container. It's amazingly brilliant (insert sarcasm here) and also relatively close to what a real IoC container does (really). Here is the IocContainer class in all it's glory:<br />
<br />
<pre class="brush:csharp">class IoCContainer
{
private readonly IDictionary<string, object=""> _allObjects = new Dictionary<string, object="">();
public T GetObject<t>(string objectName)
{
return (T)_allObjects[objectName];
}
public void Initialize()
{
// Wouldn't it be nice if we could configure this through
// app.config or web.config? Spring does that!
_allObjects.Add("myObject", new ClassA());
}
}
</t></string,></string,></pre><br />
Most IoC containers work in a similar manner. There's some sort of initialization function, and there's some sort of GetObject method. Internally, all it does is "new up" all the classes you've defined and shoves them in a global dictionary object. The rest, as they say, is window dressing. As you see in the comment, once you've built an IoC container, you can think of all kinds of cool things to do. It would be really nice if you could configure from web.config/app.config, or maybe a separate XML file, or maybe the database, or maybe all of them? What if you added the ability to set properties on the objects, not just create them? How about the ability to create an object based on the state of another object (Spring calls this a factory method). How about defining objects in one place, and values for properties in another? IoC containers have all this stuff, and it's built for you...there's no reason to reinvent the wheel.<br />
<br />
But at the end of the day, remember: An IoC container, at its heart, is a Dictionary<string, object>. And that's all, folks. Another key thing to remember, especially in a stateless ASP.NET scenario, is that those objects exist during the lifetime of the application. This is a performance gain (no GC stepping in, no creation of multiple objects), and a bug factory if you assume your objects are going to be created, used once, and destroyed.<br />
<br />
More goodies are in the <a href="https://github.com/elerch/eduSpring/blob/master/2%20-%20IocWithoutSpring/IoCWithoutSpring.cs">main file</a> if you read the comments, but I'll explore them more in depth in later posts.Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-30908418573202150782011-06-13T17:25:00.000-07:002011-06-13T17:26:01.128-07:00EduSpring Part 2: Simplifying dependencies<a href="http://emilsblog.lerch.org/2011/06/eduspring-part-1-introduction.html">Last time</a>, I introduced you to Spring, IoC, and Dependency Injection. If you haven't read that post, please do. This time, I'll start walking through some of the code in the <a href="https://github.com/elerch/eduSpring">accompanying GitHub project</a>. The code is organized by project in order of these posts. Some conventions (specifically 1 class/file) have been ignored specifically to let the reader go through in a linear manner. All projects are setup as console applications.<br />
<br />
This time, I'll tackle the first project, "0 - Advantages of DI". This is one of the few projects I that will have more than one file to peruse. The first file is a baseline...how we would solve a particular problem in a "traditional" procedural manner. I've simulated a program that calls a service (MyClass) that needs to authenticate the user prior to performing some work on behalf of the caller. If authentication fails, it will throw an exception. Here is the class:<br />
<br />
<pre class="brush:csharp">/// <summary>
/// Simulates a typical class
/// </summary>
public class MyClass
{
/// <summary>
/// Authentication provider. We can't change this out for the production version
/// without changing source code and recompiling
/// </summary>
private readonly MyAuthenticationProvider authenticationProvider = new MyAuthenticationProvider();
// Comment the line above, uncomment and recompile for production.
//
// By recompiling, you won't know if you're testing the same
// code that exists in production (did you just change this line, or something else too?) Versions might
// be different, etc.
//private readonly MyProductionAuthenticationProvider authenticationProvider = new MyProductionAuthenticationProvider();
public void DoWork(string user, SecureString password)
{
if(!authenticationProvider.Authenticate(user,password).Identity.IsAuthenticated)
throw new SecurityException("Not authorized to perform this action");
Thread.Sleep(3000);// Simulate some work
}
}
</pre><br />
You'll notice that when we move this class into production, we have to remember to swap out our authentication provider. In reality, the new authentication provider might now call a central authentication single-sign-on service through a web/rest service, might redirect the user in order to change password, or any number of crazy things. For these purposes, I just check that the password is "bar". <br />
<br />
The main point here is that we have to remember to swap, and we'll have to recompile the application when we do that. If we forget, anyone can log in with anything and we'll happily give up the goods. Since everything has been "tested", it's likely we won't thoroughly check the service (indeed, if we're on a production system, and this service's purpose was to delete a bunch of accounts, we probably wouldn't test it). After deployment have two versions of the binary - one for production, and one outside production. Who is to say there aren't any other changes in this code. Now we have a maintenance problem too - we can't assume the code is identical, and every time we deploy we run the risk of missing this step. But, it's simpler when we're coding it, isn't it?<br />
<br />
If we could just pass this dependency into MyClass, we'll be in much better shape. At the minimum we can centralize the changes, and in the best case we can move these changes out into a configuration file or some other mechanism that doesn't require code changes for this simple switch. Enter the next file in this project - "1 - WithDependencyInjection.cs". Here are the contents:<br />
<br />
<pre class="brush:csharp">/// <summary>
/// Simulates a typical class
/// </summary>
public class MyClassWithDependencyInjection
{
/// <summary>
/// Authentication provider. Because we use an interface, we no longer
/// need to change this code after it's been tested
/// </summary>
private readonly IAuthenticate _authenticationProvider;
/// <summary>
/// Constructor to establish this class' dependencies. Since the
/// class is not "complete" (can't operate) without an authentication
/// provider, we require an object up front.
/// </summary>
/// <param name="authProvider" />public MyClassWithDependencyInjection(IAuthenticate authProvider)
{
if (authProvider == null)
throw new ArgumentNullException("authProvider");
_authenticationProvider = authProvider;
}
public void DoWork(string user, SecureString password)
{
if (!_authenticationProvider.Authenticate(user, password).Identity.IsAuthenticated)
throw new SecurityException("Not authorized to perform this action");
Thread.Sleep(3000);// Simulate some work
}
}
/// <summary>
/// New Interface introduced. Our two classes don't have a real-world inheritance relationship,
/// but the authentication process is identical, so we build a contract
/// </summary>
public interface IAuthenticate
{
IPrincipal Authenticate(string user, SecureString password);
}
class TestingAuthenticationProvider : IAuthenticate
{
public IPrincipal Authenticate(string user, SecureString password)
{
// Implementation for development
return new GenericPrincipal(new GenericIdentity(user), new string[] { });
}
}
class ProductionAuthenticationProvider : IAuthenticate
{
public IPrincipal Authenticate(string user, SecureString password)
{
if (user == "foo" && password.StringEquals("bar"))
return new GenericPrincipal(new GenericIdentity(user), new string[] { });
return new GenericPrincipal(new GenericIdentity(""), new string[] { }); ;
}
}
</pre><br />
Here, we've done the following things:<br />
<br />
<ol><li>Introduced an interface for authentication and marked both providers as implementing the interface. We could just as well have introduced a base class (concrete or abstract), but we have no default implementation, so an interface is probably best.</li>
<li>Introduced a parameterized constructor for the main class. Now this class lets the world know that it can't do it's job without a way to authenticate. And it doesn't care how the authentication gets done, just that it <b>can</b> authenticate.</li>
</ol><div>Back in the main program, we can now (sort of) demonstrate what we've done. Obviously without changing the code we can't demonstrate changing the provider for MyClass, but we can demonstrate the DI approach to the problem:</div><div><br />
</div><div><br />
</div><pre class="brush:csharp">static void Main(string[] args)
{
// Without DI
new MyClass().DoWork("foo", new SecureString().Append("bar"));
// With DI
var testSystemProvider = new TestingAuthenticationProvider();
var productionSystemProvider = new ProductionAuthenticationProvider();
// The choice of test/production is now made here, outside of the class.
// The class shouldn't "care" who does the authentication work, it's job is to do other work
// The new statement in the next line would be done through an IoC container (e.g. Spring) in a
// real environment.
new MyClassWithDependencyInjection(testSystemProvider).DoWork("foo", new SecureString().Append("bar"));
// Switch the constructor (in Spring.NET, done through a config file change) and now we're running against
// "production". No recompile necessary
new MyClassWithDependencyInjection(productionSystemProvider).DoWork("foo", new SecureString().Append("bar"));
// We can also do this without a container. Here, we'll get type information from the command line.
// Change the provider type via project properties to see how this works.
// The next line is basically what an IoC container would do
var myAuthProvider = (IAuthenticate)Activator.CreateInstance(Type.GetType(args[0]));
new MyClassWithDependencyInjection(myAuthProvider).DoWork("foo", new SecureString().Append("bar"));
}
</pre><br />
With dependency injection techniques, the caller can decide the authentication mechanism. Given a proper IoC container, this configuration will be centralized, but for now, we can do it manually by creating two objects, one of type TestingAuthenticationProvider and one of type ProductionAuthenticationProvider. These are passed into the constructor for the DI class, and voilà, we can change the way authentication works. In the last two lines, I show how we can even pass in the type name via the command line. Now, for the first time, we have the ability to change the way we authenticate without changing code.<br />
<br />
...and that, folks, is all an IoC container is about.Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-41609476078291499732011-06-13T16:46:00.000-07:002011-06-13T16:46:30.088-07:00EduSpring Part 1: IntroductionI get quite a few questions about <a href="http://springframework.net/">Spring.Net</a>, so I thought I'd put together a VS Solution, presentation, and set of blog posts to provide some background and details about what it is, why/when to consider using it, and how to configure and debug the framework.<br />
<br />
A lot of this material will <b>not</b> be specific to Spring.Net, but rather <a href="http://en.wikipedia.org/wiki/Dependency_injection">Dependency Injection</a> generally. To understand Spring.Net, you must be familiar with <a href="http://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a> and Dependency Injection. You can read about them on Wikipedia, but here's a short summary:<br />
<br />
Inversion of Control: Flow of control of a system is inverted in comparison to procedural programming<br />
Dependency Injection: A specific technique to achieve inversion of control with respect to dependencies<br />
<br />
What this means in layman's terms is that instead of a program:<br />
<br />
<ol><li>Starts up</li>
<li>Creating new services for whatever needs to be done</li>
<li>Using the services/doing the work</li>
<li>Disposing of the services and returning the results</li>
</ol><div>The program now does only what it's responsible. Namely:</div><div><ol><li>Starts up</li>
<li>Uses services that have been configured for its use/does the work</li>
<li>Returns the results</li>
</ol><div>This makes the program itself easier to test, simpler to code/maintain, and separates infrastructural responsibilities (determine location of services and creating them) from the business logic the program was created to deliver.</div></div><div><br />
</div><div>The devil in these particular details are in #2. How does one create and configure services for a program? We can code this by hand, but it's a lot of boring glue code, and doing it right is incredibly difficult. Enter the <a href="http://www.martinfowler.com/articles/injection.html">IoC container</a> - a piece of pre-built code that will do this work for us. Depending on the application, we don't even need to use the container explicitly. In a system like <a href="http://www.asp.net/">ASP.NET</a>, we can use <a href="http://msdn.microsoft.com/en-us/library/system.web.ihttpmodule.aspx">HttpModules </a>to intercept requests and wire dependencies automatically.</div><div><br />
</div><div>One significant problem with this approach are the complexity of configuration. Using Spring.net, I can have a dependency-injected factory method to deliver an instance of an object used to populate a property that will be injected into another object that will have additional advice applied through Spring.Net's AOP module. When that fails, I might get a "node cannot be resolved for the specified context" without any additional information pointing me to the cause of the problem. With flexibility comes complexity.</div><div><br />
</div><div>Another issue is a fundamental problem with .NET (C# and VB and I believe all .NET classes adhering to the <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf">CLI</a>). Interfaces are incomplete contracts. </div><div><br />
</div><div>Finally, with regards to Spring.Net in particular, the framework can be slow to move (IIS7 Integrated mode, introduced with Windows Server 2008 on Feb 27, 2008, gained support in Spring.Net 1.3.1 released December 10, 2010). Also, no <a href="http://forum.springframework.net/showthread.php?t=6875">Mono support</a> exists as of this writing.</div><div><br />
</div><div>Next up - some walkthrough code.</div>Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-4128532435963694682011-06-05T23:01:00.000-07:002011-06-05T23:01:23.383-07:00Total application design: circa 2011Working with a few recent projects I'm getting pretty close to a nice boilerplate for a "standard" web application built with the latest technologies. Subject to client restraints, here's the stack:<br />
<ul><li>UI and middle tier: <a href="http://www.asp.net/mvc">ASP.NET MVC3</a> (using VS2010 SP1). Note that this requires .NET 4, which has some nice features (I love Tuples) but I don't think is completely necessary otherwise. SP1 is important, which I'll mention later. For smaller-ish applications I've been moving away from multiple projects in a solution, mainly because I haven't been seeing a ton of real business logic besides authorization, and I've been able to productize many ancillary functions into separate DLLs. Razor view engine is used, and templates are updated to mirror <a href="http://html5boilerplate.com/">Html5Boilerplate.com</a>'s templates. jQuery is applied unobtrusively.</li>
<li>Data access: <a href="http://fluentnhibernate.org/">Fluent NHibernate</a>. This is integrated in such a way that depending on your needs, you don't need to add a direct reference to it, though. References are needed for access to NHibernate advanced queries and the Linq provider.</li>
<li>URL Rewriting: <a href="http://urlrewriter.net/">UrlRewriter.Net</a>. This is used for css/js versioning. A <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.aspx">URLHelper</a> extension method appends the current version number (derived at build time from source control) for the application to the script or CSS filename, and the rewriter strips it back off. We probably could use MVC3 routes here, but it seems overkill for something that could be handled by simple Url rewriting.</li>
<li>Dependency Injection: <a href="http://www.springframework.net/">Spring.net</a>. Any DI/IOC container would work here. Again, the integration with spring is very lightweight and easily replaceable. One strike against Spring.Net is the lack of support for Mono, but this hasn't been an issue in the environments with which I've been working.</li>
<li>Other tools: <a href="http://www.dotlesscss.org/">Dotless</a> is used in a development-time capacity to generate CSS, with <a href="http://chirpy.codeplex.com/">Chirpy</a> (<a href="https://hg01.codeplex.com/forks/etlerch/directorybasedsettingswithinchirp">customized</a>) to keep the development experience smooth. A handful of other custom DLLs and build tools keep the project structure relatively vanilla. <a href="http://hudson-ci.org/">Hudson</a> is used for continuous integration.</li>
</ul><div>I'm putting together a NuGet package with this build. When this is complete, I'll post an update.</div><div><br />
</div><div>Other technologies/tools on the radar are <a href="http://msdn.microsoft.com/en-us/library/aa697427(v=vs.80).aspx">Entity Framework</a> (NHibernate replacement) and <a href="http://www.castleproject.org/">Castle Windsor</a> (IoC container that supports Mono). <a href="http://www.dotnetopenauth.net/">DotNetOpenAuth</a> is under consideration as a standard way to pull in authentication and authorization functions.</div><div><br />
</div><div><br />
</div>Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-64447192856018269542011-03-29T08:48:00.001-07:002011-03-29T08:49:21.181-07:00Supporting Multiple Databases in Applications<p>In general, having a persistence-ignorant application provides a lot of flexibility.  Allowing us to easily port between various RDBMS’s, NoSQL data stores, text files, the cloud, or simply storing our data on papyrus managed and maintain by a group of beer-making monks provides us with tangible opportunities to cross-sell our (non-hosted) application to multiple clients.</p> <p>As any write once, run anywhere scheme, support for multiple databases can be notoriously difficult.  Consider the following SQL Server T-SQL code:</p> <p><img src="http://content.screencast.com/users/EmilT/folders/Jing/media/26d80b2f-5e0f-4bdf-9593-45d0d13116f6/Table%20name%20sensitivity.png" /></p> <p>Wait…what?  I just created FOO, yet SQL Server is telling me that the table foo doesn’t exist.  What’s going on?  In this case, the database <a href="http://msdn.microsoft.com/en-us/library/ms175835.aspx">default collation</a> has been changed to Latin1_General_Bin, a binary collation, so FOO != ‘foo’.  As a result, the following query also provides no results:</p> <p><img src="http://content.screencast.com/users/EmilT/folders/Jing/media/05da1fbf-2a14-4701-85c3-4edcbbb451d6/Case%20sensitivity%20at%20data%20level.png" /></p> <p>To get any data back from this table, we need to match exactly:</p> <p><img src="http://content.screencast.com/users/EmilT/folders/Jing/media/03b2cdc1-7848-4cd4-91cb-41a3867ff38a/Sucess.png" /></p> <p>Great, so I’ve jacked the default installation collation in SQL Server.  Not a lot of people or organizations do this?  But…is this an academic exercise?  If you want to support multiple databases and clients, the answer is a resounding NO.  Consider:</p> <ol> <li>Some organizations may want the application to work on a database with binary collation.  Rare, but it could happen. </li> <li>Organizations might be using another database, and not all databases are case insensitive, even by default. </li> </ol> <p>If you want a portable application, #2 is your much more concerning issue.  Recently I verified default installations on a number of popular database systems to determine what behavior they produced.  Here are my findings (in alphabetical order):</p> <center> <table border="0" cellspacing="0" cellpadding="2" width="400"><tbody> <tr> <td valign="top" width="133"> <p align="left"></p> </td> <td valign="top" width="149">Table/Column Names</td> <td valign="top" width="117">Data</td> </tr> <tr> <td valign="top" width="133">Oracle</td> <td valign="top" width="149">Insensitive</td> <td valign="top" width="117"><font style="background-color: #ffc000">Sensitive</font></td> </tr> <tr> <td valign="top" width="133">Postgres</td> <td valign="top" width="149">Insensitive</td> <td valign="top" width="117"><font style="background-color: #ffc000">Sensitive</font></td> </tr> <tr> <td valign="top" width="133">MySQL</td> <td valign="top" width="149"><font style="background-color: #ffc000">Sensitive</font></td> <td valign="top" width="117">Insensitive</td> </tr> <tr> <td valign="top" width="133">SQLLite</td> <td valign="top" width="149">Insensitive</td> <td valign="top" width="117"><font style="background-color: #ffc000">Sensitive</font></td> </tr> <tr> <td valign="top" width="133">SQL Server</td> <td valign="top" width="149">Insensitive</td> <td valign="top" width="117">Insensitive</td> </tr> </tbody></table> </center> <p>The most curious finding is MySQL.  I’d love to know what reasoning was used to come to the conclusion that Table and Column names should be case sensitive, but data should be considered insensitive.  In any case, programming for the least common denominator requires handling these situations.  </p> <p>Ideally you’d leave the SQL to an ORM.  If your application is unlikely to switch database platforms and an ORM is out of the question, I’d recommend a RDBMS-specific data access layer.  If you’re application absolutely must have a generic data layer, though, you must keep this in mind as part of design.</p> Emil Lerchhttp://www.blogger.com/profile/13948666821294274991noreply@blogger.comtag:blogger.com,1999:blog-6692354.post-54804833490990591962010-03-22T07:10:00.000-07:002010-03-22T07:10:00.856-07:00Batch uploading RDL files to SQL Server Reporting Services 2005There doesn't seem to be a tool to mass-upload all RDL files in a directory, so I created one. It's available on BitBucket here: http://bitbucket.org/emil/bulk-rdl-uploader-for-ssrs-reports/overview/<br />
<br />
The executable is available here: http://bitbucket.org/emil/bulk-rdl-uploader-for-ssrs-reports/downloads/ReportingServicesBatchUpload.exe<br />
<br />
This is a console application with no dependencies (it calls a web service). Call without parameters for usage information. One known bug is that the "create a folder if it doesn't already exist" logic seems to be broken for some servers, so for best results create the reporting services folder prior to running the program.Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-89337657199748703142010-03-09T08:51:00.000-08:002010-03-10T08:59:19.842-08:00Working with a feature branch in Subversion (TortoiseSVN on Windows)Branching and merging is one of the most nerve-racking activities for people working with Subversion. Unlike Mercurial and other DVCS where branching and merging is commonplace, typical workflows in Subversion do not include this activity. As a result, the terminology is typically confusing, the massive number of changes can be scary, and a lot of people are so concerned about "getting it right" that they typically just avoid the practice altogether and work completely outside of source control. That, of course, is the exact opposite of what we need when working on an important design spike or critical new feature.<br />
<br />
Conceptually, what we want with a design spike or large new feature is to:<br />
<br />
<ul><li>Create a new branch for the change</li>
<li>Work in the new branch, committing early and often</li>
<li>Periodically pull in (merge) the changes from the project trunk</li>
<li>When complete, reintegrate the branch into the trunk</li>
</ul>For these instructions, I assume that you have a subversion repository checked out and you're actively working on the trunk.<br />
<br />
<span style="font-size: large;"><b>Creating a new branch:</b></span><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha1dbZ6Md6CwEmaoImqHMJdlhKLyY64FqbNRT7k6YXdQhXw4suMlKQxM6rhNydhTMDq8qqrwGnXbobY6YaCB1hY7eQKwe44dXJAzN8JOt-7t4PDjudlg6xuh8SyhlxXaE2lXt6/s1600-h/Magical+Snap+-+2010.03.09+08.17+-+003.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha1dbZ6Md6CwEmaoImqHMJdlhKLyY64FqbNRT7k6YXdQhXw4suMlKQxM6rhNydhTMDq8qqrwGnXbobY6YaCB1hY7eQKwe44dXJAzN8JOt-7t4PDjudlg6xuh8SyhlxXaE2lXt6/s400/Magical+Snap+-+2010.03.09+08.17+-+003.png" width="342" /></a></div><ol><li> Right-click on the directory you want to branch. Pick the Branch/Tag operation.</li>
<li>On the branch/tag screen, enter a new branch (typically the repository has a /branches folder as well as a /trunk folder). The new branch is typically /branches/<i>mynewbranch</i>, where the branch name itself is a folder that does not exist in the repository.</li>
<li>In this scenario, you will also want to choose "switch working copy to new branch/tag". We'll be doing work on the new feature or design change immediately, so this tells subversion that any new commits will be on that other branch.</li>
</ol><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvbqUQAgGwIEeXN4TxgOfnNktuNcavycIANq6nVyhKod4DgB0Tcdw21LPOMcFXNRl6shBRs8617utGC8f3JZ08ktxpWRmFSwVBMknGJpmziaym1kkN1hxCMrYgz2ndU3nsiOC1/s1600-h/Magical+Snap+-+2010.03.09+08.22+-+004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvbqUQAgGwIEeXN4TxgOfnNktuNcavycIANq6nVyhKod4DgB0Tcdw21LPOMcFXNRl6shBRs8617utGC8f3JZ08ktxpWRmFSwVBMknGJpmziaym1kkN1hxCMrYgz2ndU3nsiOC1/s640/Magical+Snap+-+2010.03.09+08.22+-+004.png" width="587" /></a></div> At this point you'll want to take note of the revision number that had the last changes.<br />
<br />
<span style="font-size: large;"><b></b></span><br />
<span style="font-size: large;"><b>Work in the new branch, committing early and often</b></span><br />
<br />
This is standard subversion behavior.<br />
<br />
<span style="font-size: large;"><b>Periodically pull in (merge) the changes from the project trunk</b></span><br />
<br />
You'll want to keep track of the last revision you've pulled changes from. In the beginning, this revision number is the revision that represented the branch itself.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiAQJgYPvBxyKM43plscHGYZs8iHOTYDFGtR3wH3IZclIzdjLz6uf4pZquuUv6zsenOgybq_zW4MOQ6vQhMtuZuXWWPVnCQjnOHbbhc9IsYFbmeVjq71rFfllTo8pFi-Laua5l/s1600-h/Magical+Snap+-+2010.03.09+08.32+-+005.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiAQJgYPvBxyKM43plscHGYZs8iHOTYDFGtR3wH3IZclIzdjLz6uf4pZquuUv6zsenOgybq_zW4MOQ6vQhMtuZuXWWPVnCQjnOHbbhc9IsYFbmeVjq71rFfllTo8pFi-Laua5l/s400/Magical+Snap+-+2010.03.09+08.32+-+005.png" width="345" /></a></div><ol><li> Pick the Merge tool off the TortoiseSVN menu.</li>
<li>Choose the "Merge a range of revisions" from the first screen of the wizard.</li>
<li>In the "URL to merge from", choose the trunk.</li>
<li>In the Revision range to merge, the best approach is to be precise. Put in the last revision number that was merged (e.g. if you branched when the repository was at revision 10, put in 11-HEAD). You can leave this blank, but we want to avoid merging a change twice. You may need to look at the log to help find the right revisions.</li>
</ol><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYudAW5-FQ0w1Rjc7yH-EstdF8ng2nbmJWrPw36MpTI_Jjx0yzi8mFBKGyWpWi04GYgm9WIg9ZC3Mx5cteaAboKcVt-uRhCMnTEUCHQdYWR4JYXEbQzo8Kb7n1Lg7ISiYYANjF/s1600-h/Magical+Snap+-+2010.03.09+08.37+-+006.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="588" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYudAW5-FQ0w1Rjc7yH-EstdF8ng2nbmJWrPw36MpTI_Jjx0yzi8mFBKGyWpWi04GYgm9WIg9ZC3Mx5cteaAboKcVt-uRhCMnTEUCHQdYWR4JYXEbQzo8Kb7n1Lg7ISiYYANjF/s640/Magical+Snap+-+2010.03.09+08.37+-+006.png" width="640" /></a></div>Hit next and do a test merge just to be sure before performing the actual merge. All other settings can be left at their defaults. Note that the merge is done in your working directory, so you'll have a bunch of local changes to test and commit on your branch.<br />
<br />
<span style="font-size: large;"><b>Reintegrate the branch into the trunk</b></span><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqp8OaXK0C7Z9zFUmt-v_YETb6vJuZ232MTYka8svBT76_LINZXatTMvcsBGBsVfCMyOPKT7Y2Tsh886WyzqjlPg6T6OYiompc3vrCv9SlFms86aphnwIQoTEEM5pmJX68QzUH/s1600-h/Magical+Snap+-+2010.03.09+08.47+-+007.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqp8OaXK0C7Z9zFUmt-v_YETb6vJuZ232MTYka8svBT76_LINZXatTMvcsBGBsVfCMyOPKT7Y2Tsh886WyzqjlPg6T6OYiompc3vrCv9SlFms86aphnwIQoTEEM5pmJX68QzUH/s400/Magical+Snap+-+2010.03.09+08.47+-+007.png" width="343" /></a></div><ol><li>Commit all branch changes</li>
<li> Switch the working directory back to the trunk. This is done via the TortoiseSVN switch command.</li>
<li>Pick the Merge command off the TortoiseSVN menu as before. This time, however, we'll pick the "Reintegrate a branch" option.</li>
<li>In the "From URL" field, put the URL to the branch you've finished working on.</li>
<li>Test the merge and if happy, perform the merge, test the changes, and commit to the trunk.</li>
</ol><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk7vUz6W2Cj_NbY4fW3NZv9wwJoATvFKlV_IZ4xGDryjjSP-tlXZgE9HhnEwGkFL9rqVTuRAIPD1iACQ0H8_GJyTWKqaUIhyphenhyphenBfK-uEx7RVxmVdUNXRCNDHORViH8fq1jn0Nnxh/s1600-h/Magical+Snap+-+2010.03.09+08.48+-+008.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="587" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk7vUz6W2Cj_NbY4fW3NZv9wwJoATvFKlV_IZ4xGDryjjSP-tlXZgE9HhnEwGkFL9rqVTuRAIPD1iACQ0H8_GJyTWKqaUIhyphenhyphenBfK-uEx7RVxmVdUNXRCNDHORViH8fq1jn0Nnxh/s640/Magical+Snap+-+2010.03.09+08.48+-+008.png" width="640" /></a></div><br clear="all"/>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-83656340773933672302010-02-25T17:39:00.000-08:002010-02-25T17:46:52.281-08:00Spring.Net-enabled WCF Services available from Microsoft Ajax<div class="separator" style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLGxndQbRgNFAI1qwZ7dBegAGT-eQHseVpZ6aETYxdGENF0Kq0EX-bsaaxjcdnANyffCKbOuGiyxqdbxshW7HuP6sULkDtDWcZosmtmub8OuhfI7QHe0JasS096MllaqUe4mcF/s1600-h/Magical+Snap+-+2010.02.25+16.58+-+005.png" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLGxndQbRgNFAI1qwZ7dBegAGT-eQHseVpZ6aETYxdGENF0Kq0EX-bsaaxjcdnANyffCKbOuGiyxqdbxshW7HuP6sULkDtDWcZosmtmub8OuhfI7QHe0JasS096MllaqUe4mcF/s320/Magical+Snap+-+2010.02.25+16.58+-+005.png" /></a></div>Implementing Spring.NET WCF services is fairly straightforward.<br />
<br />
Implementing MS Ajax WCF services is also straightforward, if you pick the right New Item to add from Visual Studio.<br />
<br />
The complication comes in when you want a Spring.NET WCF service that handles calls from Microsoft Ajax controls. This method will let you add them. <br />
<br />
Step 1. Add new "Ajax-Enabled WCF Service"<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihoo5TIbWEhNEelEcXduGpQqI0I4_pqJFqyQ-6btcymoym_3ojMci-PdxD4Z4qMNiy-T7t13QaceevgF9VWdRYAp61fFaWeXpC69EVN2DpqA69Oo9KjdlVwgY5T39PHWwdFL9p/s1600-h/Magical+Snap+-+2010.02.25+16.59+-+006.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="420" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihoo5TIbWEhNEelEcXduGpQqI0I4_pqJFqyQ-6btcymoym_3ojMci-PdxD4Z4qMNiy-T7t13QaceevgF9VWdRYAp61fFaWeXpC69EVN2DpqA69Oo9KjdlVwgY5T39PHWwdFL9p/s640/Magical+Snap+-+2010.02.25+16.59+-+006.png" width="640" /></a></div><br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: left;">Step 2. Create your methods, test and make sure all base functionality is working. This sample is for a CascadingDropDown control from the Ajax Control Toolkit, but any control will work.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif2TXyVxfUE8Rd-WVScgYyrrGbaj7F27dYl93kXBJ7SUtj45Agj0H_Zi7N1MyMQheNlP6b9Ugja2jWe9ok8RUIHBh8yasI0UYoFICIJKKBTP7dfNH_JEfv7DR8as8CWnpuDEm7/s1600-h/Magical+Snap+-+2010.02.25+17.03+-+007.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif2TXyVxfUE8Rd-WVScgYyrrGbaj7F27dYl93kXBJ7SUtj45Agj0H_Zi7N1MyMQheNlP6b9Ugja2jWe9ok8RUIHBh8yasI0UYoFICIJKKBTP7dfNH_JEfv7DR8as8CWnpuDEm7/s640/Magical+Snap+-+2010.02.25+17.03+-+007.png" width="640" /></a><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDuI5g7AY6APHNPDlL9YrwQjiqZKGFt4CHOC5p40arE6_r_lqj4ppC7c1joprhXf66gj9z3CCFsJ_qenvZyyw3qictu3pttALHLMhVrMpPLUJzf0lM5gjx6Kqj6YB1Xo9vrzrw/s1600-h/Magical+Snap+-+2010.02.25+17.06+-+011.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDuI5g7AY6APHNPDlL9YrwQjiqZKGFt4CHOC5p40arE6_r_lqj4ppC7c1joprhXf66gj9z3CCFsJ_qenvZyyw3qictu3pttALHLMhVrMpPLUJzf0lM5gjx6Kqj6YB1Xo9vrzrw/s320/Magical+Snap+-+2010.02.25+17.06+-+011.png" /></a></div>Step 3. Introduce an interface to use for the methods. Spring.Net requires an interface, and this is the crux of the problem. Here I've created IMyAjaxService.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: left;">Step 4. Move the [ServiceContract(Namespace = "")] from the class to the interface</div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHIakzHDkkNwvW3WkAir1bZ8XqzKOHLk9tdgEnlAUh5Bs8ddIsrT5hAUhQZKdaEG9VUmbU52-mhhP82LzY_yShW0E_PZLEExjBZ-WqdCFDnnG5FnionF0M5FB2-LVwtierdqJv/s1600-h/Magical+Snap+-+2010.02.25+17.09+-+012.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHIakzHDkkNwvW3WkAir1bZ8XqzKOHLk9tdgEnlAUh5Bs8ddIsrT5hAUhQZKdaEG9VUmbU52-mhhP82LzY_yShW0E_PZLEExjBZ-WqdCFDnnG5FnionF0M5FB2-LVwtierdqJv/s640/Magical+Snap+-+2010.02.25+17.09+-+012.png" width="640" /></a><br />
<br />
<div class="separator" style="clear: both; text-align: left;">Step 5. Move the [OperationContract] tags from the methods on the class to the interface method definitions</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCRjREg-ikxqFrB7bQEADHzmeGbW-wOy9HQlISa3YqxvxK83nvkOw1zdYN819UTOl_VMpxgZSOhF_SI_elLFF1SSlQ49f3oxvnVJq1lnN06qZntoN8BjHFZBXSLsUYI6WpEwSm/s1600-h/Magical+Snap+-+2010.02.25+17.10+-+013.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="404" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCRjREg-ikxqFrB7bQEADHzmeGbW-wOy9HQlISa3YqxvxK83nvkOw1zdYN819UTOl_VMpxgZSOhF_SI_elLFF1SSlQ49f3oxvnVJq1lnN06qZntoN8BjHFZBXSLsUYI6WpEwSm/s640/Magical+Snap+-+2010.02.25+17.10+-+013.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div>Step 6. Change web.config endpoint contract (xpath = /configuration/system.serviceModel/services/service/endpoint) to reference the interface<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilEMoPB_WYN7XHnm-MFvF_Q6zBpY7Vldz3GQNo0jgLeefDSAqJuhSfC8HkLDZ6z5C8h0qNqHFpRq1Fg0_ZkXtk7vU9GVshUr-y-YgcTXhAeofk5R-1p5oTJs3blGoyssdK0Hlk/s1600-h/Magical+Snap+-+2010.02.25+17.13+-+015.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilEMoPB_WYN7XHnm-MFvF_Q6zBpY7Vldz3GQNo0jgLeefDSAqJuhSfC8HkLDZ6z5C8h0qNqHFpRq1Fg0_ZkXtk7vU9GVshUr-y-YgcTXhAeofk5R-1p5oTJs3blGoyssdK0Hlk/s640/Magical+Snap+-+2010.02.25+17.13+-+015.png" width="640" /></a></div><br />
<br />
Step 7: Test. The test should work, without dependency injection from Spring.Net. Now we have a WCF service that responds to Ajax, but has the interface definitions just the way Spring likes them.<br />
<br />
<div style="text-align: center;"><u><span style="font-size: large;">Wiring in Spring</span></u></div><br />
For Spring.NET to handle WCF, you need .NET 3.0 or higher, and you need Spring.Net 1.3.0 or higher. You'll need the following DLLs available for binding (either your bin directory or the GAC):<br />
<br />
<ul><li>Spring.Core.dll from the 2.0 folder</li>
<li>Spring.Web.dll from the 2.0 folder</li>
<li>Spring.Services.dll from the 3.0 folder</li>
</ul>In the Service you've created, edit the markup and add Factory="Spring.ServiceModel.Activation.ServiceHostFactory" onto the end, like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUuS8g7BiHvvRf-IHDf8O0xFO7_HTRh0Wcp5GRCFqVnMjpuBnQTQsW3nuuni9teut3y4Vjhilv8cQqhmUSLccz9N2oNBjsOI3-GSHEuZ_MDb8RnaXJP0RApqG-Wv-2pgPOJTAH/s1600-h/Magical+Snap+-+2010.02.25+17.14+-+016.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="76" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUuS8g7BiHvvRf-IHDf8O0xFO7_HTRh0Wcp5GRCFqVnMjpuBnQTQsW3nuuni9teut3y4Vjhilv8cQqhmUSLccz9N2oNBjsOI3-GSHEuZ_MDb8RnaXJP0RApqG-Wv-2pgPOJTAH/s640/Magical+Snap+-+2010.02.25+17.14+-+016.png" width="640" /></a></div>This will get Spring.Net into the activation pipeline for the service.<br />
<br />
Lastly, you'll add the new object to spring configuration. It is <span style="background-color: white;">CRITICAL that the OBJECT ID MATCH THE SERVICE NAME FROM WEB.CONFIG. The Spring.Net documentation mentions this, but I don't think they mention it very loudly. The type information is exactly as you'd expect: the type for the WCF service class.</span><br />
<span style="background-color: white;"><br />
</span><br />
Also CRITICAL: Add singleton="false" to the object definition for Spring for your new objectUnknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-52302598009239428442009-07-08T22:50:00.001-07:002009-09-29T13:20:59.569-07:00Intermittent Operation Aborted Errors in IE when using MS AjaxThis issue has been plaguing our project: operation aborted errors, intermittent in nature, occurring sometimes as little as once/week. Even in IE 8 there were issues, although thankfully not the crazy dialog box we see in IE 6 and 7.<br /><br />It turns out that the problem is due to a bug in Ajax itself. I won't go into all the details, since they're covered very well in these two blog posts:<br /><ul><li>First post with background: <a href="http://seejoelprogram.wordpress.com/2008/06/08/when-sysapplicationinitialize-causes-operation-aborted-in-ie/">http://seejoelprogram.wordpress.com/2008/06/08/when-sysapplicationinitialize-causes-operation-aborted-in-ie/</a><br /></li><li>Second post with bug fixes to the original bug fix: <a href="http://www.blogger.com/post-create.g?blogID=6692354#%20http://seejoelprogram.wordpress.com/2008/10/03/fixing-sysapplicationinitialize-again/">http://seejoelprogram.wordpress.com/2008/10/03/fixing-sysapplicationinitialize-again/</a><br /></li></ul>I didn't particularly care for the recommended way of packaging the fix, so instead I've used built-in ASP.NET Ajax functionality to override the default script delivery. I also updated the fixed functions to work for all versions of Ajax (at the time of this writing - currently Ajax bundled with .NET 3.5 SP1 and below). First, here are the updated functions:<br /><br /><ul><br /><li>Sys$_Application$initialize:<br /><pre class="brush:js"><br /> function Sys$_Application$initialize() {<br /> if(!this._initialized && !this._initializing) {<br /> this._initializing = true;<br /> var u = window.navigator.userAgent.toLowerCase(),<br /> v = parseFloat(u.match(/.+(?:rv|it|ml|ra|ie)[\/: ]([\d.]+)/)[1]);<br /><br /> var initializeDelegate = Function.createDelegate(this, this._doInitialize);<br /><br /> if (/WebKit/i.test(u) && v < 525.13)<br /> {<br /> this._load_timer = window.setInterval(function()<br /> {<br /> if (/loaded|complete/.test(document.readyState))<br /> {<br /> initializeDelegate();<br /> }<br /> }, 10);<br /> }<br /> else if (/msie/.test(u) && !window.opera)<br /> {<br /> document.attachEvent('onreadystatechange',<br /> function (e) {<br /> if (e && arguments.callee && document.readyState == 'complete') {<br /> document.detachEvent('on'+e.type, arguments.callee);<br /> initializeDelegate();<br /> }<br /> }<br /> );<br /> if (window == top) {<br /> (function () {<br /> try {<br /> document.documentElement.doScroll('left');<br /> } catch (e) {<br /> setTimeout(arguments.callee, 10);<br /> return;<br /> }<br /> initializeDelegate();<br /> })();<br /> }<br /><br /> }<br /> else if (document.addEventListener<br /> && ((/opera\//.test(u) && v > 9) ||<br /> (/gecko\//.test(u) && v >= 1.8) ||<br /> (/khtml\//.test(u) && v >= 4.0) ||<br /> (/webkit\//.test(u) && v >= 525.13))) {<br /> document.addEventListener("DOMContentLoaded", initializeDelegate, false);<br /> }<br /> else<br /> {<br /> $addHandler(window, "load", initializeDelegate);<br /> }<br /> }<br /> }<br /><br /></pre><br /></li><li>Sys$_Application$_doInitialize():<br /><pre class="brush:js"><br /> function Sys$_Application$_doInitialize() {<br /> if (this._initialized) {<br /> return;<br /> }<br /> Sys._Application.callBaseMethod(this, 'initialize');<br /> if (this._load_timer !== null)<br /> {<br /> clearInterval(this._load_timer);<br /> this._load_timer = null;<br /> }<br /> var handler = this.get_events().getHandler("init");<br /> if (handler) {<br /> this.beginCreateComponents();<br /> handler(this, Sys.EventArgs.Empty);<br /> this.endCreateComponents();<br /> }<br /> if (Sys.WebForms) {<br /> if (this._onPageRequestManagerBeginRequest) this._beginRequestHandler = Function.createDelegate(this, this._onPageRequestManagerBeginRequest);<br /> if (this._beginRequestHandler) Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._beginRequestHandler);<br /> if (this._onPageRequestManagerEndRequest) this._endRequestHandler = Function.createDelegate(this, this._onPageRequestManagerEndRequest);<br /> if (this._endRequestHandler) Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._endRequestHandler);<br /> }<br /><br /> if (this.get_stateString){<br /> var loadedEntry = this.get_stateString();<br /> if (loadedEntry !== this._currentEntry) {<br /> this._navigate(loadedEntry);<br /> }<br /> }<br /> this.raiseLoad();<br /> this._initializing = false;<br /> }<br /><br /></pre><br /></li><li>Sys$_Application$_loadHandler():<br /><pre class="brush:js"><br /> function Sys$_Application$_loadHandler() {<br /> if(this._loadHandlerDelegate) {<br /> Sys.UI.DomEvent.removeHandler(window, "load", this._loadHandlerDelegate);<br /> this._loadHandlerDelegate = null;<br /> }<br /> this._initializing = true;<br /> this._doInitialize();<br /> }<br /></pre><br /></li><br /></ul><br /><br />Next, here is how I overrode how the framework delivers the script:<br /><br /><pre class="brush:xml"><br /> <ajaxtoolkit:toolkitscriptmanager runat="server" enablepartialrendering="true" id="ScriptManager"><br /> <scripts><br /> <asp:scriptreference name="MicrosoftAjax.js" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" path="~/js/MicrosoftAjax-withFix.js"><br /> </scripts><br /> </ajaxToolkit:ToolkitScriptManager><br /></pre><br />You do not need to use the ToolKitScriptManager - you can also do it this way:<br /><br /><pre class="brush:xml"><br /> <asp:scriptmanager runat="server" enablepartialrendering="true" id="ScriptManager"><br /> <scripts><br /><asp:scriptreference name="MicrosoftAjax.js" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" path="~/js/MicrosoftAjax-withFix.js"><br /> </scripts><br /> </asp:ScriptManager><br /></pre><br />Note that you can replace ~/js with the directory of your choosing.<br /><br />Be aware that when the framework loads the file, it automatically adds .debug or .release onto the end of the file name, so the final file reference provided will be either MicrosoftAjax-withFix.debug.js or MicrosoftAjax-withFix.release.js.<br /><br />If you don't want to bother incorporating these fixes into .NET 3.5 SP1 Ajax files, feel free to download them from here:<br /><br /><ul><li>Debug version: <a href="http://lerch.org/js/MicrosoftAjax-WithFix.debug.js">http://lerch.org/js/MicrosoftAjax-WithFix.debug.js</a><br /></li><li>Release version (simply a minified version of the debug js - run through <a href="http://developer.yahoo.com/yui/compressor/">YUI Compresssor</a>): <a href="http://lerch.org/js/MicrosoftAjax-WithFix.release.js">http://lerch.org/js/MicrosoftAjax-WithFix.release.js</a><br /></li></ul>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-49440900638655178072009-07-07T10:56:00.001-07:002009-07-07T13:59:22.320-07:00Javascript Hacks: Using XHR to load binary dataI recently needed to get image data from a server using Javascript, base64 encode it, and post that data back to an application. While the details of <span style="font-weight: bold;">why</span> I needed to do this are a bit complex, I believe that getting image data through an XMLHttpRequest object and base 64 enconding it will become more valuable in terms of client-side image manipulation using the <a href="http://en.wikipedia.org/wiki/Data_URI_scheme">data URI scheme</a> for image tags.<br /><br />This would allow a Javascript developer, for instance, to load an existing image (say, a photo), without base64 encoding it on the server, load it into an image tag with a data URI, and make direct manipulations on that image.<br /><br />Unfortunately, this area is relatively new and browsers have a lot of differences. Data URI support is still very new, inconsistent, and limited. In the meantime, here is how you get that base64 encoded image in the first place:<br /><br />Internet Explorer:<br /><div style="padding-left: 4em;"><br />IE has a property of XMLHttpRequest object for binary data <a href="http://msdn.microsoft.com/en-us/library/ms534368%28VS.85%29.aspx">ResponseBody</a>. This contains exactly what we need, but unfortunately the property is not visible to Javascript. Since the string returned to Javascript by <a href="http://msdn.microsoft.com/en-us/library/ms534369%28VS.85%29.aspx">ResponseText</a> will be terminated at the first null value, we must use ResponseBody. This requires a bit of VBScript, which can do one of the following things:<br /><ol><li>Get the numeric value of each unsigned byte and turn that into a number in a string of comma delimited numbers. This is less efficient, but gets you in and out of VBScript as quickly as possible, allowing a generic base64 encoding routine. This is the route I followed (it may be less efficient, but it pales in comparison with the XHR request just made):<br /><pre class="brush:vb"><br />Function BinaryArrayToAscCSV( aBytes )<br /> Dim j, sOutput<br /> sOutput = "BinaryArrayToAscCSV"<br /> For j = 1 to LenB(aBytes)<br /> sOutput= sOutput & AscB( MidB(aBytes,j,1) )<br /> sOutput= sOutput & ","<br /> Next<br /> BinaryArrayToAscCSV = sOutput<br />End Function<br /></pre><br /></li><li>Base 64 encode it directly in VBScript.</li></ol><br />Once this is done, we can then base64 encode it using a fairly generic function in Javascript:<br /><pre class="brush:js"><br />Base64 = {<br /> <br /> // private property<br /> _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",<br /><br /> encodeBinaryArrayAsString : function(input){<br /> var ascArr;<br /> var output = "";<br /> var bytebuffer;<br /> var encodedCharIndexes = new Array(4);<br /> <br /> var inx = 0;<br /> ascArr = input.substring("BinaryArrayToAscCSV".length, input.length - 1).split(',');<br /> while(inx < ascArr.length){<br /> // Fill byte buffer array<br /> bytebuffer = new Array(3);<br /> for(jnx = 0; jnx < bytebuffer.length; jnx++)<br /> if(inx < ascArr.length)<br /> bytebuffer[jnx] = parseInt(ascArr[inx++]); <br /> else<br /> bytebuffer[jnx] = 0;<br /> <br /> // Get each encoded character, 6 bits at a time<br /> // index 1: first 6 bits<br /> encodedCharIndexes[0] = bytebuffer[0] >> 2; <br /> // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)<br /> encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); <br /> // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)<br /> encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); <br /> // index 3: forth 6 bits (6 least significant bits from input byte 3)<br /> encodedCharIndexes[3] = bytebuffer[2] & 0x3f; <br /> <br /> // Determine whether padding happened, and adjust accordingly<br /> paddingBytes = inx - (ascArr.length - 1);<br /> switch(paddingBytes){<br /> case 2:<br /> // Set last 2 characters to padding char<br /> encodedCharIndexes[3] = 64; <br /> encodedCharIndexes[2] = 64; <br /> break;<br /> case 1:<br /> // Set last character to padding char<br /> encodedCharIndexes[3] = 64; <br /> break;<br /> default:<br /> break; // No padding - proceed<br /> }<br /> // Now we will grab each appropriate character out of our keystring<br /> // based on our index array and append it to the output string<br /> for(jnx = 0; jnx < encodedCharIndexes.length; jnx++)<br /> output += this._keyStr.charAt(encodedCharIndexes[jnx]); <br /> }<br /> return output;<br /> }<br />};<br /></pre><br /><br/><br />Firefox:<br /><div style="padding-left: 4em;"><br />Firefox works a little differently, as there is no RequestBody property. In this case, RequestText is not truncated as long as you override the mime type coming from the server, forcing Firefox to pass the data unaltered. All we need to do is compensate for binary data coming back and being placed in a Unicode Javascript string. To compensate, we can AND each character with 0xFF to throw away the high-order byte (see <a href="https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data">https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data</a>). The resulting encoding function looks like this:<br /><pre class="brush:js"><br />Base64 = {<br /> <br /> // private property<br /> _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",<br /><br /> encodeBinary : function(input){<br /> var output = "";<br /> var bytebuffer;<br /> var encodedCharIndexes = new Array(4);<br /> var inx = 0;<br /> var paddingBytes = 0;<br /> <br /> while(inx < input.length){<br /> // Fill byte buffer array<br /> bytebuffer = new Array(3);<br /> for(jnx = 0; jnx < bytebuffer.length; jnx++)<br /> if(inx < input.length)<br /> bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; // throw away high-order byte, as documented at: https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data<br /> else<br /> bytebuffer[jnx] = 0;<br /> <br /> // Get each encoded character, 6 bits at a time<br /> // index 1: first 6 bits<br /> encodedCharIndexes[0] = bytebuffer[0] >> 2; <br /> // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)<br /> encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); <br /> // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)<br /> encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); <br /> // index 3: forth 6 bits (6 least significant bits from input byte 3)<br /> encodedCharIndexes[3] = bytebuffer[2] & 0x3f; <br /> <br /> // Determine whether padding happened, and adjust accordingly<br /> paddingBytes = inx - (input.length - 1);<br /> switch(paddingBytes){<br /> case 2:<br /> // Set last 2 characters to padding char<br /> encodedCharIndexes[3] = 64; <br /> encodedCharIndexes[2] = 64; <br /> break;<br /> case 1:<br /> // Set last character to padding char<br /> encodedCharIndexes[3] = 64; <br /> break;<br /> default:<br /> break; // No padding - proceed<br /> }<br /> // Now we will grab each appropriate character out of our keystring<br /> // based on our index array and append it to the output string<br /> for(jnx = 0; jnx < encodedCharIndexes.length; jnx++)<br /> output += this._keyStr.charAt(encodedCharIndexes[jnx]);<br /> }<br /> return output;<br /> };<br /></pre><br /></div><br />Ideally we'd combine these two functions into a single encoding function, but I've left them separate for clarity. Note also that these techniques do not appear to work for Safari, Chrome or Opera. It should work for IE6 if using the correct ActiveX XHR object, but I was not supporting IE6. I did a spot check on Safari/Chrome/Opera and they were not working, but I did not investigate as they were not supported browsers for my implementation. The actual XHR function I used was:<br /><pre class="brush:js"><br />LoadBinaryResource = function(url) { <br /> var req = new XMLHttpRequest(); <br /> req.open('GET', url, false); <br /><br /> if (req.overrideMimeType)<br /> req.overrideMimeType('text/plain; charset=x-user-defined'); <br /> req.send(null); <br /> if (req.status != 200) return ''; <br /> if (typeof(req.responseBody) !== 'undefined') return BinaryArrayToAscCSV(req.responseBody);<br /> return req.responseText; <br />} <br /><br />LoadBinaryResourceAsBase64 = function(url) { <br /> var data = LoadBinaryResource(url);<br /> <br /> if (data.indexOf("BinaryArrayToAscCSV") !== -1)<br /> return Base64.encodeBinaryArrayAsString(data);<br /> else<br /> return Base64.encodeBinary(data); <br />} <br /></pre><br /><br /></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-19041252600168789352008-10-28T23:42:00.001-07:002009-07-07T20:17:33.198-07:00A little surprised no one caught thisSo I just watched last week's <a href="http://www.nbc.com/Saturday_Night_Live/video/categories/weekend-update-thursdays/29439/">SNL Weekend Update Thursdays </a>on <a href="http://nbc.com">NBC.com</a>, and decided to play around with their viewer. I haven't watched shows there before, but the Olympics were Silverlight and I wanted to know if they used <a href="http://silverlight.net/">Silverlight </a>(no, they use <a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash">Flash</a>), and what features they had. I hit the info button (the thing with the arrow pointing to it), and was greeted with the interface you see below...the red box is mine (added for emphasis). Clearly they had some of the original mockup "<a href="http://en.wikipedia.org/wiki/Lorem_ipsum">Lorem Ipsum</a>" in there and no one bothered to update it or correct it.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://img11.imageshack.us/img11/286/200810282331.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 1019px; height: 672px;" src="http://img11.imageshack.us/img11/286/200810282331.jpg" alt="" border="0" /></a>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-31280641704448955612008-09-25T09:13:00.000-07:002008-09-25T09:21:33.471-07:00It doesn't get much better than thisHow's this for a setup message? Kinda hard to comply with...<br /><br /><a href="http://content.screencast.com/users/EmilT/folders/Jing/media/5412a0bb-c6d1-48be-a4df-352829c740e3/2008-09-25_0849.png"><img style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="http://content.screencast.com/users/EmilT/folders/Jing/media/5412a0bb-c6d1-48be-a4df-352829c740e3/2008-09-25_0849.png" border="0" /></a><br /><div><br /><div> </div><br /><br /><div></div><br /><br /><div></div></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-85102871311246048092008-05-27T08:56:00.000-07:002008-05-27T08:59:41.582-07:00One more technical analysis linkI bumped across <a href="http://www.stoxline.com/">Stoxline</a> during my <a href="http://emilsblog.lerch.org/2008/05/excercising-intc-stock-options.html">recent foray into the technical analysis world</a>. It provides a good quick summary of some key price points.Unknownnoreply@blogger.comtag:blogger.com,1999:blog-6692354.post-2152996678541850712008-05-23T07:50:00.000-07:002008-05-23T08:39:32.374-07:00Excercising INTC stock optionsSo I've excercised the remaining stock options from Intel that remain above water. There are still a large number of options that will die worthless (my original options were priced at $67 back in 2001, current stock price is $23.52, and there were no splits in between). The next set of options that even have a shot at becoming in the money are priced around $26, and with 3 weeks out, it would be surprising if they became valuable. Here's the quick story of how the excercise went down.<br /><br />I excercised in three batches. The first batch I got totally lucky and sold at $27.98, exactly $0.01 off the 52 week high. Dumb luck. I sold only half because word on the street was that Q1 would be great, and the price would keep going up. In retrospect, I think selling half was a good move, but my big mistake here was not to have sold the most expensively priced options. Those options at $26 would have actually been worth something. <br /><br />The stock tanked this year, but recently began to gain ground. Oddly, it picked up momentum based on almost no news (the overall market was also up). Intel did <a href="http://www.thestreet.com/s/tech-winners-and-losers-intel/newsanalysis/winnerstech/_msnh/10417027.html?&cm_ven=MSNH&cm_cat=FREE&cm_ite=NA">get an upgrade</a> that did pretty well for the stock. Due to what seemed to be a short term movement and the imminent expiration of my options, I dug out some of my technical analysis knowledge and went to town:<br /><br />I watched the following indicators:<br /><br /><ul><li><a href="http://www.investopedia.com/terms/m/macd.asp">MACD</a>: I was looking pretty short-term (<1><li><a href="http://www.investopedia.com/terms/b/bollingerbands.asp">Bollinger Bands</a>: I thought this would be a fairly useless indicator, but in fact, it was just when the stock crossed the upper band that it turned negative.</li><li><a href="http://www.investopedia.com/terms/r/rsi.asp">RSI</a>: Fairly useful indicator in this scenario</li><li><a href="http://www.investopedia.com/terms/s/stochasticoscillator.asp">Slow Stochastic Oscillator</a>: Fast stoch always seems too touchy for me. Maybe if I were trading several times a day it would be different, but the slow stoch was useful</li><li><a href="http://www.investopedia.com/terms/p/parabolicindicator.asp">Parabolic SAR</a>: My primary source of when the options should be sold.<br /></li></ul>When the stock hit 25 and retreated a bit to 24.60, I decided to sell my second batch, a fairly small set of options that were priced in the mid 23's. My primary thinking here was to lock in some of the options since going up over 5% in one day on no news was just crazy.<br /><br />At 25, the MACD, Bollinger Bands and RSI indicators all went bearish, so I thought I'd sell when the price started to dip. The next day it opened pretty low and then dropped below 24.13, which was the Parabolic SAR trigger point, so now all the indicators I was tracking went bearish. I sold at 24.08, and so far, it's down another 0.85 from there.<br /><br />Lessons learned? The indicators can work...don't rely on just one, and make sure that you use the right indicator for your goal.<br /><br />Another couple links of use:<br /><ul><li><a href="http://research.scottrade.com/public/stocks/charts/charts.asp?symbol=INTC">Scottrade chart</a>: This chart is continuously updated, and summarizes what the indicators are saying (e.g. Parabolic Indicator is bearish/MACD is bullish). The conintuous updates made it more useful than Yahoo. It does, however, force you to re-add the indicators - no deep link is possible.</li><li><a href="http://finance.yahoo.com/echarts?s=INTC#chart1:symbol=intc;range=1m;indicator=bollinger+psar+rsi+macd+stochasticfast;charttype=candlestick;crosshair=on;ohlcvalues=0;logscale=off;source=undefined">Yahoo chart</a>: I was originally using this chart from Yahoo. Since the URL includes all the options, it looks exactly as I was using. However, it only updates at the end of each day.</li><li><a href="http://www.tdameritrade.com/tradingtools/commandcenter.html">TD Ameritrade Command Center 2.0</a>: A Java app available for <a href="http://www.tdameritrade.com/welcome1.html">TD Ameritrade</a> customers, it let me watch the stock in real-time during the day.<br /></li></ul>Unknownnoreply@blogger.com