Jeff and .NET

The .NET musings of Jeff Putz

Sponsors

News

My Sites

Archives

August 2009 - Posts

On constant connectivity and information overload in the online social age

There was a solid post on the Mix blog about just letting go of all the stuff going on in the online social world and getting back to work. It's a subject that I've thought a great deal about lately for a lot of reasons. With a baby on the way, balancing life is important to me. I see friends who can't got five minutes without checking Twitter. Sometimes I worry about whether or not I'm learning the right things. The presence of information itself causes worry.

The thing that I keep coming back to is that there are a number of means to limit what you're exposed to, and they're not always electronic tools. Some people make it their job to find stuff and filter out the unimportant stuff (heck, I'm applying for just such a job). I find that in areas of expertise or interest, your overload is reduced when you find these human filters. The method of transmission is unimportant. I've been filtering out amusement industry news for almost ten years on CoasterBuzz, with a Web site. Remember Web sites? Pages, hypertext, pictures? It doesn't matter if it's a blog, Twitter, Facebook or a newsletter printed on dead trees. Fundamentally, there are still sources that act as information aggregators for things you care about. In the .NET world we have these folks, and they're authors, Microsofties, code project owners, etc.

The bottom line is that I don't think you need to be on 100% of the time trying to follow it all yourself. The trickle down filters work pretty well for most people.

If it's your job to have a higher awareness, then yes, engage at an appropriate level. But at the same time, make sure you're monitoring your peers, and if people report to you, listen to what they have to say. The tools and conduits are only a discovery mechanism, and most of them don't even offer a lot of depth or context. Engaging with people is still necessary.

Don't be lured into the real-time trap to the extent that you feel you have to see every last thing. If it's important, it'll keep coming up, and you'll see it tomorrow. The only exception I can think of is if you're a thought leader, but in those cases, shouldn't you be the originator of the important brain snacks in the first place?

Snow Leopard impressions

I was one of the nerds that went to church, er, the Apple Store, yesterday to pick up Snow Leopard, the OS X update. For $29, I think it's a pretty reasonable upgrade price (are you listening, Windows 7 pricing people?), considering it's an evolutionary upgrade and not feature heavy.

The first win was getting back 10 gigs of space from my hard drive. I thought it was supposed to be only 7, but I'll take what I can get. My Mac Pro's system drive is also where I put my iTunes library, and it's getting crowded.

Booting and shut down is faster, as they said it would be. Time Machine backups are crazy fast now, where it used to be that the icon would swirl for ages without anything new to even backup. Everything in Finder seems snappier, though it's hard to quantify it. The slider in Finder windows for icon size is a welcome addition. Spotlight seems faster. Stack navigation out of the dock is far, far better now that it scrolls.

I wonder if they haven't tweaked memory management. Parallels seems to be more responsive when I've also got Photoshop and/or Aperture open. Perhaps it's the CPU core management. It's all that under the hood stuff that's hard to measure.

Lots of little tweaks that I've read about, but not encountered, are intriguing. That it can figure out what time zone I'm in and adjust the clock is really cool. Definitely a worthy and inexpensive upgrade. And did I mention there are no install keys or other such nonsense?

Twitter: I begrudgingly get it

More than two years ago, I made a post on here about how I didn't get Twitter. It's one of the most popular posts I've ever made for some reason, which perhaps I'm not proud of. I been meaning to follow up on that for, well, at least a year, because obviously things have changed a great deal.

My view was skewed in some respects because I never looked at it much outside of the context of technology circles. In its earlier days, Twitter was dominated by attention whoring tech pundits, and that seemed boring to me. These days, it enjoys more widespread use, but there are still some critical points that measure how effective it is as a communications medium, and furthermore, it serves different people different ways.

That 80% of people never post anything and have few followers indicates to me that a lot of people are tending a flock, and that's OK. In reality, this is a lot like any other Internet media we have, whether it be blogs or Web sites as a whole. It's a minority that publishes content while the vast majority are consumers only. This has been true for a long time. In fact, the forums on my sites over the years have always been a 95% read-only affair. Many view, few post.

The development community has a much more robust two-way audience. Its effectiveness is rooted in using the right tools, like TweetDeck, to follow not individuals, but hash tags and search terms that matter to you. You get and give help pretty quickly. There's a lot of re-tweet noise, unfortunately.

The bigger story is that it has finally achieved a more critical mass, making it useful by volume. So these days, yes, I'll admit that Twitter is useful if you cast out the attention whoring. Yesterday, I got RT'd by @scottgu, and within an hour, added 15 new followers. Can't argue with that as a means to get your words out. (Wonderfalls reference!)

Under the covers of HTML helpers in ASP.NET MVC

Coming from the Webforms world, the thing you might miss most when using ASP.NET MVC is the ability to create rich Web controls that generate all kinds of markup and do nifty things. HTML helpers do similar work, even if their plumbing is different, and because we can see the full source code of the MVC framework, we can explore their innards. Keep in mind that this isn't a straight analog, since there are no events to worry about. The helpers have one responsibility, and that's to display the right data as HTML. The truth is that you don't need to know any of this, as the existing helpers probably meet your needs 95% of the time. But in the event you want to build your own helpers for the purpose of encapsulating some kind of common, reusable markup (or keep your views cleaner), you'll benefit from understanding what goes on inside the black box.

By the way, if you've never looked, I'd strongly encourage you to download and poke around the MVC source code. I know that you're probably expecting a big mess of overly abstract pieces that you can't follow, but it's one of the cleanest and easiest to understand projects I've ever seen. They did a really great job with this, and the whole thing weighs in at only 10,000 lines of code, and 500 of that is just resource stuff.

HTML helpers generally do the dumb work of creating markup. They save you the hassle of making input tags or links or whatever. But the other thing they do, the magic, if you will, is process model state. Controller has a property called ModelState, which is an instance of the ModelStateDictionary class. This is passed along to the view in a context object. Your views inherit from ViewPage, which has an instance of HtmlHelper (the Html property). Got all that? I'm first trying to illustrate how data gets from the controller to the view, where the helpers do their thing. The controller is where you process input via model binding and validate, and this is what gets the model state involved. It's a different topic from what we're discussing here, but hopefully you've had exposure to it and understand the goodness that makes working with input and models so easy. (Read up on the tutorials on the official site, specifically the stuff about model binders and validation.)

The HtmlHelper class by itself doesn't do much to generate markup. It does have the anti-forgery token code in it, as well as some static methods to create route links (I'm not sure I understand the decision to put them there), but otherwise, the creation of markup lies in several other classes filled with extension methods to HtmlHelper, found in the System.Web.Mvc.Html namespace. They're grouped into classes for input, forms, links, selection controls, validation, etc. Since they're all extension methods, they have access to the data in the HtmlHelper instance (the Html property of the view), so that means they can work with the model state and virtually anything else available in the view. As extension methods, you can hopefully see that you can build your own to generate most any HTML you can think of.

Let's start with the simplest example: text boxes. Found in the InputExtensions class, there are several overloads:

public static string TextBox(this HtmlHelper htmlHelper, string name) {
    return TextBox(htmlHelper, name, null /* value */);
}

public static string TextBox(this HtmlHelper htmlHelper, string name, object value) {
    return TextBox(htmlHelper, name, value, (object)null /* htmlAttributes */);
}

public static string TextBox(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes) {
    return TextBox(htmlHelper, name, value, new RouteValueDictionary(htmlAttributes));
}

public static string TextBox(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes) {
    return InputHelper(htmlHelper, InputType.Text, name, value, (value == null) /* useViewData */, false /* isChecked */, true /* setId */, true /* isExplicitValue */, htmlAttributes);
}

The MVC team is obviously thinking of your well being in allowing you to provide as much, or little, as you need to make that text box. The real meat comes in the last overload, which calls another extension method in the class named InputHelper. This is where we finally start to make some HTML.

Before we get into that method, consider what the typical code looks like in your view to make a text box. It may look something like this in a strongly typed view that has a "Name" property on the Model:

<%= Html.TextBox("Name", null, new { @class = "textField" })%>

This says, "Create a text box on the 'Name' property, don't give it a value, and while you're at it, add a class attribute with the value 'textField'." This corresponds to the third overload of the available extension methods. In essence, we're calling:

InputHelper(Html /* instance of HtmlHelper on the view */, InputType.Text, "Name", null, (null == null) /* useViewData */, false /* isChecked */, true /* setId */, true /* isExplicitValue */, new { @class = "textField" });

Pretty well-factored code! This works with the extension methods for check boxes, hidden fields, passwords and radio buttons. Note the fifth parameter, the Boolean useViewData parameter. What this says in English is, "If the value given is null, then use the view data."

Here's the InputHelper code, with some of the non-relevant parts taken out for the purpose of this example.

private static string InputHelper(this HtmlHelper htmlHelper, InputType inputType, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, IDictionary<string, object> htmlAttributes) {
    if (String.IsNullOrEmpty(name)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
    }

    TagBuilder tagBuilder = new TagBuilder("input");
    tagBuilder.MergeAttributes(htmlAttributes);
    tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
    tagBuilder.MergeAttribute("name", name, true);

    string valueParameter = Convert.ToString(value, CultureInfo.CurrentCulture);
    bool usedModelState = false;

    switch (inputType) {
        case InputType.CheckBox:
            ...
        case InputType.Radio:
            ...
        case InputType.Password:
            ...
        default:
            string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
            tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue);
            break;
    }

    if (setId) {
        tagBuilder.GenerateId(name);
    }

    // If there are any errors for a named field, we add the css attribute.
    ModelState modelState;
    if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState)) {
        if (modelState.Errors.Count > 0) {
            tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
        }
    }

    ...

    return tagBuilder.ToString(TagRenderMode.SelfClosing);
}

Now we can dig in. To get things started, the method creates a TagBuilder object, which is used across most (maybe all) of the helper extension methods. Check out the source if you get a chance. It encapsulates the process of creating the tag and its attributes, and does all of the boring string formatting work. It creates an ID, checks for duplicate attributes, sets the innards of a non-self-closing tag, etc. The one important thing to note is that it also concatenates CSS classes (important for the validation part, as we'll see in a minute).

The switch block trickles down to the default, where it uses the GetModelStateValue method of the HtmlHelper to see if there is a value to drop into the text box. That method returns the value from the model if it's there and matches the type String (since we're using text here), otherwise it returns null. The next line calls up the TagBuilder to add a value attribute to our tag. What it puts there depends on what's available. You may recall from the documentation or books that the first thing it tries to do is use the value stored in ViewData.ModelState, if that's available, and that's what the EvalString method of HtmlHelper does. If that's not available, it goes with the value we passed in from the markup in the view. Since we specified null, it won't show anything, even if there was no value in model state. Again, read up on how model state is used to work with validation to repopulate a view with the values entered before posting the form to the controller.

After creating an id attribute for the tag, the method finally gets to the validation piece. Recall that fields that don't validate have their helpers render the CSS class "input-validation-error" in addition to any style classes you've specified. That happens here by checking to see if there are any errors associated with the model state of this field.

Finally, the method uses TagBuilder to build out the string of HTML to drop into the view. If you look around at the other helper methods, you'll find that they all work similarly to this.

To summarize, the helpers do this work:

  • Use TagBuilder to create the HTML tag
  • Pass in the attributes
  • Figure out what the value of the HTML control will be
  • Give the tag an id
  • If there are validation errors, apply the predetermined CSS class in addition to others specified
  • Output the string of HTML into the view
As I said before, I think the code is surprisingly easy to follow, and once you understand what's going on under the covers, and how it interacts with model state, you're in a good position to start working your own helpers.

 

Windows 7 in Parallels on a Mac

It's no secret that I'm all about Mac hardware and living in OS X when I'm not developing .NET stuff. It's also no secret that I thought Vista was too much of a dog to use, and have been sticking to Windows XP because of that. And in all fairness, I suppose some of that bias is rooted in the fact that Vista was a nightmare on my wife's old laptop, but I did experiment a little with it in a Parallels VM, and it just felt clunky. The outright bizarre dialogs with a chapter of text for everything also threw me for a loop.

People seemed pretty enthusiastic about Windows 7 though, so I thought I'd give it a go using Parallels 4, which lists 7 support as "experimental." Well, it's a pretty solid experiment so far!

Install went perfectly, and pretty quickly, without the silly self-serving ads describing how great Windows is. Once the install was done, the first win is the boot time, which is frankly awesome. This is after installing Visual Studio, SQL and such. Visual Studio seems to start faster as well, but I'm still convinced that this is caused by some kind of "cache rot" with ReSharper, since turning it off seems to yield faster start up times.

I prefer coherence mode in Parallels, since I typically run Adium, Firefox for e-mail and CoasterBuzz Feed in the background while working. It generally seems to work pretty well, and dock icons are much nicer than they were in XP when a high-res version is available. Trying to drag a window around at high speed is still not a pretty affair, but generally I don't do that in real life anyway. Drag-and-drop between an Explorer window and the OS X desktop works fine too.

So my early impression is that at the very least, it's a substantial improvement over Vista in terms of general perceived performance. I'll have to experiment some more and see how it affects battery life, which is something largely left to the folks at Parallels, I suspect. The question becomes, "What do I get that I don't get in XP?" I'm sure that's what IT departments everywhere also ask. I don't have a good answer for that other than I want the pretty, and I want to feel like everything is a bit zippier.

Poking around control panels and properties dialogs and such, it does appear that the Windows team has made great strides in getting away from the ridiculous verbosity of Vista, thank God. Stuff feels like it was built by user interface designers and not engineers who "know" what people want. I'm really happy to see this corner turned.

Be more than a developer

I do love a spirited debate. It seems that everyone I've had a relationship with suggests that I should have been a litigator because I love to argue. And hey, if practicing law wasn't 95% research and 5% arguing, I'd be all over that.

That said, I think it's important to have a general awareness of the world, especially in business. A lot of techies and developers don't seem interested in that, unfortunately. Take this recent random Twitter exchange:

someguy: Why is #Zune website www.zune.net made in flash and not silverlight?...
@jeffputz: Why do people ask this question over and over? Because for a marketing site to move product you use what's most installed.
someguy: well then they could have it done in both SL as well as Flash.. atleast show it to the people who have it installd...
@jeffputz: For what purpose? How does that sell more Zunes?
someguy: true but atleast those blogs criticizing MS for it, wouldnt be written :-) ... it shouldnt always be ONLY marketing..

I probably wasn't being very diplomatic in this case, but my intention was to challenge him on the reasoning for making his initial statement. In this case, perhaps he was baiting some goofy point like, "Well if Microsoft doesn't use Silverlight themselves, then what does that say about it?" Great scandal? No, I think they just want to sell more Zunes, and that has nothing to do with platform religion or their belief in the product.

Every time I've hired consultants for project work, regardless of how trivial or complex, I've made it a point to try and get in their head to see if they understand just the fundamentals of business, and if they can work and design software with business goals in mind. I can teach someone how to use dependency injection or the control lifecycle, but I strongly believe that greater awareness about the business is a lot harder to instill in someone.

I freely admit that I'm a gear head (or is it bit head?) and love to mess with stuff. But I also believe that it's critical in your every day work to ask yourself if what you're doing adds value. It's OK to not be sure about the value in cases where you're taking a risk. I'm not suggesting you have to buckle down and not try new things, but if you want to rewrite some component just because, ask yourself if there's some return you'll get for that action, and if not, I'd do something else.

The best developers have a keen awareness of the bigger picture across other disciplines. You can be more than just a heads-down code monkey.

Silverlight vs. Flash and other pundit fodder

Yet another blog post has hit the airwaves and become all atwitter about Flash and Silverlight, the competition, Adobe vs. Silverlight, etc. While this makes for interesting pundit fodder, I just think that the people observing the situation don't really, well, get the situation.

Earlier this year, just after Mix in Las Vegas, I was asked by a client about what Silverlight is, because he read about how it was supposed to be "Microsoft's Flash killer." If I had a dime for every headline like that, right? I told him that there were different perspectives on what its role was, but killer wasn't one of them in my mind. I believe the root of the difference truly comes from the history behind Silverlight and Flash.

Flash began its life as a way to make stuff dance on a Web page. Let's not kid ourselves, it was a cosmetic thing. Over time, it introduced more UI elements and a scripting language to make it more than just a timeline of moving objects. Silverlight, by comparison, set out to be a great many things, rooted in its big brother, WPF, a UI technology intended to (in my view) kill the awful Windows Forms. Remember that Silverlight was once called "WPF/E" for "WPF Everywhere." I think these two technologies started from two different angles, and today can do many of the same things. Yet their origins still largely dictate their dominant use.

Initially, I felt that Silverlight's greatest strength was the ability to build line-of-business apps that didn't suck, and deployment was a snap. If you've ever worked in a corporate environment where dozens of barely maintained Windows Forms apps get passed around on network shares or installed by phantom IT forces, then you know what I'm talking about. Learn a few important concepts about WPF/Silverlight, and you're well on your way to leveraging hoards of .NET code monkeys to make good stuff. This is hardly the goal of Flash.

When you really let go of the punditry, link baiting and scandalous headlines, and God forbid put on your business hat, you see that in the current universe, Flash and Silverlight seem intended for two different things. I'd never put Silverlight on the front page of a marketing site because the penetration rate. But on the other hand, you bet I'm using it today to handle file uploading deeper in a site. Then I added a simple out-of-browser app for my most passionate audience, and guess what my Silverlight 3 penetration rate is now? 20%! Add another 20% for version 2.

With the forthcoming Winter Olympics being broadcast via Silverlight, I suspect we'll see another bump in penetration. But all of the predictions about a winner are silly. Advertising will be Flash for a very long time to come. Silverlight will be the dominant line-of-business platform on corporate networks as soon as skillsets align with it. I'll push my audiences on public sites toward it because they're passionate enough to want the content it brings.

So what has Microsoft truly accomplished? They put browser-based rich UI (and dare I say, animation) in the hands of a bazillion .NET developers, using tools they already know. My prediction is not that there are clear winners here, but a long-term coexistence. The versus debate causes a needless holy war that non-technical management types will read and want a VHS vs. Betamax prediction instead of leaning toward the right tools for the job.

Charity fund raiser: Give Kids The World

It's hard to ask people for money when a lot of folks are having a hard time even looking out for themselves, but I'm going to give it a shot anyway. CoasterBuzz, one of the sites I run, is teaming up with Cedar Point (a huge amusement park west of Cleveland) to raise money for Give Kids The World. As described on the CoasterBuzz event page:

Give Kids The World Village, in Orlando, Florida, is a 70-acre resort that offers children with life-threatening illness and their families an opportunity to enjoy a cost-free and worry-free experience, in as little as 24 hours if necessary. In a coordinated effort with world-class theme parks, thousands of volunteers and generous donations, Give Kids The World helps these families put illness in the background while kids get a chance to just be kids and enjoy the attractions of Central Florida.

If you have a few bucks to spare, it would be incredibly awesome if you could donate to this charity. You can donate here:

http://www.firstgiving.com/jeffputz

And no, I'm not eligible to win the fundraising prizes, since I run the site. :) Unfortunately, many of these kids will never see a better economy, and that's why it's critical that GKTW continues to thrive. Your donation will be greatly appreciated, no matter what the amount!

Posted: Aug 10 2009, 04:21 PM by Jeff | with no comments
Filed under:
Book project follow up

I'm still getting e-mail about the book I started to write and posted chapters for. Now that ScottGu has formally announced the progress on v2 of ASP.NET MVC, hopefully it's more obvious now why I put off the project. As I said previously, I had to prioritize with some other projects that would yield income sooner, and I was concerned with the speed to market with which I could get it out there (read: not fast enough). I also knew about the second iteration in the pipe, which made it a no-brainer to put it off.

As I said, that content will find some kind of home eventually. I still think that the mid-level experience developers aren't being served adequately, especially the tens of thousands in small shops, indie contractors, etc. I'm still trying to get my head around what that means and what the solution might be. If you're a part of that group, trying to latch on to the latest and greatest, I'd like to hear from you!

CoasterBuzz Feed: A Silverlight 3 story

A few weeks ago, I decided to jump in and do a "science project" with Silverlight 3. My prior experiences with Silverlight involved a simple DeepZoom viewer that happened to use a Web service as its tile source, and a file uploader that cut up multiple files and sent them to the server. The latter is being used as a part of a plugin to the forum on CoasterBuzz, and it has served me very well. With the out-of-browser option on Silverlight 3, I figured it was a perfect chance to give my audience another reason to stalk the site, using a small "feed" app that they could run on the desktop.

This is a write-up of the process I used to get the product out. It's a very small project, but I realize that the process isn't all that different from a large one for me. The only thing different is that in this case I don't have any particular game plan in terms of use cases/stories/features, as I would for something large.

I had a few design goals in mind up front. I wanted to iterate quickly and just ship something, to club members first. (CoasterBuzz Club is the paid, ad-free experience for the hardcore roller coaster nerds who form the core of the audience.) I was less worried about coding things "right" than I was making something function. I had already learned my proper lessons around dependency properties and data binding and layout and all of the things that made Silverlight cool, so I'd worry about polish once it worked. That's the benefit of a small project. Secondary goals included the OOB deployment and some trivial use of the new 3D projection just because.

First sketch mess

As with most projects, and especially a relatively small one like this, I started by just sketching and scribbling. UI, architecture, data, whatever... just get it out of my head and organized.

First UI sketchThe nice thing about paper is that it's pretty cheap, so whatever you decide isn't worth your time, you scribble out or throw away. I started with a simple sketch of what I thought the UI should look like. I wanted to syndicate new forum topics and posts, news items and additions to the photo database. Each one would simply appear shortly after the event on the client, and clicking on any particular item would take you there on the site.

At this point, I got a little into the weeds with data structures and implementation details, even though I wasn't ready for that. Ironically, my motivation for feeling out UI first is so that I don't end up placing constraints on myself that are founded in implementation details. I stepped back and got to thinking about architecture instead. This is all pretty simple stuff here. No need to over-think it.

Right away, I saw some potential for reuse, and at that point already started to toss away the just-get-it-working mentality. I suspect that's the result of having worked on various frameworks before. I've worked on projects where you would record all kinds of data, often not even knowing how or if it would be used, so making this kind of generic, both in terms of the data coming in and the way it was consumed, seemed like a good idea.

Feed architecture

I wanted to have some kind of publisher that could accept input from anything, and at that point decided to throw any kind of strongly-typed data out the window. Yes, this eliminated any kind of compile-time assurance that I was recording the right things, but I saw no compelling reason to do anything other than record some kind of event type name, a time stamp, and a spoke table of various properties (user names, post ID's, whatever). If I came up with a compelling reason, I'd worry about it at some refactoring point. So the deployed service simply sent a List<EventItem> collection, and each EventItem had an event type indicated by a string, a time stamp and a Dictionary<string, string> for the spoke data. Easy to serialize, easy to digest, very flexible.

I also wanted the publisher to not worry about what it was recording the data to. So it simply takes a collection of IPublisher objects that do whatever they do. The obvious one is to record to a database, but I figured that I could just as easily publish to Facebook or Twitter. In fact, those will probably be among the next things I do.

I still felt like I wanted to contain a few things in one convenient package though, for reuse. So I did a Visual Studio project that included the publisher, a publisher interface implementation to the database, and a fairly abstract WCF service that could spit out whatever was in the database. I started to consider server-side user options and maybe even specific authenticated user data, but decided to leave that out for now. Just focus on event publishing! The pieces that landed in this project are surrounded by the dotted line in the sketch.

To this point I really never used WCF, but understood it conceptually. And sure enough, it's really easy to use, and you don't have to get into that mess with proxy classes and all of that nonsense. (Sidebar: Even for this simple service arrangement, using the VS "Add Web reference..." proxy generation added enough code to make the .xap 3k larger than using the straight C# code to create bindings and a channel. It's worth it to learn to make your own asynchronous consumer on the client.) I didn't really care to use config files for setting up the address, binding and contract, so I did that in code in the Silverlight client. I also wanted to make deployment easy enough so that it didn't care if it was running on my local machine or the server. And since the OOB app has no reference to the HTML/Javascript bridge in the host page, I eventually discovered that you can use Application.Current.Host.Source (a Uri object) to find the domain and what not that the app was installed from. Easy since the service the client calls would live on the same box.

Feed screen shotThe first attempt was just to get the app pulling and displaying data. That actually went pretty fast. By using a UserControl as the DataTemplate of an ItemsControl, I could have the UserControl act as a factory to load the appropriate UserControl for an item type. Simple switch/case, no problem. The ItemsControl is bound to an ObservableCollection fed by calls to the Web service.

With this basic functionality in place, I felt like the hardest work was done. Next I wanted to have a small control panel that might allow the user to filter the kind of items displayed, but for now figured that version number and status "lights" about connectivity were adequate. And what better place to try projection?

This is where the tooling inside of Visual Studio started to annoy me. I don't need a drag-and-drop design surface, but it's nice to see that when you tweak some XAML, the result is there to see. Rebuilding every time is a pain in the ass I'd rather not endure. I finally gave in and used the Expression Blend 3 RC. Admittedly, that made trying out the animation of the projection transitions a lot easier to see.

The important lesson learned about animation is that it simply holds the last position, and is in fact still "running" when it's done. The various display properties have not actually changed, and if you call Stop() on the animation, you'll see this is the case. You need a little extra plumbing to set objects to their end state, especially if you intend to reverse the animation.

Debugging buttonMy last step was to engage in the OOB installation. I used Tim Heuer's video on implementing out-of-browser, along with the connectivity and update checking. Wow did Microsoft get this right. My only complaint is that there's no particularly simple way to debug when you're out of the browser like this. It's cumbersome to rebuild, relaunch, see the update, relaunch again, then attach the debugger to the host process. To combat this, I built in a button that would launch the proper app while still in the browser, but only if it was running from localhost.

Once the club members had their chance to hack away at it for awhile, I did find some problems. One of them was that the WCF service, when using the binary binding, has an 8k message limit. The client was choking when it started up and had to receive a large number of feed items.

One of the things that I like to do with new features is a short video that explains stuff. I did this with the "day in pictures" forum that allows you to upload photos into the forum via a Silverlight app (video here) and it went over pretty well. I did it for the feed as well. Notice that YouTube is hosting much higher quality these days?

In any case, the "finished" product is live. I say "finished" because I'm sure I'll add filtering for the various event types at some point. Getting these bits out of the way, I feel much better equipped for more ambitious projects when they arise.

More Posts