Fear of Silverlight Gaudiness

When Java applets were all the rage, every website had the reflecting text Java applet (the "Lake" effect). Here is an example of the lake effect with a picture. If you don't remember these, you're lucky.

If you do remember these, you should recall that animated GIFs were also all the rage. Pictures like this gem:

Or perhaps this commonly used one:

Back then, it seemed like the web was nothing but a place to put tacky websites. The more your website moved the better. It was no longer okay to have a website that was plain and looked static. Your website needed some pizazz! This behavior has started to fall by the wayside as more and more designers get their hands on the web. The concepts of a well designed site are permeating throughout the internet and even people who would normally produce a gaudy website now have plenty of resources to make things look good.

Then Microsoft released Silverlight. All the Silverlight demos initially focused on how to animate and how to produce an incredibly tacky application. Want to skin your application? No problem! Your standard input button can have a plain blue background, white text, glow red when hovered and turn yellow when clicked! See how easy it is!

Internally, I feared that every application would begin to look like this:

Get Microsoft Silverlight

 

So far, it appears my fears are unfounded. There are plenty of examples of how to ugly-up your Silverlight application, but so far it seems there are enough good resources (both built-in and external) that provide reasonable amounts of good looking styling for applications. The Silverlight toolkit has reasonable themes, Infragistics has a whole sample browser trying to help people create good user experiences, and my own experience has been that people are looking for only the right amount of flash.

So I beg everyone building Silverlight applications and Silverlight content and styles: please keep things looking good. The first one of you to build a Silverlight Lake effect on Text will get evicted from the internet.

Silverlight Anonymous Type Binding Gotcha

When Silverlight databinding evaluates a binding expression, it does one of two things. If the object it is bound to inherits from FrameworkElement and there is a DependencyProperty matching the binding expression, it uses FrameworkElement.GetValue to retrieve the value [simplified]. If not a FrameworkElement and not a DependencyProperty, Silverlight falls back to using reflection to retrieve the values.

This is problematic if you attempt to data bind to an anonymous type.

In Silverlight, when you attempt to use reflection to retrieve a property value of an object whose Type is not defined in your assembly, a MethodAccessExcepttion is thrown. Go ahead I'll give you a minute to test it.

Or follow along if you want to take my word for it. Create two projects: one Silverlight Application and one Silverlight Class Library. Add a reference to the library from the application. In the library, add the following classes:

   1:  public class Class1 {
   2:      public object GetFoo() {
   3:          return new Foo() {
   4:              Baz = "baz1",
   5:              Bap = "bap1"
   6:          };
   7:      }
   8:   
   9:      public object GetBar() {
  10:          return new Bar() {
  11:              Baz = "baz1",
  12:              Bap = "bap1"
  13:          };
  14:      }
  15:  }
  16:   
  17:  public class Bar {
  18:      public string Baz { get; set; }
  19:      public string Bap { get; set; }
  20:  }
  21:   
  22:  class Foo {
  23:      public string Baz { get; set; }
  24:      public string Bap { get; set; }
  25:  }

Now in the application, add the following code inside App.xaml.cs:

   1:  Class1 c = new Class1();
   2:  var o = c.GetFoo();
   3:  var prop = o.GetType().GetProperty( "Baz" );
   4:  try {
   5:      var value = prop.GetValue( o, null );
   6:  }
   7:  catch( MethodAccessException ex ) {
   8:      System.Diagnostics.Debugger.Break();
   9:  }
  10:   
  11:  o = c.GetBar();
  12:  prop = o.GetType().GetProperty( "Baz" );
  13:  try {
  14:      var value = prop.GetValue( o, null );
  15:  }
  16:  catch( MethodAccessException ex ) {
  17:      System.Diagnostics.Debugger.Break();
  18:  }

Run the application. The debugger will stop inside the first catch on line 8 but not the second on line 17. What this tells us is that you can use reflection to get the value of properties on a public Type defined in another assembly, but not on one that isn't public.

Why is this important? It's important because anonymous Types are defined internal to the assembly that they are used in. Because they are not public, and the data binding framework is not in the same assembly (it's in System.Windows), it will receive an exception when trying to use reflection to get the value of a property from an anonymous type.

To get around this, simply create a "dummy object" (same as a DTO) that is public and has all the public properties you need. Then instead of this format:

   1:  var results = from d in data
   2:                select new {
   3:                    Bar = d.Bar,
   4:                    Baz = d.Baz
   5:                };

You use this format:

   1:  var results = from d in data
   2:                select new Result() {
   3:                    Bar = d.Bar,
   4:                    Baz = d.Baz
   5:                };

 

Getting Notified When An IIS AppPool Recycles

IIS Application Pool recycling in IIS 6 is a crutch for poorly performing code and is frequently misunderstood and overused. However, if you do have a need to use it and want to minimize the hit of your applications in that AppPool spinning up again on the next request, you can use the following code to determine when it recycles.

First, you need to configure IIS to enable reporting AppPool recycle events. This is off by default. This can easily be done using WMI and C#:

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Text;
 
namespace LogIISRecycleEvents {
       class WmiUtils {
              public static void SetLogEventsOnRecycle( RecycleOnEventsTypes types ) {
                     DirectoryEntry rootEntry = new DirectoryEntry( "IIS://localhost/W3SVC" );
                     foreach( DirectoryEntry siteEntry in rootEntry.Children ) {
                           if( siteEntry.SchemaClassName == "IIsApplicationPools" ) {
                                  siteEntry.Properties["LogEventOnRecycle"].Value = (int) types;
                                  siteEntry.CommitChanges();
                           }
                           siteEntry.Dispose();
                           break;
                     }
                     rootEntry.Dispose();
              }
       }
 
       [Flags]
       enum RecycleOnEventsTypes {
              PrivateMemory = 128,
              ConfigChange = 64,
              OnDemand = 32,
              IsapiUnhealthy = 16,
              Memory = 8,
              Schedule = 4,
              Requests = 2,
              Time = 1,
              None = 0,
              All = PrivateMemory |
                     ConfigChange |
                     OnDemand |
                     IsapiUnhealthy |
                     Memory |
                     Schedule |
                     Requests |
                     Time
       }
}

Next you need to listen for these events. I'm not sure whether the IIS WMI provider supports sending WMI Events or not, but I do know it writes entries to the System Event Log. Listening to the System Event Log is easy and all you need to do is wait for the right event to come through:

 

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
 
namespace LogIISRecycleEvents {
       static class Program {
              [STAThread]
              static void Main() {
                     WmiUtils.SetLogEventsOnRecycle( RecycleOnEventsTypes.All );
                     EventLog log = new EventLog( "System" );
                     log.EntryWritten += new EntryWrittenEventHandler( log_EntryWritten );
                     log.EnableRaisingEvents = true;
 
                     Console.WriteLine( "Press enter to finish" );
                     Console.ReadLine();
 
                     log.Close();
              }
 
              static void log_EntryWritten( object sender, EntryWrittenEventArgs e ) {
                     if( e.Entry.Source == "W3SVC" && e.Entry.EventID == 1075 &&
                           e.Entry.EntryType == EventLogEntryType.Information &&
                           e.Entry.Message.Contains( "worker process" ) &&
                           e.Entry.Message.Contains( "recycle" ) ) {
                           Console.WriteLine( "AppPool has recycled!" );
                     }
              }
       }
}

Finally, you may have to change what criteria you're searching the EventLogEntry for. As you can see I'm looking at Event Type, Event ID and looking for certain words in the message to indicate the AppPool has recycled. You could use regular expressions to find the specific AppPool name as well.

What to do with this? Create a WebRequest and request your application's default web page and that will force the application to spin up and the next user to your site won't have to wait.

I Sold a Dream Last Night

Everyone wants to play an instrument when they're young. In elementary school I tried to play the tumpet and failed. They moved me onto the trombone because it would be easier for me to play. I swtiched, but I wasn't too thrilled about playing it (I wanted the cool saxophone but they wouldn't let me) and after a year I realized it wasn't for me.

In high school I had some guitarist friends and decided to learn to play. I got a $200 used guitar and an amp and started to play. I learned all the standard beginner songs and eventually realized I was neither good nor did I really want to keep learning how to play.

In college I went to clubs and parties and had a couple DJ friends. I really enjoyed using their tables when they weren't so a few years ago I bought my own. I got a ton of records and set up my turntables and mixer and started to learn how to use them. As it turns out, one of the reasons I've quit so many musical instruments is that I'm tone deaf. As that turns out, not being tone deaf is a requirement to play any sort of musical instrument.

After two years of being locked away in a closet, I decided to list my turntables for sale on Craigslist. I priced out new models of what I had and then cut the price in half. Within hours I had a ton of people interested in buying my barely used, incredibly cheap turntable mix setup.

Last night the first person to come to my apartment and look at them bought them. He seemed pretty amazed at the condition they're in and the price I was asking so pretty quickly said he wanted to buy them from me. He said he plays guitar and drums and he enjoys using his friends' turntables and wanted his own. I thought I'd feel guilty about selling them since it was a dream of mine, but I am glad I sold them to someone who will actually be able to use them.

Anyway, now I get to buy myself a couple 20+ inch LCD monitors for my desktop PC to use in place.

Elevensies: this morning was a good morning

My wife made a Lord of the Rings joke this morning.

(sort of quote)
"I packed a ton of food because I didn't eat breakfast. I'll have second breakfast and elevensies."

I think I may have won her over.

Windows Server 2003 SP1 KB FIX

Well, my first reporting of a bug to Microsoft (via the phone, through product support services) has finally resulted in a KB article.

http://support.microsoft.com/kb/913548/

I submitted this bug to Microsoft on November of 2005 and it finally made a public KB article on June 1 of 2006. At least this was a relatively minor issue.

Tom, James, and Adam vs. the UPS truck

I wrote this years ago when I had my weblog hosted through Blogger. Some recent conversations reminded me of it so I decided to bring it back. I call these stories "Tom Stories". Tom is that crazy-ass person you were friends with in high school that always seemed to prompt you into doing some incredibly stupid things. Following is the first ever Tom Story I wrote, unedited from my first posting of it.

We were in ninth grade (James was in tenth), it was an afternoon nearing summer, immediately after school was over. Tom, James and I always met outside a certain door and walked home. Typically we walked James home, then Tom and I went back to one of our houses and played video games until dinner time.

Well this was a day when it didn't happen exactly like that.

Tom, James and I met outside the high school just like usual. We always took a shortcut through someone's yard, which put us at the end of a dead-end street, at least 25 seconds ahead of all the kids who walked around the house and down another street. We were smarter than they were.

Anyway, while walking down the street, talking our kid talk, and me trying to sing a song and getting made fun of because I cannot change the inflection in my voice while singing, we spot a grand opportunity. About three houses down the street was a UPS truck parked on the side of the road. There was an incredibly short man delivering a package to the house the truck was parked in front of. I mean short. This guy was n't any bigger than five foot one, maybe not even that. Anyway, he had just started walking back to the truck when we started running for the truck. I don't know who said to do it, or even if any of us said anything, but we did it. If it were a movie, the scene would be: "the three boys all looked at each other, knowing the others thoughts, nodded, and started running."

By some uncanny timing we reached the truck just moments after he got in, so he hadn't been able to see us in his mirrors. We tried to figure out who would go where, so I just jumped on the right side of the truck. I grabbed my backpack, secured it, then grabbed the bar on the side of the truck. James got on the left side, and Tom got in the middle where the handle is to open the back door. Right after we all secured ourselves, we giggled, knowing how fun this was about to be.

Then the truck started moving.

We all were hanging on for dear life. Somebody said, "this is too fast!", or possibly it was a thought of mine I misinterpreted as someone else speaking, I'm not sure. Either way, it really was too fast. Only about ten seconds and fifteen miles per hour go by and that's when I notice James flying through the air. In retrospect, time had slowed down, I can see him slipping and slowly moving one leg off the truck and attempting to jump to control his fall. Well, he succeeded in one of his goals, but controlling the fall was completely impossible. Time speeds back up and James' feet land on the ground, then his chin is the next thing to hit. He fell over like a tree after it gets cut down. No bending, just rigid straightness, then a bounce or two. 

I was completely stunned. I just saw my friend fall off of a moving vehicle, hit his head on the ground, and not move afterwards. I was a bit worried. I quit worrying about James and worked on tightening my grip. I had my arm worked through the bar, so I wasn't going anywhere. 

Unfortunately all my grip-strengthening made me miss half of Tom's jump. Time slowed down again, and I looked back just as he was in mid-air, posing for his crowd. He had jumped off in real superman style, one arm up in the air, the other back, one leg bent and the knee up in the air, and the other leg bent backwards. Sort of like an exaggerated running position, but completely lacking of grace. I watched Tom sail in the air for what seemed like minutes. I watched him fly, and I saw the glint in his eye as he marvelled in his greatness.

Time sped back up, and Tom fell also. His feet hit first, and unlike James, Tom thought to put his arms out to catch himself. His arms out, he fell, then smacked his head after his arms buckled. Tom bounced slightly less than James, and I held on to the truck for dear life. I just watched two of my friends beaten by the UPS truck, and I was not about to let myself be beaten. 

By now the truck had gone maybe two hundred feet, and apparently the driver saw two limp bodies in the road directly behind his truck, and he slowed very fast. He was almost to a stop when I jumped off and ran towards Tom and James. As I ran I saw the UPS truck driver speed off, probably not wanting to take credit for puting down two high school kids with his truck. As I got near my friends Tom was just starting to stir, and he was laughing a bit. Tom helped James get up and I saw James' face bleeding. Tom pointed it out and James wiped his face with his biker leather jacket. 

Not knowing what to do, and not seeing anyone around who witnessed our UPS truck horror, we started to walk towards James' house. Needing an explanation, Tom and James came up with a great one: they were running around while walking home and ran into each other and fell down. It was so dumb it was almost believable. I wanted to protest, but it wasn't me who got hurt so I let them make up whatever story they wanted to. We were only a few minutes from James' house when Tom stopped his hysterical laughter. He hadn't stopped laughing the whole walk home, and finally he did and proclaimed "my arm hurts". 

Tom was done laughing, we were a block from James' house, James had blood all over his jacket and his chin was bleeding profusely, then the middle school track team ran past us. They stared. Tom was clutching his arm, James' chin was bleeding, and I was just sort of tailing them both. "Yes I'm bleeding!" James proclaimed. The track team stared at us as they ran past, and I looked down hoping I didn't know anybody. 

Tom and I dropped James off, then walked a while and parted ways as he went to his house and I went to mine. I got home, looked around. It was 4:10 and my mother wasn't home and I didn't have anything to do. I turned on my Super Nintendo, played Street Fighter, and wished I had someone to play it with. Damned UPS truck.

Host the Windows Workflow Foundation Designer In Your Own App

Mostly for my own reference, but here is an article on MSDN for hosting the WF design surface in your own application.

You Immerged A Lucky Winner

Come on now... if you're going to spam me to try and convince me I've won 10 million dollars, at least spell your subject correctly!

ScottGu Article on DLINQ

Scott Guthrie has posted part 2 of a series of postings on LINQ. This one gets into DLINQ specifically and definitely starts to show off some of the reasons why you'd want to use it (iterating over your own object collection is neat and all, but doing SQL queries in code without SQL and System.Data is a spectacular demonstration).

I'd still like to see more of the nuts and bolts of how to enable LINQ on your own custom objects, however.