Tuesday, September 6, 2011

Modular JavaScript Tracing


UPDATE (2/18/2012) -- I have moved the source code to Codeplex

Much to my chagrin, I have been doing a LOT of JavaScript debugging lately.  In order to handle multple "levels" of debugging information, I started using Ben Alman’s “ba-debug” javascript library (http://benalman.com/projects/javascript-debug-console-log/).

ba-debug is really nice, but it's unfortunately "global", meaning that the setLevel() method and all the messages are switched with a single global switch.  After using it for a while, I decided I needed something more modular.So, I took his library and modified it heavily.

Being a fan of the .NET System.Diagnostics library, including the TraceSource/SourceSwitch objects, I decided to emulate that somewhat. result is the Trace file I’m including here.

Here’s a brief overview of how to use it.

(NOTE: When I say "module", I mean a closure/module as defined by this -- and many other-- article: www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth)

The idea is that, in some sort of module, you do this:

   var _trace = new Trace('ModuleName');

Then, when you want to trace out any level of diagnostics, you do:

   _trace.debug('ItemsListView - redrawing...');

Supported methods are: error, warn, info, debug, log
The current default level is “error” for all Trace objects.

If you want to increase that level for a particular module, you insert a line like this into your web page:

   Trace.traceLevel('ModuleName', Trace.Levels.log);

Trace.Levels contains all the method names and “off” as options.

Additionally, I continue the functionality that ba-debug gives you so you can set a callback function for Trace messages like this:

    Trace.setCallback(function (args) {
        // do something with the arguments array here.
    },
    true, // force it
    50); //  give me the last 50 at most 

Parameters:
  1. A method that receives an array of the arguments that were passed to the trace message (the level should be the first argument in the array).  Pass null to turn it off
  2. Boolean on whether or not to “force” the callback.  If this is true, it will always call the callback for every message.  Otherwise, it will only call the callback if the browser doesn’t support the “window.console.log” method (at the very least).
  3. A limit to the number of messages to be given up front.  Since messages could have accumulated before you call the callback, there may be a flood of messages right away when you set the callback up, so this will stop you from getting too many messages in the beginning.
The 2nd and 3rd parameters are both optional.

The callback will be called for every existing message (up to the optional "limit") and for all subsequent trace messages.  Note also that the callback does NOT get filtered, so it receives all trace messages.

If there is any expressed interest, I can go over the implementation of the object in detail as well in a follow-up post.

T

Download the whole file here:

Preventing accidental deployments to Azure

Your Azure Roles won't start. You're in the painful loop of "Busy", "Stopped", "Busy"... maybe they're reporting themselves as "unhealthy". It's Azure Deployment Hell and we (those of us who do Windows Azure dev) know it well.

Well, one of the situations that casuses this is easy to prevent: Deploying the wrong configuration to Azure.




In the name of pride, we need to avoid this embarrassing time sink and I'll tell you how. On my current project, the production scenario consists of using a "Production" Service Configuration and an "AzureRelease" Build Configuration. So, I want to make sure that these two things are selected when Packaging/Deploying the software.

So, we turn to MSBuild tasks:

Manually edit the ".ccproj" file and insert the following before the tag.
  1. <PropertyGroup>
  2. <PublishDependsOn>
  3. VerifyAzureRelease;
  4. $(PublishDependsOn);
  5. </PublishDependsOn>
  6. </PropertyGroup>
  7. <Target Name="VerifyAzureRelease" Condition="'$(Configuration)' != 'AzureRelease' Or '$(TargetProfile)' != 'Production'">
  8. <Error Text="Should Not Be Deploying non-AzureRelease Code" ContinueOnError="false" />
  9. </Target>
The tag redefines the standard group to include your new "VerifyAzureRelease" <Target> Task where we test for the conditions we want and spit out an error if they are not fulfilled.



Hopefully, this will help some other unfortunate souls out there from going through this problem as many times as I have.

Tom

Tuesday, August 4, 2009

Redefining DataTemplates for an Inheritance Hierarchy in WPF

I'm working on a project using WPF and MVVM. Given that, my app is very DataTemplate-heavy.

My app is following this pattern:

Every ViewModel class has a default View (CustomControl).

Normally, the template looks like this:

<DataTemplate DataType="{x:Type viewModel:MyViewModel}">
<view:MyView />
</DataTemplate>

This way, there's always a default view (in this case, "MyView"). This works great. So, when you want to change the template in a specific situation, you can just change the DataTemplate for the type "MyViewModel".

Well, I ran across a bit of a problem when I was creating a pluggable architecture which included a set of ICommand-derived objects that would render as a menu. In order to allow naming and separators, I created 2 classes, PlugInAction and PlugInActionSeparator.

So, I started with my templates:

<DataTemplate DataType="{x:Type plugin:PlugInAction}">
<MenuItem Header="{Binding Name}" Command = "{Binding Command}"/>
</DataTemplate>

<DataTemplate DataType="{x:Type plugin:PlugInActionSeparator}">
<Separator />
</DataTemplate>

This way, I bound my actions to a root MenuItem.

<MenuItem
x:Name="actionsMenu"
Header="Actions"
ItemsSource="{Binding Actions}" />

So far, so good. Without anything explicit, the actions will render as menu items or separators based on their data type. Cool. Now, what happens when I want to completely change the way this hierarchy of objects renders? Say... as TextBlocks?

Well, I defined new (non-default) DataTemplates...

<DataTemplate
DataType="{x:Type plugin:PlugInAction}"
x:Key="ActionAsTextTemplate">
<TextBlock Text="{Binding Name}" />
</DataTemplate>

<DataTemplate
DataType="{x:Type plugin:PlugInActionSeparator}"
x:Key="SeparatorAsTextTemplate">
<TextBlock Text="--" />
</DataTemplate>


Now, I want do display my list again... So, I start with an ItemsControl.

If I try:

<ItemsControl
x:Name="actionsControl"
ItemsSource="{Binding Actions}"/>

I get a list of MenuItems and Separators. I need to change the templates.. so, what about this?

<ItemsControl
x:Name="actionsControl"
ItemsSource="{Binding Actions}"
ItemTemplate={..... oh, wait... I can only have one of these.... hmmm...
/>

Code? I guess I could create a DataTemplateSelector class and specify that in my XAML, but I think that's pretty lame. I prefer to leave as much in the XAML as I can for my UI...

The problem is that I want ONE DataTemplate that will handle all types in the hierarchy. I could use DataTriggers based on the Type of the object, but that just makes me want to beat myself with an OO text book.

After thinking long and hard, I figured it out: Nested DataTemplates!

I realized that, through their Resources, DataTemplates can redefine the scope of "default" templates. This means that I can nest new defaults inside a single Default DataTemplate, like this:

<!-- DEFAULT template for ALL Actions -->
<DataTemplate DataType="{x:Type plugin:PlugInAction}" >
<DataTemplate.Resources>
<!-- NEW Default Action Template in the DataTemplate.Resources -->
<DataTemplate DataType="{x:Type plugin:PlugInAction}">
<MenuItem Header="{Binding Name}" Command = "{Binding Command}"/>
</DataTemplate>

<!-- NEW Default Separator Template in the DataTemplate.Resources -->
<DataTemplate DataType="{x:Type plugin:PlugInActionSeparator}">
<Separator />
</DataTemplate>

</DataTemplate.Resources>

<!-- Actual Content Presentation Here -->
<ContentPresenter Content="{Binding}" />
</DataTemplate>

THAT WORKS! So now, my new Text-based template looks like this:

<!-- Text template for ALL Actions -->
<DataTemplate
DataType="{x:Type plugin:PlugInAction}"
x:Key="pluginActionTextTemplateSet" >

<DataTemplate.Resources>
<DataTemplate DataType="{x:Type plugin:PlugInAction}">
<TextBlock Text="{Binding Name}" />
</DataTemplate>

<DataTemplate DataType="{x:Type plugin:PlugInActionSeparator}" >
<TextBlock Text="--" />
</DataTemplate>
</DataTemplate.Resources>

<!-- Content Presentation Here -->
<ContentPresenter Content="{Binding}" />
</DataTemplate>

So now, for the text version, all you'd have to do is:

<ItemsControl
x:Name="actionsAsText"
ItemsSource="{Binding Actions}"
ItemTemplate="{StaticResource pluginActionTextTemplateSet}" />

And there you have it! It redefines a whole hierarchy of DataTemplates.

Ahhh Learning...