<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DkMGRHc5fSp7ImA9WhRWEEU.&quot;"><id>tag:blogger.com,1999:blog-6692354</id><updated>2011-12-28T07:00:25.925-08:00</updated><category term="C#" /><category term="Tools" /><category term="EduSpring" /><category term="SQL" /><category term="Javascript" /><title>Emil's Wicked Cool Blog</title><subtitle type="html">Hmm...</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://emilsblog.lerch.org/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>156</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/emillerch" /><feedburner:info uri="emillerch" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0QMRHs4fSp7ImA9WhZbEEs.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-2366771614810546922</id><published>2011-06-14T09:36:00.000-07:00</published><updated>2011-06-14T09:36:25.535-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-14T09:36:25.535-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EduSpring" /><title>EduSpring Part 6: Crazy Error Messages and What to do about them</title><content type="html">&lt;div&gt;Because Spring will create most of your objects up front, a simple error in the configuration Xml can have&amp;nbsp;disastrous&amp;nbsp;effects. &amp;nbsp;This, in my opinion, is the #1 reason people fear Spring.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Here are a few error messages I've seen, and their corresponding solutions:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;The virtual path '/currentcontext.dummy' maps to another application, which is not allowed&lt;/b&gt;: This error message usually means you've deployed the application to a server, but forgotten to make the virtual directory an application in IIS. &amp;nbsp;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.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;no application context for virtual path&lt;/b&gt;: &amp;nbsp;This error message tells you that there's no spring configuration setup at all.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Resource handler for the 'web' protocol is not defined&lt;/b&gt;: &amp;nbsp;This message tells you that the httpModule is not active. &amp;nbsp;Add the spring.net HttpModule into the appropriate section of web.config (system.web for IIS6, system.webserver for IIS7).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Could not load type from assembly&lt;/b&gt;: &amp;nbsp;This may or may not have anything to do with Spring, so take a look a the stack trace. &amp;nbsp;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.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;node cannot be resolved for the specified context&lt;/b&gt;: Spring tried to assign an object or value to a property, but the property doesn't exist on the object. &amp;nbsp;It's likely you misspelled the property name, or maybe you refactored, removed the property, but forgot to update the spring configuration.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Things to check if your dependency is showing up as null:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Is your configuration binding the right type? &amp;nbsp;For example, if your property is a string, and you're assigning a stringbuilder to it, Spring will just ignore the assignment.&lt;/li&gt;
&lt;li&gt;You're missing the object definition in the spring configuration.&lt;/li&gt;
&lt;li&gt;You're missing the property definition in the spring configuration.&lt;/li&gt;
&lt;li&gt;Did you commit the cardinal sin of DI? &amp;nbsp;Do not use new MyType()!&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;Take a look through &lt;a href="https://github.com/elerch/eduSpring/blob/master/4%20-%20Debugging%20Web%20Applications/Web.config"&gt;web.config&lt;/a&gt; and &lt;a href="https://github.com/elerch/eduSpring/blob/master/4%20-%20Debugging%20Web%20Applications/spring.config"&gt;spring.config&lt;/a&gt; of the &lt;a href="https://github.com/elerch/eduSpring/tree/master/4%20-%20Debugging%20Web%20Applications"&gt;Debugging Web Applications&lt;/a&gt; project in the &lt;a href="https://github.com/elerch/eduSpring"&gt;eduSpring &lt;/a&gt;project on GitHub for troubleshooting examples. &amp;nbsp;There are several errors scattered throughout the two configuration files, and the errors are fully documented.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Setting up Spring.Net's verbose logging is also shown in the web.config. &amp;nbsp;You might notice that the actual project references do not include anything except standard ASP.NET DLLs. &amp;nbsp;Spring, Common Logging, and Log4Net must exist in the bin directory at run time, but no project references are actually required. &amp;nbsp;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.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-2366771614810546922?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/2366771614810546922/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=2366771614810546922" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/2366771614810546922?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/2366771614810546922?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/PQJkAKraz8c/eduspring-part-6-crazy-error-messages.html" title="EduSpring Part 6: Crazy Error Messages and What to do about them" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/eduspring-part-6-crazy-error-messages.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE4NRHk7fCp7ImA9WhZbEEs.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-6835875723355145129</id><published>2011-06-14T07:49:00.000-07:00</published><updated>2011-06-14T07:49:55.704-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-14T07:49:55.704-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EduSpring" /><title>EduSpring Part 5: Spring.Net in an ASP.NET environment (including MVC)</title><content type="html">This post is part of a &lt;a href="http://emilsblog.lerch.org/search/label/EduSpring"&gt;series &lt;/a&gt;on Spring.NET. I recommend starting at the beginning if you haven't already. &amp;nbsp;Also, I am walking through code in the &lt;a href="https://github.com/elerch/eduSpring"&gt;accompanying GitHub project&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
By now, you should have the basics of DI, IoC, and the benefits and drawbacks of the approach. &amp;nbsp;Now, I'll introduce you to the architecture of Spring.NET in an ASP.NET environment. &amp;nbsp;I'm sure a lot of other IoC frameworks operate in a similar manner. &amp;nbsp;If not, you can add code to make them work that way. ;-)&lt;br /&gt;
&lt;br /&gt;
If you look at the &lt;a href="https://github.com/elerch/eduSpring/tree/master/2%20-%20IocWithoutSpring"&gt;IocWithoutSpring &lt;/a&gt;project, you'll see this Main function:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;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&lt;idosomething&gt;("myObject");

            // This is what the ASP.NET Framework would do
            Console.WriteLine("The output is: " + service.DoTheWork());
        }
&lt;/idosomething&gt;&lt;/pre&gt;&lt;br /&gt;
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. &amp;nbsp;Ideally, we want our objects to be completely ignorant of this container, though. &amp;nbsp;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. &amp;nbsp;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. &amp;nbsp;Awesome!&lt;br /&gt;
&lt;br /&gt;
Now our Spring.Net dictionary is populated, assuming we have a valid configuration. &amp;nbsp;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. &amp;nbsp;The next question is, what about setting up dependencies in ASPX pages?&lt;br /&gt;
&lt;br /&gt;
Technically speaking, the ASP.NET framework parses an ASPX file (or MVC view) and code-generates a class. &amp;nbsp;On each request, it creates an instance of this class and allows it to process the request, before destroying the object. &amp;nbsp;Very stateless, but this creation and destruction of classes rubs against IoC's Dictionary&amp;lt;string,object&amp;gt; heart.&lt;br /&gt;
&lt;br /&gt;
If you &lt;a href="http://blogs.msdn.com/b/oldnewthing/archive/2008/05/28/8555658.aspx"&gt;read this contract from the other side&lt;/a&gt; (a.k.a. how would I solve this problem if I were writing Spring.Net), you can imagine yourself writing a&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ui.pagehandlerfactory.aspx"&gt;PageHandlerFactory&lt;/a&gt;&amp;nbsp;that&amp;nbsp;can deliver the aspx page class with dependencies already injected. &amp;nbsp;There are two problems you have to solve, however:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;What name do you use to look up the object?&lt;/li&gt;
&lt;li&gt;How do you deal with request-specific data?&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;The answer to #1 is relatively obvious if you look at the problem from the perspective of Spring. &amp;nbsp;The object doesn't really have a name, so we leave that blank, and the &lt;a href="http://msdn.microsoft.com/en-us/library/ms178116.aspx"&gt;virtual path&lt;/a&gt;&amp;nbsp;(~/page.aspx) is used as the type of the object since someone configuring the object will not know the type ASP.NET generates. &amp;nbsp;The actual type name needs to be figured out by Spring. &amp;nbsp;The answer to the second question runs a bit contrary to what I've been discussing so far.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;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. &amp;nbsp;However, there's no reason that the objects need to be created right away, nor do they have to be held in the dictionary. &amp;nbsp;In the case of this PageHandlerFactory, objects are created and configured at the time of the request, not at initialization. &amp;nbsp;However, dependencies follow the normal rules. &amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-6835875723355145129?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/6835875723355145129/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=6835875723355145129" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/6835875723355145129?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/6835875723355145129?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/wJXZ_Y65CXA/eduspring-part-5-springnet-in-aspnet.html" title="EduSpring Part 5: Spring.Net in an ASP.NET environment (including MVC)" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/eduspring-part-5-springnet-in-aspnet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cAQXo4cSp7ImA9WhZbEE8.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-3108598003762062848</id><published>2011-06-13T22:23:00.001-07:00</published><updated>2011-06-13T22:24:00.439-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-13T22:24:00.439-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EduSpring" /><title>EduSpring Part 4: What is so terribly broken with Dependency Injection?</title><content type="html">Move all the CS BS to the side. &amp;nbsp;This stuff doesn't work in the real world. &amp;nbsp;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. &amp;nbsp;And I'm talking about .Net specifically here, although I can throw the same stones at Java. &amp;nbsp;Most (but not all) other languages have the same problems I'll get on my soapbox about here.&lt;br /&gt;
&lt;br /&gt;
To do DI correctly, you have one of two options:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Your class has dependencies on properties/internal fields that implement Interfaces&lt;/li&gt;
&lt;li&gt;Your class has dependencies on properties/internal fields that implement base classes&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;In both cases, the contracts are relatively weak. &amp;nbsp;If you depend on a method that requires an object and returns an object, there are lots of things that can go wrong. &amp;nbsp;And you have no way of knowing whether it will go wrong unless an until you run it - compile time checks don't help. &amp;nbsp;Here's a short list of Murphy's law for a single method that takes an object parameter and returns an object:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Do you assume anything about the return value? &amp;nbsp;It might return what you expect, or might return null. &amp;nbsp;Or, it could throw an exception. &amp;nbsp;Generally, experience with DI will teach you good defensive coding, but it does take work...&lt;/li&gt;
&lt;li&gt;Can the method handle null input values? &amp;nbsp;If it errors, is it going to return null or throw an exception? &amp;nbsp;If it throws, what kind of exception will it generate?&lt;/li&gt;
&lt;li&gt;Is the method you're calling going to muck with the object you pass in? &amp;nbsp;If it does alter properties, is that a problem? &amp;nbsp;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?&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;Without some type of &lt;a href="http://en.wikipedia.org/wiki/Design_by_contract"&gt;design by contract&lt;/a&gt; construct built into your language of choice, these questions become just the tip of the iceberg. &amp;nbsp;Glancing through the Common Language Specification for .NET, it appears that there is no built-in construct available in the platform. &amp;nbsp;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. &amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Feel free to run through the Main method for FallaciesOfInterfaces for concrete examples of how Murphy can strike. &amp;nbsp;This project will compile, but will fail at almost every step. &amp;nbsp;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.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-3108598003762062848?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/3108598003762062848/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=3108598003762062848" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3108598003762062848?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3108598003762062848?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/3La6Od7tpII/eduspring-part-4-what-is-so-terribly.html" title="EduSpring Part 4: What is so terribly broken with Dependency Injection?" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/eduspring-part-4-what-is-so-terribly.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4ERHo9fip7ImA9WhZbEE8.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-2870415398713372575</id><published>2011-06-13T22:05:00.000-07:00</published><updated>2011-06-13T22:05:05.466-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-13T22:05:05.466-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EduSpring" /><title>EduSpring Part 3: What do we need an IoC for?</title><content type="html">This post is part of a &lt;a href="http://emilsblog.lerch.org/search/label/EduSpring"&gt;series &lt;/a&gt;on Spring.NET. I recommend starting at the beginning if you haven't already. &amp;nbsp;Also, I am walking through code in the &lt;a href="https://github.com/elerch/eduSpring"&gt;accompanying GitHub project&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Last time, I walked through why we might want to use dependency integration. &amp;nbsp;Outside the authentication example, here are a few other examples:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Authorization&lt;/li&gt;
&lt;li&gt;SMTP settings&lt;/li&gt;
&lt;li&gt;Payment gateways&lt;/li&gt;
&lt;li&gt;Business rules (rule engine style)&lt;/li&gt;
&lt;li&gt;Branding&lt;/li&gt;
&lt;/ul&gt;This time, I'd like to explore how an IoC container actually does its job. &amp;nbsp;By understanding how the IoC does its job, we can understand the value that it adds to our solutions. In the project "&lt;a href="https://github.com/elerch/eduSpring/tree/master/2%20-%20IocWithoutSpring"&gt;2 - IocWithoutSpring&lt;/a&gt;" on GitHub, you'll see a quick, hand-coded IoC container. &amp;nbsp;It's amazingly brilliant (insert sarcasm here) and also relatively close to what a real IoC container does (really). &amp;nbsp;Here is the IocContainer class in all it's glory:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;class IoCContainer
    {
        private readonly IDictionary&lt;string, object=""&gt; _allObjects = new Dictionary&lt;string, object=""&gt;();

        public T GetObject&lt;t&gt;(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());
        }
    }
&lt;/t&gt;&lt;/string,&gt;&lt;/string,&gt;&lt;/pre&gt;&lt;br /&gt;
Most IoC containers work in a similar manner.  There's some sort of initialization function, and there's some sort of GetObject method. &amp;nbsp;Internally, all it does is "new up" all the classes you've defined and shoves them in a global dictionary object. &amp;nbsp;The rest, as they say, is window dressing. &amp;nbsp;As you see in the comment, once you've built an IoC container, you can think of all kinds of cool things to do. &amp;nbsp;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? &amp;nbsp;What if you added the ability to set properties on the objects, not just create them? &amp;nbsp;How about the ability to create an object based on the state of another object (Spring calls this a factory method). &amp;nbsp;How about&amp;nbsp;defining&amp;nbsp;objects in one place, and values for properties in another? &amp;nbsp;IoC containers have all this stuff, and it's built for you...there's no reason to reinvent the wheel.&lt;br /&gt;
&lt;br /&gt;
But at the end of the day, remember: An IoC container, at its heart, is a Dictionary&amp;lt;string, object&amp;gt;. &amp;nbsp;And that's all, folks. &amp;nbsp;Another key thing to remember, especially in a stateless ASP.NET scenario, is that those objects exist during the lifetime of the application. &amp;nbsp;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.&lt;br /&gt;
&lt;br /&gt;
More goodies are in the &lt;a href="https://github.com/elerch/eduSpring/blob/master/2%20-%20IocWithoutSpring/IoCWithoutSpring.cs"&gt;main file&lt;/a&gt; if you read the comments, but I'll explore them more in depth in later posts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-2870415398713372575?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/2870415398713372575/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=2870415398713372575" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/2870415398713372575?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/2870415398713372575?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/4OmgM_EV7sI/eduspring-part-3-what-do-we-need-ioc.html" title="EduSpring Part 3: What do we need an IoC for?" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/eduspring-part-3-what-do-we-need-ioc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0YCQH85cCp7ImA9WhZbEEw.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-3090841857320215078</id><published>2011-06-13T17:25:00.000-07:00</published><updated>2011-06-13T17:26:01.128-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-13T17:26:01.128-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EduSpring" /><title>EduSpring Part 2: Simplifying dependencies</title><content type="html">&lt;a href="http://emilsblog.lerch.org/2011/06/eduspring-part-1-introduction.html"&gt;Last time&lt;/a&gt;, I introduced you to Spring, IoC, and Dependency Injection. &amp;nbsp;If you haven't read that post, please do. This time, I'll start walking through some of the code in the &lt;a href="https://github.com/elerch/eduSpring"&gt;accompanying GitHub project&lt;/a&gt;. &amp;nbsp;The code is organized by project in order of these posts. &amp;nbsp;Some conventions (specifically 1 class/file) have been ignored specifically to let the reader go through in a linear manner. &amp;nbsp;All projects are setup as console applications.&lt;br /&gt;
&lt;br /&gt;
This time, I'll tackle the first project, "0 - Advantages of DI". &amp;nbsp;This is one of the few projects I that will have more than one file to peruse. &amp;nbsp;The first file is a baseline...how we would solve a particular problem in a "traditional" procedural manner. &amp;nbsp;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. &amp;nbsp;If authentication fails, it will throw an exception. &amp;nbsp;Here is the class:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;/// &lt;summary&gt;
    /// Simulates a typical class
    /// &lt;/summary&gt;
    public class MyClass
    {
        /// &lt;summary&gt;
        /// Authentication provider.  We can't change this out for the production version 
        /// without changing source code and recompiling
        /// &lt;/summary&gt;
        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
        }
    }
&lt;/pre&gt;&lt;br /&gt;
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".  &lt;br /&gt;
&lt;br /&gt;
The main point here is that we have to remember to swap, and we'll have to recompile the application when we do that. &amp;nbsp;If we forget, anyone can log in with anything and we'll happily give up the goods. &amp;nbsp;Since everything has been "tested", it's likely we won't&amp;nbsp;thoroughly&amp;nbsp;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). &amp;nbsp;After deployment have two versions of the binary - one for production, and one outside production. &amp;nbsp;Who is to say there aren't any other changes in this code. &amp;nbsp;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. &amp;nbsp;But, it's simpler when we're coding it, isn't it?&lt;br /&gt;
&lt;br /&gt;
If we could just pass this dependency into MyClass, we'll be in much better shape. &amp;nbsp;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. &amp;nbsp;Enter the next file in this project - "1 - WithDependencyInjection.cs". &amp;nbsp;Here are the contents:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;/// &lt;summary&gt;
    /// Simulates a typical class
    /// &lt;/summary&gt;
    public class MyClassWithDependencyInjection
    {
        /// &lt;summary&gt;
        /// Authentication provider.  Because we use an interface, we no longer 
        /// need to change this code after it's been tested
        /// &lt;/summary&gt;
        private readonly IAuthenticate _authenticationProvider;

        /// &lt;summary&gt;
        /// 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.
        /// &lt;/summary&gt;
        /// &lt;param name="authProvider" /&gt;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
        }
    }

    /// &lt;summary&gt;
    /// 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
    /// &lt;/summary&gt;
    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" &amp;amp;&amp;amp; password.StringEquals("bar"))
                return new GenericPrincipal(new GenericIdentity(user), new string[] { });
            return new GenericPrincipal(new GenericIdentity(""), new string[] { }); ;
        }
    }

&lt;/pre&gt;&lt;br /&gt;
Here, we've done the following things:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Introduced an interface for authentication and marked both providers as implementing the interface. &amp;nbsp;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.&lt;/li&gt;
&lt;li&gt;Introduced a parameterized constructor for the main class. &amp;nbsp;Now this class lets the world know that it can't do it's job without a way to authenticate. &amp;nbsp;And it doesn't care how the authentication gets done, just that it &lt;b&gt;can&lt;/b&gt;&amp;nbsp;authenticate.&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;Back in the main program, we can now (sort of) demonstrate what we've done. &amp;nbsp;Obviously without changing the code we can't demonstrate changing the provider for MyClass, but we can demonstrate the DI approach to the problem:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre class="brush:csharp"&gt;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"));
        }
&lt;/pre&gt;&lt;br /&gt;
With dependency injection techniques, the caller can decide the authentication mechanism. &amp;nbsp;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. &amp;nbsp;These are passed into the constructor for the DI class, and voilà, we can change the way authentication works. &amp;nbsp;In the last two lines, I show how we can even pass in the type name via the command line. &amp;nbsp;Now, for the first time, we have the ability to change the way we authenticate without changing code.&lt;br /&gt;
&lt;br /&gt;
...and that, folks, is all an IoC container is about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-3090841857320215078?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/3090841857320215078/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=3090841857320215078" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3090841857320215078?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3090841857320215078?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/MxKBnwEu2LA/eduspring-part-2-simplifying.html" title="EduSpring Part 2: Simplifying dependencies" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/eduspring-part-2-simplifying.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkANQX4zcCp7ImA9WhZbEE0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-4160947607829149973</id><published>2011-06-13T16:46:00.000-07:00</published><updated>2011-06-13T16:46:30.088-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-13T16:46:30.088-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="EduSpring" /><title>EduSpring Part 1: Introduction</title><content type="html">I get quite a few questions about &lt;a href="http://springframework.net/"&gt;Spring.Net&lt;/a&gt;, 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.&lt;br /&gt;
&lt;br /&gt;
A lot of this material will &lt;b&gt;not&lt;/b&gt; be specific to Spring.Net, but rather &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency Injection&lt;/a&gt; generally. &amp;nbsp;To understand Spring.Net, you must be familiar with &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;Inversion of Control&lt;/a&gt; and Dependency Injection. &amp;nbsp;You can read about them on Wikipedia, but here's a short summary:&lt;br /&gt;
&lt;br /&gt;
Inversion of Control: Flow of control of a system is inverted in comparison to procedural programming&lt;br /&gt;
Dependency Injection: A specific technique to achieve inversion of control with respect to dependencies&lt;br /&gt;
&lt;br /&gt;
What this means in layman's terms is that instead of a program:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Starts up&lt;/li&gt;
&lt;li&gt;Creating new services for whatever needs to be done&lt;/li&gt;
&lt;li&gt;Using the services/doing the work&lt;/li&gt;
&lt;li&gt;Disposing of the services and returning the results&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;The program now does only what it's responsible. &amp;nbsp;Namely:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Starts up&lt;/li&gt;
&lt;li&gt;Uses services that have been configured for its use/does the work&lt;/li&gt;
&lt;li&gt;Returns the results&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;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.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The devil in these particular details are in #2. &amp;nbsp;How does one create and configure services for a program? &amp;nbsp;We can code this by hand, but it's a lot of boring glue code, and doing it right is incredibly difficult. &amp;nbsp;Enter the &lt;a href="http://www.martinfowler.com/articles/injection.html"&gt;IoC container&lt;/a&gt; - a piece of pre-built code that will do this work for us. &amp;nbsp;Depending on the application, we don't even need to use the container&amp;nbsp;explicitly. &amp;nbsp;In a system like &lt;a href="http://www.asp.net/"&gt;ASP.NET&lt;/a&gt;, we can use &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.ihttpmodule.aspx"&gt;HttpModules &lt;/a&gt;to intercept requests and wire dependencies automatically.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;One significant problem with this approach are the complexity of configuration. &amp;nbsp;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. &amp;nbsp;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. &amp;nbsp;With flexibility comes complexity.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Another issue is a fundamental problem with .NET (C# and VB and I believe all .NET classes adhering to the &lt;a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf"&gt;CLI&lt;/a&gt;). &amp;nbsp;Interfaces are incomplete contracts. &amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;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). &amp;nbsp;Also, no &lt;a href="http://forum.springframework.net/showthread.php?t=6875"&gt;Mono support&lt;/a&gt; exists as of this writing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Next up - some walkthrough code.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-4160947607829149973?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/4160947607829149973/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=4160947607829149973" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/4160947607829149973?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/4160947607829149973?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/mKQUMXZ0G_w/eduspring-part-1-introduction.html" title="EduSpring Part 1: Introduction" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/eduspring-part-1-introduction.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcMQn0zeyp7ImA9WhZUE0k.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-412853243596369468</id><published>2011-06-05T23:01:00.000-07:00</published><updated>2011-06-05T23:01:23.383-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-05T23:01:23.383-07:00</app:edited><title>Total application design: circa 2011</title><content type="html">Working with a few recent projects I'm getting pretty close to a nice boilerplate for a "standard" web application built with the latest technologies. &amp;nbsp;Subject to client restraints, here's the stack:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;UI and middle tier:&amp;nbsp;&lt;a href="http://www.asp.net/mvc"&gt;ASP.NET MVC3&lt;/a&gt; (using VS2010 SP1). &amp;nbsp;Note that this requires .NET 4, which has some nice features (I love Tuples) but I don't think is completely necessary otherwise. &amp;nbsp;SP1 is important, which I'll mention later. &amp;nbsp;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. &amp;nbsp;Razor view engine is used, and templates are updated to mirror &lt;a href="http://html5boilerplate.com/"&gt;Html5Boilerplate.com&lt;/a&gt;'s templates. jQuery is applied unobtrusively.&lt;/li&gt;
&lt;li&gt;Data access: &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt;. &amp;nbsp;This is integrated in such a way that depending on your needs, you don't need to add a direct reference to it, though. &amp;nbsp;References are needed for access to NHibernate advanced queries and the Linq provider.&lt;/li&gt;
&lt;li&gt;URL Rewriting: &lt;a href="http://urlrewriter.net/"&gt;UrlRewriter.Net&lt;/a&gt;. This is used for css/js versioning. &amp;nbsp;A &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.urlhelper.aspx"&gt;URLHelper&lt;/a&gt; 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. &amp;nbsp;We probably could use MVC3 routes here, but it seems overkill for something that could be handled by simple Url rewriting.&lt;/li&gt;
&lt;li&gt;Dependency Injection: &lt;a href="http://www.springframework.net/"&gt;Spring.net&lt;/a&gt;. &amp;nbsp;Any DI/IOC container would work here. &amp;nbsp;Again, the integration with spring is very lightweight and easily replaceable. &amp;nbsp;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.&lt;/li&gt;
&lt;li&gt;Other tools: &lt;a href="http://www.dotlesscss.org/"&gt;Dotless&lt;/a&gt;&amp;nbsp;is used in a development-time capacity to generate CSS, with &lt;a href="http://chirpy.codeplex.com/"&gt;Chirpy&lt;/a&gt;&amp;nbsp;(&lt;a href="https://hg01.codeplex.com/forks/etlerch/directorybasedsettingswithinchirp"&gt;customized&lt;/a&gt;) to keep the development experience smooth. &amp;nbsp;A handful of other custom DLLs and build tools keep the project structure relatively vanilla. &amp;nbsp;&lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt; is used for continuous integration.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;I'm putting together a NuGet package with this build. &amp;nbsp;When this is complete, I'll post an update.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Other technologies/tools on the radar are &lt;a href="http://msdn.microsoft.com/en-us/library/aa697427(v=vs.80).aspx"&gt;Entity Framework&lt;/a&gt; (NHibernate replacement) and &lt;a href="http://www.castleproject.org/"&gt;Castle Windsor&lt;/a&gt; (IoC container that supports Mono). &amp;nbsp;&lt;a href="http://www.dotnetopenauth.net/"&gt;DotNetOpenAuth&lt;/a&gt; is under consideration as a standard way to pull in authentication and authorization functions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-412853243596369468?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/412853243596369468/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=412853243596369468" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/412853243596369468?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/412853243596369468?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/k4tUkfuPCC4/total-application-design-circa-2011.html" title="Total application design: circa 2011" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/06/total-application-design-circa-2011.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUACQH8zeSp7ImA9WhZSFEw.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-6444719285601826954</id><published>2011-03-29T08:48:00.001-07:00</published><updated>2011-03-29T08:49:21.181-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-29T08:49:21.181-07:00</app:edited><title>Supporting Multiple Databases in Applications</title><content type="html">&lt;p&gt;In general, having a persistence-ignorant application provides a lot of flexibility.&amp;#160; 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.&lt;/p&gt;  &lt;p&gt;As any write once, run anywhere scheme, support for multiple databases can be notoriously difficult.&amp;#160; Consider the following SQL Server T-SQL code:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://content.screencast.com/users/EmilT/folders/Jing/media/26d80b2f-5e0f-4bdf-9593-45d0d13116f6/Table%20name%20sensitivity.png" /&gt;&lt;/p&gt;  &lt;p&gt;Wait…what?&amp;#160; I just created FOO, yet SQL Server is telling me that the table foo doesn’t exist.&amp;#160; What’s going on?&amp;#160; In this case, the database &lt;a href="http://msdn.microsoft.com/en-us/library/ms175835.aspx"&gt;default collation&lt;/a&gt; has been changed to Latin1_General_Bin, a binary collation, so FOO != ‘foo’.&amp;#160; As a result, the following query also provides no results:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://content.screencast.com/users/EmilT/folders/Jing/media/05da1fbf-2a14-4701-85c3-4edcbbb451d6/Case%20sensitivity%20at%20data%20level.png" /&gt;&lt;/p&gt;  &lt;p&gt;To get any data back from this table, we need to match exactly:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://content.screencast.com/users/EmilT/folders/Jing/media/03b2cdc1-7848-4cd4-91cb-41a3867ff38a/Sucess.png" /&gt;&lt;/p&gt;  &lt;p&gt;Great, so I’ve jacked the default installation collation in SQL Server.&amp;#160; Not a lot of people or organizations do this?&amp;#160; But…is this an academic exercise?&amp;#160; If you want to support multiple databases and clients, the answer is a resounding NO.&amp;#160; Consider:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Some organizations may want the application to work on a database with binary collation.&amp;#160; Rare, but it could happen. &lt;/li&gt;    &lt;li&gt;Organizations might be using another database, and not all databases are case insensitive, even by default. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;If you want a portable application, #2 is your much more concerning issue.&amp;#160; Recently I verified default installations on a number of popular database systems to determine what behavior they produced.&amp;#160; Here are my findings (in alphabetical order):&lt;/p&gt; &lt;center&gt;   &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="133"&gt;           &lt;p align="left"&gt;&lt;/p&gt;         &lt;/td&gt;          &lt;td valign="top" width="149"&gt;Table/Column Names&lt;/td&gt;          &lt;td valign="top" width="117"&gt;Data&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="133"&gt;Oracle&lt;/td&gt;          &lt;td valign="top" width="149"&gt;Insensitive&lt;/td&gt;          &lt;td valign="top" width="117"&gt;&lt;font style="background-color: #ffc000"&gt;Sensitive&lt;/font&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="133"&gt;Postgres&lt;/td&gt;          &lt;td valign="top" width="149"&gt;Insensitive&lt;/td&gt;          &lt;td valign="top" width="117"&gt;&lt;font style="background-color: #ffc000"&gt;Sensitive&lt;/font&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="133"&gt;MySQL&lt;/td&gt;          &lt;td valign="top" width="149"&gt;&lt;font style="background-color: #ffc000"&gt;Sensitive&lt;/font&gt;&lt;/td&gt;          &lt;td valign="top" width="117"&gt;Insensitive&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="133"&gt;SQLLite&lt;/td&gt;          &lt;td valign="top" width="149"&gt;Insensitive&lt;/td&gt;          &lt;td valign="top" width="117"&gt;&lt;font style="background-color: #ffc000"&gt;Sensitive&lt;/font&gt;&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="133"&gt;SQL Server&lt;/td&gt;          &lt;td valign="top" width="149"&gt;Insensitive&lt;/td&gt;          &lt;td valign="top" width="117"&gt;Insensitive&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/center&gt;  &lt;p&gt;The most curious finding is MySQL.&amp;#160; 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.&amp;#160; In any case, programming for the least common denominator requires handling these situations.&amp;#160; &lt;/p&gt;  &lt;p&gt;Ideally you’d leave the SQL to an ORM.&amp;#160; 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.&amp;#160; If you’re application absolutely must have a generic data layer, though, you must keep this in mind as part of design.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-6444719285601826954?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/6444719285601826954/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=6444719285601826954" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/6444719285601826954?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/6444719285601826954?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/Kw1tUdjf0Vc/supporting-multiple-databases-in.html" title="Supporting Multiple Databases in Applications" /><author><name>Emil</name><uri>http://www.blogger.com/profile/13948666821294274991</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://2.bp.blogspot.com/_Blx5Kapkixs/TImg-8ELCdI/AAAAAAAAAAM/nJB5PGpyjC8/S220/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2011/03/supporting-multiple-databases-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcEQXY-fip7ImA9WxBaEks.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-5480483349099059196</id><published>2010-03-22T07:10:00.000-07:00</published><updated>2010-03-22T07:10:00.856-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-22T07:10:00.856-07:00</app:edited><title>Batch uploading RDL files to SQL Server Reporting Services 2005</title><content type="html">There 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/&lt;br /&gt;
&lt;br /&gt;
The executable is available here:  http://bitbucket.org/emil/bulk-rdl-uploader-for-ssrs-reports/downloads/ReportingServicesBatchUpload.exe&lt;br /&gt;
&lt;br /&gt;
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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-5480483349099059196?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/5480483349099059196/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=5480483349099059196" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/5480483349099059196?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/5480483349099059196?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/eQ4kowm9vHU/batch-uploading-rdl-files-to-sql-server.html" title="Batch uploading RDL files to SQL Server Reporting Services 2005" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2010/03/batch-uploading-rdl-files-to-sql-server.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQBSHY_eip7ImA9WxBbEkk.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-8933765719974870314</id><published>2010-03-09T08:51:00.000-08:00</published><updated>2010-03-10T08:59:19.842-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-10T08:59:19.842-08:00</app:edited><title>Working with a feature branch in Subversion (TortoiseSVN on Windows)</title><content type="html">Branching and merging is one of the most nerve-racking activities for people working with Subversion.&amp;nbsp; Unlike Mercurial and other DVCS where branching and merging is commonplace, typical workflows in Subversion do not include this activity.&amp;nbsp; 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.&amp;nbsp; That, of course, is the exact opposite of what we need when working on an important design spike or critical new feature.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;Conceptually, what we want with a design spike or large new feature is to:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Create a new branch for the change&lt;/li&gt;
&lt;li&gt;Work in the new branch, committing early and often&lt;/li&gt;
&lt;li&gt;Periodically pull in (merge) the changes from the project trunk&lt;/li&gt;
&lt;li&gt;When complete, reintegrate the branch into the trunk&lt;/li&gt;
&lt;/ul&gt;For these instructions, I assume that you have a subversion repository checked out and you're actively working on the trunk.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Creating a new branch:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/__qN00uIxfHI/S5Z1YMVQxGI/AAAAAAAAAPE/egW-piuGjoM/s1600-h/Magical+Snap+-+2010.03.09+08.17+-+003.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/__qN00uIxfHI/S5Z1YMVQxGI/AAAAAAAAAPE/egW-piuGjoM/s400/Magical+Snap+-+2010.03.09+08.17+-+003.png" width="342" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;&amp;nbsp;Right-click on the directory you want to branch.&amp;nbsp; Pick the Branch/Tag operation.&lt;/li&gt;
&lt;li&gt;On the branch/tag screen, enter a new branch (typically the repository has a /branches folder as well as a /trunk folder).&amp;nbsp; The new branch is typically /branches/&lt;i&gt;mynewbranch&lt;/i&gt;, where the branch name itself is a folder that does not exist in the repository.&lt;/li&gt;
&lt;li&gt;In this scenario, you will also want to choose "switch working copy to new branch/tag".&amp;nbsp; 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.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S5Z2y82KyVI/AAAAAAAAAPM/1mohp4XwIX8/s1600-h/Magical+Snap+-+2010.03.09+08.22+-+004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/__qN00uIxfHI/S5Z2y82KyVI/AAAAAAAAAPM/1mohp4XwIX8/s640/Magical+Snap+-+2010.03.09+08.22+-+004.png" width="587" /&gt;&lt;/a&gt;&lt;/div&gt;&amp;nbsp;At this point you'll want to take note of the revision number that had the last changes.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Work in the new branch, committing early and often&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This is standard subversion behavior.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Periodically pull in (merge) the changes from the project trunk&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You'll want to keep track of the last revision you've pulled changes from.&amp;nbsp; In the beginning, this revision number is the revision that represented the branch itself.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S5Z4Xhlrw6I/AAAAAAAAAPU/oA-GM7y9dSU/s1600-h/Magical+Snap+-+2010.03.09+08.32+-+005.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/__qN00uIxfHI/S5Z4Xhlrw6I/AAAAAAAAAPU/oA-GM7y9dSU/s400/Magical+Snap+-+2010.03.09+08.32+-+005.png" width="345" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt; Pick the Merge tool off the TortoiseSVN menu.&lt;/li&gt;
&lt;li&gt;Choose the "Merge a range of revisions" from the first screen of the wizard.&lt;/li&gt;
&lt;li&gt;In the "URL to merge from", choose the trunk.&lt;/li&gt;
&lt;li&gt;In the Revision range to merge, the best approach is to be precise.&amp;nbsp; 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).&amp;nbsp; You can leave this blank, but we want to avoid merging a change twice.&amp;nbsp; You may need to look at the log to help find the right revisions.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/__qN00uIxfHI/S5Z5qeaCiYI/AAAAAAAAAPc/gGYT22UnQPI/s1600-h/Magical+Snap+-+2010.03.09+08.37+-+006.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="588" src="http://4.bp.blogspot.com/__qN00uIxfHI/S5Z5qeaCiYI/AAAAAAAAAPc/gGYT22UnQPI/s640/Magical+Snap+-+2010.03.09+08.37+-+006.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;Hit next and do a test merge just to be sure before performing the actual merge.&amp;nbsp; All other settings can be left at their defaults.&amp;nbsp; 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.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Reintegrate the branch into the trunk&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/__qN00uIxfHI/S5Z75jgC2eI/AAAAAAAAAPk/gHPDaqLeWXM/s1600-h/Magical+Snap+-+2010.03.09+08.47+-+007.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/__qN00uIxfHI/S5Z75jgC2eI/AAAAAAAAAPk/gHPDaqLeWXM/s400/Magical+Snap+-+2010.03.09+08.47+-+007.png" width="343" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;Commit all branch changes&lt;/li&gt;
&lt;li&gt; Switch the working directory back to the trunk.&amp;nbsp; This is done via the TortoiseSVN switch command.&lt;/li&gt;
&lt;li&gt;Pick the Merge command off the TortoiseSVN menu as before.&amp;nbsp; This time, however, we'll pick the "Reintegrate a branch" option.&lt;/li&gt;
&lt;li&gt;In the "From URL" field, put the URL to the branch you've finished working on.&lt;/li&gt;
&lt;li&gt;Test the merge and if happy, perform the merge, test the changes, and commit to the trunk.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/__qN00uIxfHI/S5Z8VLMaQaI/AAAAAAAAAPs/pkv6bpBCZH0/s1600-h/Magical+Snap+-+2010.03.09+08.48+-+008.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="587" src="http://3.bp.blogspot.com/__qN00uIxfHI/S5Z8VLMaQaI/AAAAAAAAAPs/pkv6bpBCZH0/s640/Magical+Snap+-+2010.03.09+08.48+-+008.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br clear="all"/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-8933765719974870314?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/8933765719974870314/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=8933765719974870314" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8933765719974870314?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8933765719974870314?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/k6lr1RZswLk/working-with-feature-branch-in.html" title="Working with a feature branch in Subversion (TortoiseSVN on Windows)" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/__qN00uIxfHI/S5Z1YMVQxGI/AAAAAAAAAPE/egW-piuGjoM/s72-c/Magical+Snap+-+2010.03.09+08.17+-+003.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2010/03/working-with-feature-branch-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8FQ3wzeSp7ImA9WxBUEUk.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-8365634077393367230</id><published>2010-02-25T17:39:00.000-08:00</published><updated>2010-02-25T17:46:52.281-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-25T17:46:52.281-08:00</app:edited><title>Spring.Net-enabled WCF Services available from Microsoft Ajax</title><content type="html">&lt;div class="separator" style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S4chK-qlupI/AAAAAAAAAN8/G1D9eAenni0/s1600-h/Magical+Snap+-+2010.02.25+16.58+-+005.png" imageanchor="1" style="float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/__qN00uIxfHI/S4chK-qlupI/AAAAAAAAAN8/G1D9eAenni0/s320/Magical+Snap+-+2010.02.25+16.58+-+005.png" /&gt;&lt;/a&gt;&lt;/div&gt;Implementing Spring.NET WCF services is fairly straightforward.&lt;br /&gt;
&lt;br /&gt;
Implementing MS Ajax WCF services is also straightforward, if you pick the right New Item to add from Visual Studio.&lt;br /&gt;
&lt;br /&gt;
The complication comes in when you want a Spring.NET WCF service that handles calls from Microsoft Ajax controls.&amp;nbsp; This method will let you add them.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
Step 1. Add new "Ajax-Enabled WCF Service"&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S4chMWzTilI/AAAAAAAAAOE/x-zS6CEyYg8/s1600-h/Magical+Snap+-+2010.02.25+16.59+-+006.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="420" src="http://2.bp.blogspot.com/__qN00uIxfHI/S4chMWzTilI/AAAAAAAAAOE/x-zS6CEyYg8/s640/Magical+Snap+-+2010.02.25+16.59+-+006.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Step 2. Create your methods, test and make sure all base functionality  is working.&amp;nbsp; This sample is for a CascadingDropDown control from the  Ajax Control Toolkit, but any control will work.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S4chNb3jWhI/AAAAAAAAAOM/Vz3cQkStdt8/s1600-h/Magical+Snap+-+2010.02.25+17.03+-+007.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="305" src="http://2.bp.blogspot.com/__qN00uIxfHI/S4chNb3jWhI/AAAAAAAAAOM/Vz3cQkStdt8/s640/Magical+Snap+-+2010.02.25+17.03+-+007.png" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/__qN00uIxfHI/S4chOmV5CfI/AAAAAAAAAOU/NsiEF8_UBb0/s1600-h/Magical+Snap+-+2010.02.25+17.06+-+011.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/__qN00uIxfHI/S4chOmV5CfI/AAAAAAAAAOU/NsiEF8_UBb0/s320/Magical+Snap+-+2010.02.25+17.06+-+011.png" /&gt;&lt;/a&gt;&lt;/div&gt;Step 3. Introduce an interface to use for the methods.&amp;nbsp; Spring.Net requires an interface, and this is the crux of the problem.&amp;nbsp; Here I've created IMyAjaxService.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;Step 4. Move the [ServiceContract(Namespace = "")] from the class to the interface&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/__qN00uIxfHI/S4chPblMOfI/AAAAAAAAAOc/1M_DMkG6_0k/s1600-h/Magical+Snap+-+2010.02.25+17.09+-+012.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="188" src="http://3.bp.blogspot.com/__qN00uIxfHI/S4chPblMOfI/AAAAAAAAAOc/1M_DMkG6_0k/s640/Magical+Snap+-+2010.02.25+17.09+-+012.png" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: left;"&gt;Step 5. Move the [OperationContract] tags from the methods on the class to the interface method definitions&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&amp;nbsp;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S4chRiyigbI/AAAAAAAAAOk/pXvXay7WAjc/s1600-h/Magical+Snap+-+2010.02.25+17.10+-+013.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="404" src="http://2.bp.blogspot.com/__qN00uIxfHI/S4chRiyigbI/AAAAAAAAAOk/pXvXay7WAjc/s640/Magical+Snap+-+2010.02.25+17.10+-+013.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;
&lt;/div&gt;Step 6. Change web.config endpoint contract (xpath = /configuration/system.serviceModel/services/service/endpoint) to reference the interface&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/__qN00uIxfHI/S4chUQHHrkI/AAAAAAAAAO0/fRytnTrj4zU/s1600-h/Magical+Snap+-+2010.02.25+17.13+-+015.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="252" src="http://2.bp.blogspot.com/__qN00uIxfHI/S4chUQHHrkI/AAAAAAAAAO0/fRytnTrj4zU/s640/Magical+Snap+-+2010.02.25+17.13+-+015.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Step 7: Test.  The test should work, without dependency injection from Spring.Net.&amp;nbsp; Now we have a WCF service that responds to Ajax, but has the interface definitions just the way Spring likes them.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;u&gt;&lt;span style="font-size: large;"&gt;Wiring in Spring&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;&lt;br /&gt;
For Spring.NET to handle WCF, you need .NET 3.0 or higher, and you need Spring.Net 1.3.0 or higher.&amp;nbsp; You'll need the following DLLs available for binding (either your bin directory or the GAC):&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Spring.Core.dll from the 2.0 folder&lt;/li&gt;
&lt;li&gt;Spring.Web.dll from the 2.0 folder&lt;/li&gt;
&lt;li&gt;Spring.Services.dll from the 3.0 folder&lt;/li&gt;
&lt;/ul&gt;In the Service you've created, edit the markup and add Factory="Spring.ServiceModel.Activation.ServiceHostFactory" onto the end, like so:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/__qN00uIxfHI/S4chVg7RJAI/AAAAAAAAAO8/b26ihrR-aE8/s1600-h/Magical+Snap+-+2010.02.25+17.14+-+016.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="76" src="http://1.bp.blogspot.com/__qN00uIxfHI/S4chVg7RJAI/AAAAAAAAAO8/b26ihrR-aE8/s640/Magical+Snap+-+2010.02.25+17.14+-+016.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;This will get Spring.Net into the activation pipeline for the service.&lt;br /&gt;
&lt;br /&gt;
Lastly, you'll add the new object to spring configuration.&amp;nbsp; It is &lt;span style="background-color: white;"&gt;CRITICAL that the OBJECT ID MATCH THE SERVICE NAME FROM WEB.CONFIG.&amp;nbsp; The Spring.Net documentation mentions this, but I don't think they mention it very loudly.&amp;nbsp; The type information is exactly as you'd expect: the type for the WCF service class.&lt;/span&gt;&lt;br /&gt;
&lt;span style="background-color: white;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
Also CRITICAL:&amp;nbsp; Add singleton="false" to the object definition for Spring for your new object&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-8365634077393367230?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/8365634077393367230/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=8365634077393367230" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8365634077393367230?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8365634077393367230?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/rSjqEEBhOow/springnet-enabled-wcf-services.html" title="Spring.Net-enabled WCF Services available from Microsoft Ajax" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/__qN00uIxfHI/S4chK-qlupI/AAAAAAAAAN8/G1D9eAenni0/s72-c/Magical+Snap+-+2010.02.25+16.58+-+005.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2010/02/springnet-enabled-wcf-services.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EBSHs9cSp7ImA9WxNXEkg.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-5230259800923942844</id><published>2009-07-08T22:50:00.001-07:00</published><updated>2009-09-29T13:20:59.569-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-29T13:20:59.569-07:00</app:edited><title>Intermittent Operation Aborted Errors in IE when using MS Ajax</title><content type="html">This 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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;First post with background: &lt;a href="http://seejoelprogram.wordpress.com/2008/06/08/when-sysapplicationinitialize-causes-operation-aborted-in-ie/"&gt;http://seejoelprogram.wordpress.com/2008/06/08/when-sysapplicationinitialize-causes-operation-aborted-in-ie/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Second post with bug fixes to the original bug fix: &lt;a href="http://www.blogger.com/post-create.g?blogID=6692354#%20http://seejoelprogram.wordpress.com/2008/10/03/fixing-sysapplicationinitialize-again/"&gt;http://seejoelprogram.wordpress.com/2008/10/03/fixing-sysapplicationinitialize-again/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Sys$_Application$initialize:&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt; function Sys$_Application$initialize() {&lt;br /&gt;     if(!this._initialized &amp;&amp; !this._initializing) {&lt;br /&gt;         this._initializing = true;&lt;br /&gt;         var u = window.navigator.userAgent.toLowerCase(),&lt;br /&gt;             v = parseFloat(u.match(/.+(?:rv|it|ml|ra|ie)[\/: ]([\d.]+)/)[1]);&lt;br /&gt;&lt;br /&gt;         var initializeDelegate = Function.createDelegate(this, this._doInitialize);&lt;br /&gt;&lt;br /&gt;         if (/WebKit/i.test(u) &amp;&amp; v &lt; 525.13)&lt;br /&gt;         {&lt;br /&gt;             this._load_timer = window.setInterval(function()&lt;br /&gt;             {&lt;br /&gt;                 if (/loaded|complete/.test(document.readyState))&lt;br /&gt;                 {&lt;br /&gt;                     initializeDelegate();&lt;br /&gt;                 }&lt;br /&gt;             }, 10);&lt;br /&gt;         }&lt;br /&gt;         else if (/msie/.test(u) &amp;&amp; !window.opera)&lt;br /&gt;         {&lt;br /&gt;             document.attachEvent('onreadystatechange',&lt;br /&gt;                 function (e) {&lt;br /&gt;                     if (e &amp;&amp; arguments.callee &amp;&amp; document.readyState == 'complete') {&lt;br /&gt;                         document.detachEvent('on'+e.type, arguments.callee);&lt;br /&gt;                         initializeDelegate();&lt;br /&gt;                     }&lt;br /&gt;                 }&lt;br /&gt;             );&lt;br /&gt;             if (window == top) {&lt;br /&gt;                 (function () {&lt;br /&gt;                     try {&lt;br /&gt;                         document.documentElement.doScroll('left');&lt;br /&gt;                     } catch (e) {&lt;br /&gt;                         setTimeout(arguments.callee, 10);&lt;br /&gt;                         return;&lt;br /&gt;                     }&lt;br /&gt;                     initializeDelegate();&lt;br /&gt;                 })();&lt;br /&gt;             }&lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;         else if (document.addEventListener&lt;br /&gt;             &amp;&amp;  ((/opera\//.test(u) &amp;&amp; v &gt; 9) ||&lt;br /&gt;                 (/gecko\//.test(u) &amp;&amp; v &gt;= 1.8) ||&lt;br /&gt;                 (/khtml\//.test(u) &amp;&amp; v &gt;= 4.0) ||&lt;br /&gt;                 (/webkit\//.test(u) &amp;&amp; v &gt;= 525.13))) {&lt;br /&gt;             document.addEventListener("DOMContentLoaded", initializeDelegate, false);&lt;br /&gt;         }&lt;br /&gt;         else&lt;br /&gt;         {&lt;br /&gt;             $addHandler(window, "load", initializeDelegate);&lt;br /&gt;         }&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Sys$_Application$_doInitialize():&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt; function Sys$_Application$_doInitialize() {&lt;br /&gt;   if (this._initialized) {&lt;br /&gt;    return;&lt;br /&gt;   }&lt;br /&gt;   Sys._Application.callBaseMethod(this, 'initialize');&lt;br /&gt;   if (this._load_timer !== null)&lt;br /&gt;   {&lt;br /&gt;    clearInterval(this._load_timer);&lt;br /&gt;    this._load_timer = null;&lt;br /&gt;   }&lt;br /&gt;   var handler = this.get_events().getHandler("init");&lt;br /&gt;   if (handler) {&lt;br /&gt;    this.beginCreateComponents();&lt;br /&gt;    handler(this, Sys.EventArgs.Empty);&lt;br /&gt;    this.endCreateComponents();&lt;br /&gt;   }&lt;br /&gt;   if (Sys.WebForms) {&lt;br /&gt;    if (this._onPageRequestManagerBeginRequest) this._beginRequestHandler = Function.createDelegate(this, this._onPageRequestManagerBeginRequest);&lt;br /&gt;    if (this._beginRequestHandler) Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._beginRequestHandler);&lt;br /&gt;    if (this._onPageRequestManagerEndRequest) this._endRequestHandler = Function.createDelegate(this, this._onPageRequestManagerEndRequest);&lt;br /&gt;    if (this._endRequestHandler) Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._endRequestHandler);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   if (this.get_stateString){&lt;br /&gt;    var loadedEntry = this.get_stateString();&lt;br /&gt;    if (loadedEntry !== this._currentEntry) {&lt;br /&gt;     this._navigate(loadedEntry);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   this.raiseLoad();&lt;br /&gt;   this._initializing = false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Sys$_Application$_loadHandler():&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt; function Sys$_Application$_loadHandler() {&lt;br /&gt;  if(this._loadHandlerDelegate) {&lt;br /&gt;   Sys.UI.DomEvent.removeHandler(window, "load", this._loadHandlerDelegate);&lt;br /&gt;   this._loadHandlerDelegate = null;&lt;br /&gt;  }&lt;br /&gt;  this._initializing = true;&lt;br /&gt;  this._doInitialize();&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Next, here is how I overrode how the framework delivers the script:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;  &amp;lt;ajaxtoolkit:toolkitscriptmanager runat=&amp;quot;server&amp;quot; enablepartialrendering=&amp;quot;true&amp;quot; id=&amp;quot;ScriptManager&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;scripts&amp;gt;&lt;br /&gt;           &amp;lt;asp:scriptreference name=&amp;quot;MicrosoftAjax.js&amp;quot; assembly=&amp;quot;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; path=&amp;quot;~/js/MicrosoftAjax-withFix.js&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;/scripts&amp;gt;&lt;br /&gt;  &amp;lt;/ajaxToolkit:ToolkitScriptManager&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You do not need to use the ToolKitScriptManager - you can also do it this way:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;   &amp;lt;asp:scriptmanager runat=&amp;quot;server&amp;quot; enablepartialrendering=&amp;quot;true&amp;quot; id=&amp;quot;ScriptManager&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;scripts&amp;gt;&lt;br /&gt;&amp;lt;asp:scriptreference name=&amp;quot;MicrosoftAjax.js&amp;quot; assembly=&amp;quot;System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35&amp;quot; path=&amp;quot;~/js/MicrosoftAjax-withFix.js&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;/scripts&amp;gt;&lt;br /&gt;   &amp;lt;/asp:ScriptManager&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that you can replace ~/js with the directory of your choosing.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;If you don't want to bother incorporating these fixes into .NET 3.5 SP1 Ajax files, feel free to download them from here:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Debug version: &lt;a href="http://lerch.org/js/MicrosoftAjax-WithFix.debug.js"&gt;http://lerch.org/js/MicrosoftAjax-WithFix.debug.js&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Release version (simply a minified version of the  debug js - run through &lt;a href="http://developer.yahoo.com/yui/compressor/"&gt;YUI Compresssor&lt;/a&gt;): &lt;a href="http://lerch.org/js/MicrosoftAjax-WithFix.release.js"&gt;http://lerch.org/js/MicrosoftAjax-WithFix.release.js&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-5230259800923942844?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/5230259800923942844/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=5230259800923942844" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/5230259800923942844?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/5230259800923942844?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/cHElA_26RXU/intermittent-operation-aborted-errors.html" title="Intermittent Operation Aborted Errors in IE when using MS Ajax" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2009/07/intermittent-operation-aborted-errors.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQCQ305eCp7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-4944090063865517807</id><published>2009-07-07T10:56:00.001-07:00</published><updated>2009-07-07T13:59:22.320-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T13:59:22.320-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><title>Javascript Hacks: Using XHR to load binary data</title><content type="html">I 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 &lt;span style="font-weight: bold;"&gt;why&lt;/span&gt; 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 &lt;a href="http://en.wikipedia.org/wiki/Data_URI_scheme"&gt;data URI scheme&lt;/a&gt; for image tags.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;Internet Explorer:&lt;br /&gt;&lt;div style="padding-left: 4em;"&gt;&lt;br /&gt;IE has a property of XMLHttpRequest object for binary data &lt;a href="http://msdn.microsoft.com/en-us/library/ms534368%28VS.85%29.aspx"&gt;ResponseBody&lt;/a&gt;.  This contains exactly what we need, but unfortunately the property is not visible to Javascript.  Since the string returned to Javascript by &lt;a href="http://msdn.microsoft.com/en-us/library/ms534369%28VS.85%29.aspx"&gt;ResponseText&lt;/a&gt; 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:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;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):&lt;br /&gt;&lt;pre class="brush:vb"&gt;&lt;br /&gt;Function BinaryArrayToAscCSV( aBytes )&lt;br /&gt; Dim j, sOutput&lt;br /&gt;        sOutput = "BinaryArrayToAscCSV"&lt;br /&gt; For j = 1 to LenB(aBytes)&lt;br /&gt;  sOutput= sOutput &amp; AscB( MidB(aBytes,j,1) )&lt;br /&gt;  sOutput= sOutput &amp; ","&lt;br /&gt; Next&lt;br /&gt; BinaryArrayToAscCSV = sOutput&lt;br /&gt;End Function&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Base 64 encode it directly in VBScript.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Once this is done, we can then base64 encode it using a fairly generic function in Javascript:&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt;Base64 = {&lt;br /&gt; &lt;br /&gt; // private property&lt;br /&gt; _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",&lt;br /&gt;&lt;br /&gt; encodeBinaryArrayAsString : function(input){&lt;br /&gt;  var ascArr;&lt;br /&gt;  var output = "";&lt;br /&gt;  var bytebuffer;&lt;br /&gt;  var encodedCharIndexes = new Array(4);&lt;br /&gt;  &lt;br /&gt;  var inx = 0;&lt;br /&gt;  ascArr = input.substring("BinaryArrayToAscCSV".length, input.length - 1).split(',');&lt;br /&gt;  while(inx &lt; ascArr.length){&lt;br /&gt;   // Fill byte buffer array&lt;br /&gt;   bytebuffer = new Array(3);&lt;br /&gt;   for(jnx = 0; jnx &lt; bytebuffer.length; jnx++)&lt;br /&gt;    if(inx &lt; ascArr.length)&lt;br /&gt;     bytebuffer[jnx] = parseInt(ascArr[inx++]); &lt;br /&gt;    else&lt;br /&gt;     bytebuffer[jnx] = 0;&lt;br /&gt;     &lt;br /&gt;   // Get each encoded character, 6 bits at a time&lt;br /&gt;   // index 1: first 6 bits&lt;br /&gt;   encodedCharIndexes[0] = bytebuffer[0] &gt;&gt; 2;  &lt;br /&gt;   // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)&lt;br /&gt;   encodedCharIndexes[1] = ((bytebuffer[0] &amp; 0x3) &lt;&lt; 4) | (bytebuffer[1] &gt;&gt; 4);  &lt;br /&gt;   // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)&lt;br /&gt;   encodedCharIndexes[2] = ((bytebuffer[1] &amp; 0x0f) &lt;&lt; 2) | (bytebuffer[2] &gt;&gt; 6);  &lt;br /&gt;   // index 3: forth 6 bits (6 least significant bits from input byte 3)&lt;br /&gt;   encodedCharIndexes[3] = bytebuffer[2] &amp; 0x3f;  &lt;br /&gt;   &lt;br /&gt;   // Determine whether padding happened, and adjust accordingly&lt;br /&gt;   paddingBytes = inx - (ascArr.length - 1);&lt;br /&gt;   switch(paddingBytes){&lt;br /&gt;    case 2:&lt;br /&gt;     // Set last 2 characters to padding char&lt;br /&gt;     encodedCharIndexes[3] = 64; &lt;br /&gt;     encodedCharIndexes[2] = 64; &lt;br /&gt;     break;&lt;br /&gt;    case 1:&lt;br /&gt;     // Set last character to padding char&lt;br /&gt;     encodedCharIndexes[3] = 64; &lt;br /&gt;     break;&lt;br /&gt;    default:&lt;br /&gt;     break; // No padding - proceed&lt;br /&gt;   }&lt;br /&gt;   // Now we will grab each appropriate character out of our keystring&lt;br /&gt;   // based on our index array and append it to the output string&lt;br /&gt;   for(jnx = 0; jnx &lt; encodedCharIndexes.length; jnx++)&lt;br /&gt;    output += this._keyStr.charAt(encodedCharIndexes[jnx]);     &lt;br /&gt;  }&lt;br /&gt;  return output;&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Firefox:&lt;br /&gt;&lt;div style="padding-left: 4em;"&gt;&lt;br /&gt;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 &lt;a href="https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data"&gt;https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data&lt;/a&gt;).  The resulting encoding function looks like this:&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt;Base64 = {&lt;br /&gt; &lt;br /&gt; // private property&lt;br /&gt; _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",&lt;br /&gt;&lt;br /&gt; encodeBinary : function(input){&lt;br /&gt;  var output = "";&lt;br /&gt;  var bytebuffer;&lt;br /&gt;  var encodedCharIndexes = new Array(4);&lt;br /&gt;  var inx = 0;&lt;br /&gt;  var paddingBytes = 0;&lt;br /&gt;   &lt;br /&gt;  while(inx &lt; input.length){&lt;br /&gt;   // Fill byte buffer array&lt;br /&gt;   bytebuffer = new Array(3);&lt;br /&gt;   for(jnx = 0; jnx &lt; bytebuffer.length; jnx++)&lt;br /&gt;    if(inx &lt; input.length)&lt;br /&gt;     bytebuffer[jnx] = input.charCodeAt(inx++) &amp; 0xff; // throw away high-order byte, as documented at: https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data&lt;br /&gt;    else&lt;br /&gt;     bytebuffer[jnx] = 0;&lt;br /&gt;   &lt;br /&gt;   // Get each encoded character, 6 bits at a time&lt;br /&gt;   // index 1: first 6 bits&lt;br /&gt;   encodedCharIndexes[0] = bytebuffer[0] &gt;&gt; 2;  &lt;br /&gt;   // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)&lt;br /&gt;   encodedCharIndexes[1] = ((bytebuffer[0] &amp; 0x3) &lt;&lt; 4) | (bytebuffer[1] &gt;&gt; 4);  &lt;br /&gt;   // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)&lt;br /&gt;   encodedCharIndexes[2] = ((bytebuffer[1] &amp; 0x0f) &lt;&lt; 2) | (bytebuffer[2] &gt;&gt; 6);  &lt;br /&gt;   // index 3: forth 6 bits (6 least significant bits from input byte 3)&lt;br /&gt;   encodedCharIndexes[3] = bytebuffer[2] &amp; 0x3f;  &lt;br /&gt;   &lt;br /&gt;   // Determine whether padding happened, and adjust accordingly&lt;br /&gt;   paddingBytes = inx - (input.length - 1);&lt;br /&gt;   switch(paddingBytes){&lt;br /&gt;    case 2:&lt;br /&gt;     // Set last 2 characters to padding char&lt;br /&gt;     encodedCharIndexes[3] = 64; &lt;br /&gt;     encodedCharIndexes[2] = 64; &lt;br /&gt;     break;&lt;br /&gt;    case 1:&lt;br /&gt;     // Set last character to padding char&lt;br /&gt;     encodedCharIndexes[3] = 64; &lt;br /&gt;     break;&lt;br /&gt;    default:&lt;br /&gt;     break; // No padding - proceed&lt;br /&gt;   }&lt;br /&gt;   // Now we will grab each appropriate character out of our keystring&lt;br /&gt;   // based on our index array and append it to the output string&lt;br /&gt;   for(jnx = 0; jnx &lt; encodedCharIndexes.length; jnx++)&lt;br /&gt;    output += this._keyStr.charAt(encodedCharIndexes[jnx]);&lt;br /&gt;  }&lt;br /&gt;  return output;&lt;br /&gt; };&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;pre class="brush:js"&gt;&lt;br /&gt;LoadBinaryResource = function(url) { &lt;br /&gt;  var req = new XMLHttpRequest();  &lt;br /&gt;  req.open('GET', url, false);  &lt;br /&gt;&lt;br /&gt;  if (req.overrideMimeType)&lt;br /&gt;    req.overrideMimeType('text/plain; charset=x-user-defined');  &lt;br /&gt;  req.send(null);  &lt;br /&gt;  if (req.status != 200) return '';  &lt;br /&gt;  if (typeof(req.responseBody) !== 'undefined') return BinaryArrayToAscCSV(req.responseBody);&lt;br /&gt;  return req.responseText;  &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;LoadBinaryResourceAsBase64 = function(url) { &lt;br /&gt;  var data = LoadBinaryResource(url);&lt;br /&gt;  &lt;br /&gt;  if (data.indexOf("BinaryArrayToAscCSV") !== -1)&lt;br /&gt;    return Base64.encodeBinaryArrayAsString(data);&lt;br /&gt;  else&lt;br /&gt;    return Base64.encodeBinary(data);  &lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-4944090063865517807?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/4944090063865517807/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=4944090063865517807" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/4944090063865517807?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/4944090063865517807?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/NziPLIU4uXs/javascript-hacks-using-xhr-to-load.html" title="Javascript Hacks: Using XHR to load binary data" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2009/07/javascript-hacks-using-xhr-to-load.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcBQn8ycCp7ImA9WxJUEE8.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-1904125260016878935</id><published>2008-10-28T23:42:00.001-07:00</published><updated>2009-07-07T20:17:33.198-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T20:17:33.198-07:00</app:edited><title>A little surprised no one caught this</title><content type="html">So I just watched last week's &lt;a href="http://www.nbc.com/Saturday_Night_Live/video/categories/weekend-update-thursdays/29439/"&gt;SNL Weekend Update Thursdays &lt;/a&gt;on &lt;a href="http://nbc.com"&gt;NBC.com&lt;/a&gt;, 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 &lt;a href="http://silverlight.net/"&gt;Silverlight &lt;/a&gt;(no, they use &lt;a href="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash"&gt;Flash&lt;/a&gt;), 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 "&lt;a href="http://en.wikipedia.org/wiki/Lorem_ipsum"&gt;Lorem Ipsum&lt;/a&gt;" in there and no one bothered to update it or correct it.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://img11.imageshack.us/img11/286/200810282331.jpg"&gt;&lt;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" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-1904125260016878935?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/1904125260016878935/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=1904125260016878935" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/1904125260016878935?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/1904125260016878935?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/BuoIyxr156I/little-surprised-no-one-caught-this.html" title="A little surprised no one caught this" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/10/little-surprised-no-one-caught-this.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ENQno8eSp7ImA9WxRRE0g.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-3128064170444895561</id><published>2008-09-25T09:13:00.000-07:00</published><updated>2008-09-25T09:21:33.471-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-25T09:21:33.471-07:00</app:edited><title>It doesn't get much better than this</title><content type="html">How's this for a setup message? Kinda hard to comply with...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://content.screencast.com/users/EmilT/folders/Jing/media/5412a0bb-c6d1-48be-a4df-352829c740e3/2008-09-25_0849.png"&gt;&lt;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" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-3128064170444895561?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/3128064170444895561/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=3128064170444895561" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3128064170444895561?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3128064170444895561?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/ykBzKh_XVv4/it-doesnt-get-much-better-than-this.html" title="It doesn't get much better than this" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/09/it-doesnt-get-much-better-than-this.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4MQHszeip7ImA9WxdSGU0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-8510287131124604809</id><published>2008-05-27T08:56:00.000-07:00</published><updated>2008-05-27T08:59:41.582-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-27T08:59:41.582-07:00</app:edited><title>One more technical analysis link</title><content type="html">I bumped across &lt;a href="http://www.stoxline.com/"&gt;Stoxline&lt;/a&gt; during my &lt;a href="http://emilsblog.lerch.org/2008/05/excercising-intc-stock-options.html"&gt;recent foray into the technical analysis world&lt;/a&gt;.  It provides a good quick summary of some key price points.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-8510287131124604809?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/8510287131124604809/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=8510287131124604809" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8510287131124604809?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8510287131124604809?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/gfNyu_8J0_0/one-more-technical-analysis-link.html" title="One more technical analysis link" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/05/one-more-technical-analysis-link.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYDQ308fCp7ImA9WxdSFUg.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-215299667854185071</id><published>2008-05-23T07:50:00.000-07:00</published><updated>2008-05-23T08:39:32.374-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-23T08:39:32.374-07:00</app:edited><title>Excercising INTC stock options</title><content type="html">So 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.&lt;br /&gt;&lt;br /&gt;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. &lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.thestreet.com/s/tech-winners-and-losers-intel/newsanalysis/winnerstech/_msnh/10417027.html?&amp;amp;cm_ven=MSNH&amp;amp;cm_cat=FREE&amp;amp;cm_ite=NA"&gt;get an upgrade&lt;/a&gt; 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:&lt;br /&gt;&lt;br /&gt;I watched the following indicators:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.investopedia.com/terms/m/macd.asp"&gt;MACD&lt;/a&gt;:  I was looking pretty short-term (&lt;1&gt;&lt;li&gt;&lt;a href="http://www.investopedia.com/terms/b/bollingerbands.asp"&gt;Bollinger Bands&lt;/a&gt;:  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.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.investopedia.com/terms/r/rsi.asp"&gt;RSI&lt;/a&gt;:  Fairly useful indicator in this scenario&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.investopedia.com/terms/s/stochasticoscillator.asp"&gt;Slow Stochastic Oscillator&lt;/a&gt;: 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&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.investopedia.com/terms/p/parabolicindicator.asp"&gt;Parabolic SAR&lt;/a&gt;: My primary source of when the options should be sold.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Lessons learned?  The indicators can work...don't rely on just one, and make sure that you use the right indicator for your goal.&lt;br /&gt;&lt;br /&gt;Another couple links of use:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://research.scottrade.com/public/stocks/charts/charts.asp?symbol=INTC"&gt;Scottrade chart&lt;/a&gt;:  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.&lt;/li&gt;&lt;li&gt;&lt;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"&gt;Yahoo chart&lt;/a&gt;:  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.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.tdameritrade.com/tradingtools/commandcenter.html"&gt;TD Ameritrade Command Center 2.0&lt;/a&gt;:  A Java app available for &lt;a href="http://www.tdameritrade.com/welcome1.html"&gt;TD Ameritrade&lt;/a&gt; customers, it let me watch the stock in real-time during the day.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-215299667854185071?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/215299667854185071/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=215299667854185071" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/215299667854185071?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/215299667854185071?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/u2l96okWmIg/excercising-intc-stock-options.html" title="Excercising INTC stock options" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/05/excercising-intc-stock-options.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QDSXw_cCp7ImA9WxdSE0o.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-5325209163409213405</id><published>2008-05-21T07:13:00.000-07:00</published><updated>2008-05-21T07:16:18.248-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-21T07:16:18.248-07:00</app:edited><title>It could have been so much more effective with a little B&amp;E</title><content type="html">A couple days ago I got a flyer on my door advertising a security system and monitoring package.  I'm not sure how many people actually respond to a blanket flyer like that, but it got me thinking...wouldn't the flyer have been more effective had they managed to leave it somewhere &lt;span style="font-weight: bold;"&gt;inside&lt;/span&gt; the house while we weren't home?  Illegal - yes.  Effective: definitely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-5325209163409213405?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/5325209163409213405/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=5325209163409213405" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/5325209163409213405?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/5325209163409213405?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/ue3BazYZGQ0/it-could-have-been-so-much-more.html" title="It could have been so much more effective with a little B&amp;E" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/05/it-could-have-been-so-much-more.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQBQHc9fip7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-3666716849101529582</id><published>2008-05-02T09:23:00.000-07:00</published><updated>2009-07-07T13:59:11.966-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T13:59:11.966-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>Check for valid stored procedures</title><content type="html">I just posted a &lt;a href="http://www.codeproject.com/KB/database/validate-sqlserver-proc.aspx"&gt;small utility&lt;/a&gt; on &lt;a href="http://www.codeproject.com"&gt;CodeProject &lt;/a&gt;to check for valid stored procedures, views, and functions (in SQL Server).  It's actually a polish of some work someone else had done earlier, but if you have a large number of objects and are doing significant database refactoring, you may want to check it out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-3666716849101529582?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/3666716849101529582/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=3666716849101529582" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3666716849101529582?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3666716849101529582?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/XjBNAVBBOC4/check-for-valid-stored-procedures.html" title="Check for valid stored procedures" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/05/check-for-valid-stored-procedures.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIEQH87eip7ImA9WxRaEE4.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-3009303763967582498</id><published>2008-05-01T08:10:00.000-07:00</published><updated>2008-12-11T14:28:21.102-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-11T14:28:21.102-08:00</app:edited><title>Street signs</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__qN00uIxfHI/SBnf7IjXQRI/AAAAAAAAAHg/FRkySu62yKM/s1600-h/walk.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/__qN00uIxfHI/SBnf7IjXQRI/AAAAAAAAAHg/FRkySu62yKM/s200/walk.jpg" alt="" id="BLOGGER_PHOTO_ID_5195429852149661970" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When crossing the street and seeing one of the standard walk signs (such as the one to the left), I have a habit of imitating the sign and saying "white man walking".&lt;br /&gt;&lt;br /&gt;Well, Sweden is now crossing the gender barrier with their &lt;a href="http://www.npr.org/templates/story/story.php?storyId=90090667"&gt;new signs&lt;/a&gt;.  Where this will lead, I'm not sure.  Non-caucasians?  Dogs?  Cats?  It does make me wonder, if the signs are specific, is Sweden now implying that where this sign is posted, only women are allowed to walk?&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/__qN00uIxfHI/SBngiojXQSI/AAAAAAAAAHo/dC_BoH7WVBE/s1600-h/garmanfru.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://1.bp.blogspot.com/__qN00uIxfHI/SBngiojXQSI/AAAAAAAAAHo/dC_BoH7WVBE/s200/garmanfru.jpg" alt="" id="BLOGGER_PHOTO_ID_5195430530754494754" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-3009303763967582498?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/3009303763967582498/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=3009303763967582498" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3009303763967582498?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/3009303763967582498?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/lbOniZl02nw/street-signs.html" title="Street signs" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/__qN00uIxfHI/SBnf7IjXQRI/AAAAAAAAAHg/FRkySu62yKM/s72-c/walk.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/05/street-signs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08ESX04eyp7ImA9WxZbFEk.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-8291379206950424162</id><published>2008-04-17T07:06:00.000-07:00</published><updated>2008-04-17T07:16:48.333-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-17T07:16:48.333-07:00</app:edited><title>Google Maps update</title><content type="html">I just noticed that &lt;a href="http://maps.google.com"&gt;Google Maps&lt;/a&gt; introduced the ability to show historical "average traffic" for any given time on particular day of the week.  I just used it to confirm my commuting schedule, and it seems to correlate well with my experiences and validate that the times I drive are pretty reasonable.&lt;br /&gt;&lt;br /&gt;There are definitely some systemic traffic slowdowns in the Portland area.  For example, 26 west bound between &lt;a href="http://maps.google.com/?ie=UTF8&amp;amp;layer=t&amp;amp;ll=45.5243,-122.816548&amp;amp;spn=0.021047,0.057335&amp;amp;z=15"&gt;Murray and Bethany&lt;/a&gt; is nearly always a problem from 4PM-7PM, probably stemming from the fact that the road moves from 3 lanes down to 2 just after the Bethany exit.  This is especially unfortunate since the third lane was just added...although I do admit that there are much more serious traffic concerns in the area to focus our resources on. &lt;br /&gt;&lt;br /&gt;It would be nice to know that those that plan road improvements take a look at this type of data to prioritize their efforts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-8291379206950424162?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/8291379206950424162/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=8291379206950424162" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8291379206950424162?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/8291379206950424162?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/BXriVEvF5js/google-maps-update.html" title="Google Maps update" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/04/google-maps-update.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkIEQH07fyp7ImA9WxRaEE4.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-892337348663160870</id><published>2008-04-02T19:56:00.000-07:00</published><updated>2008-12-11T14:28:21.307-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-11T14:28:21.307-08:00</app:edited><title>Calendar sync bliss (finally)</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__qN00uIxfHI/R_RHowcMlKI/AAAAAAAAAG4/Ur724udiHQM/s1600-h/Calendar+sync.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://2.bp.blogspot.com/__qN00uIxfHI/R_RHowcMlKI/AAAAAAAAAG4/Ur724udiHQM/s400/Calendar+sync.png" alt="" id="BLOGGER_PHOTO_ID_5184847836533789858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Finally, a calendar sync solution that works.  After my experiment with &lt;a href="http://www.google.com/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fwww.daveswebsite.com%2Fsoftware%2Fgsync%2F&amp;amp;ei=z-f0R6zgNoiYoQS90ZC_DQ&amp;amp;usg=AFQjCNH3xj_OGBn4h2o4CMxFzTU8Px_TKQ&amp;amp;sig2=lSOehs0id7vBbq2inRdnNQ"&gt;gSyncIT&lt;/a&gt;, I just couldn't quite get past some of its limitations.  Once multiple calendars get involved, things get a bit ugly.&lt;br /&gt;&lt;br /&gt;A coworker recommended &lt;a href="http://www.google.com/url?sa=t&amp;amp;ct=res&amp;amp;cd=1&amp;amp;url=http%3A%2F%2Fwww.syncmycal.com%2F&amp;amp;ei=Ruj0R7T5EYiYoQSX0Yy_DQ&amp;amp;usg=AFQjCNEmiPLtCDyy3CMY1BHS0iRFzi2pGQ&amp;amp;sig2=jmJ4PsN07peTa6JE9sSXVw"&gt;SyncMyCal&lt;/a&gt; as a way past those issues, and I'm pretty happy.  You'll see my calendaring setup to the right. &lt;br /&gt;&lt;br /&gt;Google Calendar is pretty much my primary calendar, and I have several calendars loaded.  Some calendars, like US, UK, Indian Holidays and the Winterhawks game schedule are information only.  However, I have my own calendar, a family calendar for events the whole family is attending, and two TripIt calendars (one for my wife, one for me) that do a great job representing any travel I'm doing. &lt;br /&gt;&lt;br /&gt;I'd like to make sure that these calendars are available (at least in free/busy form) to other Exchange users at work, and that the calendars get posted to my cell phone using Windows Mobile.  The Outlook 2007 Internet Calendars feature doesn't allow this, so I needed a solution that would allow my Google calendars to merge into my single Outlook calendar.  I was also looking for my work calendar to post out to Google so I could have visibility there as well.&lt;br /&gt;&lt;br /&gt;SyncMyCal had the answer through the use of category synchronization.  Each Google calendar has their events assigned to a specific category, and only those events are sync'd with that calendar.  Anything not assigned to a category (work stuff) gets sync'd to Google under a new "Work" calendar.  I didn't need full synchronization here, but it's nice to know I have it if I need it.&lt;br /&gt;&lt;br /&gt;What's missing?  I can't find a way to have SyncMyCal make all Google-sourced events private on the Outlook side (although it does sync the private flag).  I have to remember to mark anything truly private as such.  Not a big deal, but it's worth mentioning.&lt;br /&gt;&lt;br /&gt;There is definitely whitespace for an entrepreneur to simplify calendaring...I can't believe that my needs are *THAT* special...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-892337348663160870?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/892337348663160870/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=892337348663160870" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/892337348663160870?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/892337348663160870?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/EiAFvjG7xcg/calendar-sync-bliss-finally.html" title="Calendar sync bliss (finally)" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/__qN00uIxfHI/R_RHowcMlKI/AAAAAAAAAG4/Ur724udiHQM/s72-c/Calendar+sync.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/04/calendar-sync-bliss-finally.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQEQHgzfSp7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-890557513805546836</id><published>2008-04-01T08:28:00.000-07:00</published><updated>2009-07-07T13:58:21.685-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T13:58:21.685-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C#" /><title>C# Covariant Generics</title><content type="html">Sorry for the highly technical posts...lighter stuff to come!&lt;br /&gt;&lt;br /&gt;This has really been bugging me on my current project.  In an object oriented system, if one class inherits from another (e.g. "Cat" inherits from "Animal"), and a method expects to receive the base class as a parameter, it is safe to send in a subtype.  In my example, a method operating on "Animal" can take "Cat" safely.  This is sometimes called "downcasting".&lt;br /&gt;&lt;br /&gt;This behavior should extend to generic types.  Again, in my example, if a method expects a List of Animals, I should be able to pass in a List of Cats.  However, C# does not allow this behavior (but the CLR does).  Bah!&lt;br /&gt;&lt;br /&gt;Here is some more background I've dug up on the issue: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://research.microsoft.com/research/pubs/view.aspx?type=inproceedings&amp;amp;id=1215"&gt;MS Research article&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/b47879b2fecdf61a"&gt;Google Groups discussion&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-890557513805546836?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/890557513805546836/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=890557513805546836" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/890557513805546836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/890557513805546836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/ipEfyQ9hj5o/c-covariant-generics.html" title="C# Covariant Generics" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/04/c-covariant-generics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQHQnY9fip7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-6654421483382673867</id><published>2008-03-27T08:47:00.001-07:00</published><updated>2009-07-07T13:58:53.866-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T13:58:53.866-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>Yet more SQL 2005 fun: Developing search procs</title><content type="html">A common pattern in applications is to have a search stored procedure work as the backend for a search screen.  If a term has not been passed by the user, the intent is that there is no filter on the results for that parameter.  Here's a &lt;a href="http://www.sommarskog.se/dyn-search.html"&gt;great article&lt;/a&gt; discussing the ways that this can be acheived.  I'm a personal fan of the COALESCE statement talked about in the &lt;a href="http://www.sommarskog.se/dyn-search.html#static"&gt;static &lt;/a&gt;discussion.&lt;br /&gt;&lt;br /&gt;One area that was not discussed in the article was the idea of having similar functionality with a list of filters (e.g. filter to these specific books in the library).  I found a &lt;a href="http://weblogs.asp.net/jgalloway/archive/2007/02/16/passing-lists-to-sql-server-2005-with-xml-parameters.aspx"&gt;pretty good article&lt;/a&gt; talking about SQL 2005's use of Xml parameters to do this - Xml's main benefit being that it's more designed for this use case than a delimited string.  However, the same problem now applies...what if I either have a list of books, or don't pass anything, meaning I want to search across all books?&lt;br /&gt;&lt;br /&gt;My solution was to grab all the data from the reference table and build my own Xml string.  Then I could use it in the main select statement:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;IF &lt;/span&gt;@param&lt;span style="color: rgb(102, 102, 102);"&gt; is null  &lt;/span&gt;&lt;br /&gt;    &lt;span style="color: rgb(51, 51, 255);"&gt;SET &lt;/span&gt;@param =&lt;br /&gt;    (&lt;span style="color: rgb(51, 51, 255);"&gt;SELECT &lt;/span&gt;1 &lt;span style="color: rgb(51, 51, 255);"&gt;AS &lt;/span&gt;Tag,0 &lt;span style="color: rgb(51, 51, 255);"&gt;AS &lt;/span&gt;Parent,MyElementName &lt;span style="color: rgb(51, 51, 255);"&gt;AS &lt;/span&gt;[Root!1!string!element]&lt;br /&gt;     &lt;span style="color: rgb(51, 51, 255);"&gt;FROM &lt;/span&gt;sourcetable &lt;span style="color: rgb(51, 51, 255);"&gt;FOR XML EXPLICIT&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;SELECT&lt;/span&gt;...&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;WHERE&lt;/span&gt;...&lt;br /&gt;...&lt;span style="color: rgb(51, 51, 255);"&gt;AND &lt;/span&gt;&lt;br /&gt;FieldName &lt;span style="color: rgb(51, 51, 255);"&gt;IN &lt;/span&gt;&lt;br /&gt;        (&lt;span style="color: rgb(51, 51, 255);"&gt;SELECT &lt;/span&gt;Field.value(&lt;span style="color: rgb(255, 0, 0);"&gt;'.'&lt;/span&gt;,&lt;span style="color: rgb(255, 0, 0);"&gt;'VARCHAR(max)'&lt;/span&gt;) FinalName&lt;br /&gt;        &lt;span style="color: rgb(51, 51, 255);"&gt;FROM &lt;/span&gt;@param.nodes(&lt;span style="color: rgb(255, 0, 0);"&gt;'//string'&lt;/span&gt;) &lt;span style="color: rgb(51, 51, 255);"&gt;AS &lt;/span&gt;Table(Field)) &lt;br /&gt;&lt;br /&gt;I'm sure this wouldn't perform well with large tables, but my reference tables are fairly small (&lt;100 rows each), and it works great.&lt;br /&gt;&lt;br /&gt;FYI: Here is an example COALESCE statement for the standard filters:&lt;br /&gt;&lt;br /&gt;table            &lt;span style="color: rgb(102, 102, 102);"&gt;LIKE &lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;'%'&lt;/span&gt; + &lt;span style="color: rgb(153, 51, 153);"&gt;COALESCE&lt;/span&gt;(@Name,      fac.FacilityName           ) + &lt;span style="color: rgb(255, 0, 0);"&gt;'%'&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-6654421483382673867?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/6654421483382673867/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=6654421483382673867" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/6654421483382673867?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/6654421483382673867?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/Dd4AsN4FtDM/yet-more-sql-2005-fun-developing-search.html" title="Yet more SQL 2005 fun: Developing search procs" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/03/yet-more-sql-2005-fun-developing-search.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQHQnY9fyp7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-6692354.post-4971957042425078858</id><published>2008-03-27T08:24:00.000-07:00</published><updated>2009-07-07T13:58:53.867-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-07T13:58:53.867-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL" /><title>More SQL 2005: SqlDependency update</title><content type="html">While SQL Server data update notifications through the SqlDependency object seemed like a great idea, I now believe the architecture is fundamentally flawed...I'm looking forward to changes in this area to make the feature more robust in the next release(s) of SQL Server and/or the .NET Framework.  Here are some of the problems I've run into:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/KB/database/SqlDependencyPermissions.aspx"&gt;Massive amounts&lt;/a&gt; of &lt;a href="http://emilsblog.lerch.org/2008/03/database-permissions-for-sqldependency.html"&gt;required permissions&lt;/a&gt; in the default run mode&lt;/li&gt;&lt;li&gt;Query types available are &lt;a href="http://msdn2.microsoft.com/en-us/library/aewzkxxh.aspx"&gt;incredibly restrictive&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/remusrusanu/archive/2007/10/12/when-it-rains-it-pours.aspx"&gt;Ineffective tear down of resources&lt;/a&gt;, again, in default run mode, with no programatic workaround.  (The worst part?  The problem is actually most acute while doing active development...)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/remusrusanu/archive/2007/10/12/when-it-rains-it-pours.aspx"&gt;Severe ramifications&lt;/a&gt; for any issue, whether caused by environment or poor coding&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Complex (and maybe unusable) &lt;a href="http://www.sqlskills.com/blogs/bobb/2006/06/28/PreprovisioningAndSqlDependency.aspx"&gt;setup for custom service/queue implementation&lt;/a&gt; to alleviate the first two issues.  I never really even figured out that setup when operating in a non-default schema in a restricted permission environment.&lt;/li&gt;&lt;/ul&gt;This feature is a great concept, but with an implementation that severely limits its use.  My recommendation is to avoid this functionality in nearly all cases.  In my current project, I've moved to a custom cache implementation that checks last modified date across all all lookup tables and clears the cache of all out of date lists.  If something happens in between checks, we'll just have to deal with that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6692354-4971957042425078858?l=emilsblog.lerch.org' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://emilsblog.lerch.org/feeds/4971957042425078858/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=6692354&amp;postID=4971957042425078858" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/4971957042425078858?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6692354/posts/default/4971957042425078858?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/emillerch/~3/MZFIPsdlidQ/more-sql-2005-sqldependency-update.html" title="More SQL 2005: SqlDependency update" /><author><name>Emil</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="30" src="http://bp0.blogger.com/__qN00uIxfHI/RqzItQ3lDSI/AAAAAAAAABo/2O11BBux3SY/s400/Emil+Head.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://emilsblog.lerch.org/2008/03/more-sql-2005-sqldependency-update.html</feedburner:origLink></entry></feed>

