Dev Logging

printf("does this work\n");
in

July 2009 - Posts

Referring to Enums (and Other Nested Types) in XAML

This is going to be a brief post, because it’s really just about making the XAML parser happy in an obscure case.

I ran into a problem when I tried to refer to an enum in XAML. This isn’t something you need to do often, but sometimes you need the full, qualified name. Suppose I have a class like this:

public class SuperMario2
{
    public enum Characters
    {
        Mario,
        Luigi,
        Toad,
        Princess
    }
}

Now suppose I have a need to refer to these in XAML. I might try something like this:

{x:Static local:SuperMario2.Characters.Mario}

But the compiler complains:

image

I couldn’t figure out why this wouldn’t work, until I realized that the problem isn’t specific to enums. The problem is that nested types aren’t supported in XAML, and this is just one instance of that. Fortunately, I found this post on MSDN that reveals an undocumented trick to make this work. (Scroll about 3/4 of the way down.) It turns out that what you actually want to do is this:

{x:Static local:SuperMario2+Characters.Mario}
And the compiler is happy.

Hope this helps.

Cascading Implicit Styles in WPF

I was all set to write a post detailing a cumbersome workaround for getting implicit styles to cascade in WPF, when I figured out there’s an easier way. Actually, I think it’s probably common knowledge to a lot of people, but I figured I should post it here in case anyone (like me) is in the dark. (After digging around a little, I couldn’t find anything about this in the Sells book. It’s hinted at on p. 315 of WPF Unleashed, but not stated explicitly.)

Implicit style in WPF are styles you don’t need to refer to by name. They simply apply to all elements in scope belonging to the specified type. An example will help.

Suppose I’m writing a new app, and I decide that every TextBlock should have red text. (Warning: I am not a designer.) I might create a style like this in my App.xaml:

<Application.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Red" />
    </Style>
</Application.Resources>

Note that we do not specify a key on the style. We don’t need to. We do need to make sure to specify the target type; otherwise, WPF can’t know which elements we want this style to apply to. Let’s drop some code in to test that this works:

<StackPanel>
    <Grid>
        <TextBlock Text="where my implicit styles at" />
    </Grid>
    <Grid Grid.Row="1">
        <TextBlock Text="where my implicit styles at" />
    </Grid>
</StackPanel>
If we run the app, we can see that it works:

image

Perfect. Now, suppose I want to add another style to apply only to some of my text. I might scope it like this:

<StackPanel>
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="FontSize" Value="24" />
            </Style>
        </Grid.Resources>
        <TextBlock Text="where my implicit styles at" />
    </Grid>
    <Grid Grid.Row="1">
        <TextBlock Text="where my implicit styles at" />
    </Grid>
</StackPanel>
I’ve created another implicit style to increase the font size of any TextBlocks I place in the top Grid. Let’s try running this and see what happens.

image

Hmm. That’s not quite what we wanted. Our new implicit style seems to have overridden the old one. To understand why, we need to think a little bit about how implicit styles actually work. When we specify a style explicitly, WPF walks up the chain of resource dictionaries and looks for one with the specified key. It returns the first (most local) one it finds. In light of this, it’s not clear how our implicit styles get applied, since we didn’t specify any keys for them. If we think about it a little, we can work it out.

We know the styles have to have some keys; otherwise, how would they fit into the resource dictionaries? What’s not clear is how the key is chosen. One might suspect some randomly generated value to serve as the key, but the answer is much simpler: the target type is the key. (This is mentioned on p. 315 of WPF Unleashed.) Armed with this knowledge, we can easily understand implicit styles. For any elements where the style is not explicitly specified, look for the element’s type in the resource dictionary chain and return the most local one you find. So in our example, we have two such styles: one at the application level and one scoped just to the Grid. It finds the local style first and stops looking.

Now that we have a good understanding of the problem, the solution is pretty obvious. Since we know our implicit style does have a key, we can use it as a base for our new style like this:

<StackPanel>
    <Grid>
        <Grid.Resources>
            <Style TargetType="{x:Type TextBlock}" 
                   BasedOn="{StaticResource {x:Type TextBlock}}">
                <Setter Property="FontSize" Value="24" />
            </Style>
        </Grid.Resources>
        <TextBlock Text="where my implicit styles at" />
    </Grid>
    <Grid Grid.Row="1">
        <TextBlock Text="where my implicit styles at" />
    </Grid>
</StackPanel>

We’ll run the app to make sure it works:

image

Neat.

This isn’t a perfect solution, since we still need to be aware when we’re stomping on our previous styles, but I think the benefits of implicit styles are more than worth the price.

Like I said, I’m sure a lot of people know about this already, but I was oblivious until now, so I thought I’d share.

Hope this helps.

 

EDIT: Just as an addendum, I want to point out that you can have implicit styles with explicit keys. You just need to make sure that the key is the same as it would be if generated implicitly; that is, the key must be the target type. So when you see code like this:

<Application.Resources>
    <Style x:Key="{x:Type TextBlock}" TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Red" />
    </Style>
</Application.Resources>

Understand that this is still an implicit type.

Hope this helps.

AJAX Logging with Exponential Backoff

I’ve been on something of a JavaScript kick lately. Despite its flaws, it’s a really expressive language that lacks you pack a lot of functionality into just a little bit of (still readable!) code. To that end, I spent some time this morning fiddling around with client-side logging. Specifically, I wanted to be able to make AJAX calls to log user actions from the browser back to the server. This wasn’t really driven by any actual project need, but I think it could be potentially useful in a few scenarios. Maybe you have a public-facing app, and you want to test usability; something like this could make it easy to figure out how people are navigating around your site. This could be especially useful if the site is AJAX-heavy already, or if it’s some kind of mash-up with a lot of calls to third parties.

How do we get started? Let’s build a simple page with a button:

<input id="btn" type="button" value="Click Me!" />

And this is how we want to make our calls:

CLARITY.log('clicked the button at ' + new Date());
Note the use of a global object to act as our namespace. This is a good idea because it lets you minimize your footprint on the global namespace. (I learned this from JavaScript master Douglas Crockford, who wrote the best book on the subject I’ve come across.) We’ll hook these up using a little jQuery. Don’t fret if you’re not too familiar with it; just believe me when i tell you this code will bind a callback to the button’s click event:
$(function () {
    $('#btn').click(function () {
        CLARITY.log('clicked the button at ' + new Date());
    });
});
Let’s go take a look at how CLARITY.log is defined.
var CLARITY = {
    log: function (message) {
        //do some logging, probably
    }
};

As in previous examples, we’re taking advantage of JavaScript’s support for object and function literals to create an object with a property (“log”) on it. The log property is mapped to a function that takes a message parameter and (we hope!) does something interesting with it. First, let’s define a web method for our logging function to call:

[WebMethod]
public static void Log(string msg)
{
    // logging happens here
}

I’ve just defined this as a page method. If you were really building something like this out, you might make it a web service call, instead. The difference is pretty transparent from the client-side, so I’m not going to go into it here. I’m also not going to flesh this method out. Server-side logging is a pretty well-explored problem. This is the place to do it.

Let’s take a first cut at our JavaScript logging method:

var CLARITY = {
    log: function (message) {
        $.ajax({
            type: 'POST',
            url: 'Default.aspx/Log',
            data: JSON.stringify({ msg: message }),
            contentType: 'application/json; charset=utf-8',
            dataType: 'json'
        });
    }
};

We’re using jQuery again to make an AJAX call. I like jQuery’s AJAX interface; I think it strikes a good balance between simplicity and giving you complete control over your request. Many of the parameters we specify here are sort of boilerplate for making AJAX calls to ASP.NET (normally, I wrap AJAX calls in a helper method to mitigate this). For more information on this, Dave Ward’s blog is a great resource (this post in particular). The call to JSON.stringify comes from Douglas Crockford’s JSON utility. It’s kind of overkill in this scenario, but I thought I’d point it out, since it’s pretty useful for formatting data for AJAX calls.

To be honest, this is really all we need for logging. However, I thought it might be cool to add some fault tolerance. Maybe (for whatever reason) you’d prefer not to lose any of these logging messages when your server hiccups. We might try to solve that problem with an error handling function that tries again:

var CLARITY = {
    log: function (message) {
        var tryWrite = function () {
            $.ajax({
                type: 'POST',
                url: 'Default.aspx/Log',
                data: JSON.stringify({ msg: message }),
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                error: tryWrite
            });
        }
    }
};

Note that what we’ve done here is wrap our AJAX call in a function that quasi-recursively specifies itself as the error handler for the call. This means that every returned error message will immediately fire off another attempt. Note also that message is not used as a parameter for tryWrite; this is unnecessary because tryWrite creates a closure with message in scope.

This isn’t bad for a first attempt, but it has obvious problems. What if the server is down for more than a few seconds? This is going be firing off logging attempts continuously, and it will only get worse as the user continues to click around the page. This will tie up their bandwidth and bombard your server (once it recovers). It will also increase the CPU strain from their browser (though my testing shows this may be negligible). All bad things.

What can we do differently? We might try adding a timer to at least give a buffer between attempts. Something like this:

var CLARITY = {
    log: function (message) {
        var tryWrite = function () {
            $.ajax({
                type: 'POST',
                url: 'Default.aspx/Log',
                data: JSON.stringify({ msg: message }),
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                error: function () {
                    setTimeout(tryWrite, 5000);
                }
            });
        }
        tryWrite();
    }
};

Here tryWrite is wrapped in a call to setTimeout specifying tryWrite as the callback to be invoked in 5000ms. This will help to some extent. At least we won’t be firing off requests continuously until we succeed. But this still isn’t ideal. As the life of the page wears on, more and more of these will build up, and things will still eventually bog down. We can alleviate these problems with exponential backoff. You’ve probably seen something like this before. The idea is that, as we keep failing, we introduce longer and longer delays between attempts. This helps us to avoid spamming the server. Here’s a simple implementation:

var CLARITY = {
    log: function (message) {
        var delay = 1000, tryWrite;
        tryWrite = function () {
            $.ajax({
                type: 'POST',
                url: 'Default.aspx/Log',
                data: JSON.stringify({ msg: message }),
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                error: function () {
                    setTimeout(tryWrite, delay);
                    delay *= 2;
                }
            });
        }
        tryWrite();
    }
};

Note that, like tryWrite and message, delay is caught up in our closure, making it something like an implicit parameter. Here we use our delay to set our timer and then double the delay for the next (potential) failure. This guarantees that older failures will remain dormant most of the time, keeping the user from making too many extraneous calls.

This is still a fairly naive implementation, but I thought I’d throw it out there as an example. Hopefully someone can get some ideas from it. A more clever version might be more conservative after a failure (or maybe some small number of failures). It could go into a kind of hibernation state where it pings the server periodically and queues incoming messages to be sent once the server is back online. But that’s probably a topic for another post.

Hope this helps.