Glimpse 1.8.0 released – Async Support

In an effort not to leave too much time between releases, we happy to announce that as of today, Glimpse now supports capturing details that occur within Async operations. With the advent of .NET 4.5 it is easier than ever to take advantage of Async tasks to perform out-of-process or long running tasks.

Before now, Glimpse hasn’t been able to see the details of what occurs within these tasks, but with the help of the community, now we can! Unless you have specific needs, chances are the biggest difference you will see in your day-to-day usage of Glimpse, is that we can see everything that happens in Async queries that ADO/EF perform.

Release Notes

  • Glimpse.Core – Welterweight release 1.8.0
    • Support for capturing data on Async operations
    • Added Status Code to ajax and history tabs
    • Client now sensibly interpret friendly titles out of object keys
    • Client updated to render array lists as array of objects rather than array of arrays
    • Fixed bug where timeline couldn’t cope with long strings as the event title
  • Glimpse.ASP.NET – Welterweight release 1.6.0
    • Total rewrite of the Request tab to include additional request info
    • Removed Server tab as it’s now obsolete given the Request tab update
  • Glimpse.MVC* – Featherweight release 1.5.1
    • Fix version number inconsistency between MVC packages
    • Fix version information in MVC5
  • Glimpse.WebForms – Featherweight release 1.0.2
    • Greater support for many more control ViewState’s
    • Fixed circular reference bug that could be caused by some controls ViewState
    • Fixed bug which could cause trace output to be rendered in the page
  • Glimpse.ADO – Welterweight release 1.7.0
    • Support for Async queries
    • Added async indicator column to the SQL tab
    • Minor adjustment to the width of the transaction title column in SQL tab
  • Glimpse.EF* – Welterweight release 1.6.0
    • Support for Async queries
    • Added async indicator column to the SQL tab

Special Thanks
In terms of pull requests, I have to say a big thanks to:

And for the great issue reports, I want to thank:

Release Details
Well I think that is a wrap. For a full list of changes, issues and commits see below:

Thanks to everyone involved and enjoy the release!

Glimpse 1.7.0 released – First class WebForms support & MVC5

Its been a while, but we have been hard at work version 2.0 (more on that later) and producing some new packages – which we are releasing TODAY! These new packages represent the first new packages we have released since Entity Framework support went out the door in March and I think you are in for a real treat.

We have released two new packages today and a bunch of other minor features/fixes. Here are the highlights:

  • Glimpse.WebForms Released:
    • Amazing ViewState support
    • New Control Tree and Page Life Cycle Tabs
    • Deep HUD integration
  • Glimpse.MVC5 Released:
    • All the tabs you previously had with MVC4
    • Support for attribute driven routes

WebForms support

Glimpse.WebForms is a revolutionary step forward in the way we will work with WebForms in the future. For years, many have struggled to understand how WebForms works, what is responsible for ViewState bloat or if you even have a ViewState issue. As of today, we finally have the tools we need to know exactly how WebForms is running and what is responsible for problems we may be experiencing.

ViewState Reimagined
We have taken a crack at totally re-imagining what we have come to expect when working with ViewState.
ViewStatePreview

As you can see, without any ceremony, Glimpse shows you all of your controls and the ViewState that each control has generated. This is insight, that until now, we have only been able to dream about.

Current Pain:
For most, understanding/controlling ViewState has always been a struggle. When we think about ViewState, most think about a hidden input in our HTML that contains a blob of text which does something for our site.

ViewStateRaw

Mostly, when its running smoothly, ViewState isn’t one of those concerns that we think about every day. But at some point, we discover that amount of data being sent down to the page in ViewState growing out of control – ViewState bloat.

Solution Seeking:
When this occurs we typically turn to Google, which brings up a trusty StackOverflow article that will give us the answer of where to start – Seeking advice on de-bloating asp.net 3.5. Unfortunately though, the top answer is to:

“Try ASP.NET MVC or one of the other MVC web frameworks for .NET”

For most this is a very unhelpful and disappointing answer. Not everyone has the “luxury” to rewrite their whole site just to solve this one problem.

ViewState De-coders:
So, after some more searching we discover that there is a way of taking the ViewState text and running it through a de-coder:
ViewStateDecoded
At first glance, we think we are getting somewhere, but we soon discover that we have no idea what the data means or what control is responsible for generating it. Note: all this assumes that we aren’t running out WebForms site in .NET 4.5, as ViewState is now encrypted. Hence, making the only tools we had useless.

Enter Glimpse!
Glimpse is in a unique position to try and solve many of the problems we have around ViewState. Since we run on the server, we are able to see the ViewState before it is encrypted and we are even able to determine which server control generated the state.

Here is a specific example of what Glimpse is able to bring to the table:

Here is a specific example of what Glimpse is able to bring to the table

1) Master Page State,   2) Cart Count State   and   3) List View State

vs.
1) Master Page State

1) Master Page State

2) Cart Count State

2) Cart Count State

3) List View State

3) List View State

Strongly Typed ViewState:
When looking at the above screen shots of Glimpse, its easy to miss the way in which we display the data. As it turns out the ViewState object model is designed for the systems to process (not humans) and is optimised for minimum payload size. Hence, if we don’t perform any additional logic, the below is what you would see:

"Untyped ViewState data"

“Untyped ViewState data”

When looking at this, you’d be easily forgiven for finding it better than what a decoder provides (since we know what ViewState belongs to what controls), but it still doesn’t match our mental model of what we think the data should look like.

Hence, we decided to take a crack at making that better too. We discovered that since we know which server control generated the ViewState, we are able to present the data in a format that “strongly types” it on a control by control basis. This technique changes the output we can show you dramatically. Resulting in the below:
ViewStateTyped

No more guessing:
With the advent of this capability, you will no longer have to guess what controls generated which ViewState data. Glimpse makes this completely transparent and understandable to everyone.

Control Tree
As you would have guessed by looking at the above screenshots, we are able to present you the Control Tree Hierarchy as well. This structure is used by the WebForms framework to generate the HTML that you see on your page. This may look familiar from the Trace.axd days, but as discussed above, Glimpse has taken it up a notch.

Here is a list of what we show you out of the box:

  • Control Id: This is the server-side ID that is generated by the framework for your control. If you specifically set an ID, then the system will display that name instead.
  • Type: The system Type of the rendered control.
  • Render (w/ children): The size in bytes of the HTML generated by the control and its children.
  • ViewState: The size in bytes of the ViewState generated directly by the control.
  • ControlState: The size in bytes of the ControlState generated directly by the control.

Page Life Cycle
In sites using WebForms, the page life cycle is a series of events which fire on every page and has a very defined sequence. As fate would have it, its one of those things that we rarely remember exactly how and when they are supposed to execute. Glimpse makes this transparent by showing you which events occurred, their timings and offsets.

Here is what we show you out of the box:
PafeLifeCycle

Trace Tab:
Beyond showing these events in the Page Life Cycle tab, we automatically trace out the Begin and End notifications for each event to the Trace Tab. This means that when ever you write out data via either of the following methods, it will show up between the relevant Page Life Cycle trace messages:
System.Diagnostics.Trace.Write("This is a trace Message");
or
System.Web.HttpContext.Current.Trace.Write("This is another trace Message");

With that, here is the final result:
PageLifeCycleTrace

Timeline Tab:
Besides just adding this data to the Trace tab, we have included the events within the timeline tab. This means that when you have other timing events (like database access) occurring, you will be able to visual see exactly what is happening.
WebFormsTimeline

WebForms in HUD
If all this wasn’t enough, we decided to make sure the most important ViewState and Page Life Cycle data be shown within HUD (heads up display).
WebFormsHUD

HUD is specifically designed to stay at the bottom of every page and stick with you as you go about your normal development effort. Taking this into account we show you the following out of the box, without having to click, mouseover or select anything:

  • Load: Time between Begin PreLoad and End LoadComplete.
  • Render: Time between Begin PreRender and End Render (including SaveState events).
  • ViewState: Total size in bytes that the page has stored as ViewState.

If you are used to the Glimpse.MVC packages, the Load and Render times are similar to the Action and View times that we show you. But for those who use ViewState, knowing exactly what each page is generating within HUD is huge. This one figure alone is invaluable, let alone the rest of what this package brings.

HUD popup view
HUD also allows us to show a more detailed view of the most important information we have in the form a popup that appears when you mouse over a section. For WebForms, we have taken advantage of this to show a contextual view of the Page Life Cycle information along with any database activity you may have performed.

WebFormsHUDPopup

Beyond seeing what we saw in the mini view, we have added the Page Life Cycle events and included exactly different database events have occurred. This allows you to see straight away what events are taking the longest and what queries are occurring where. Prior to Glimpse.Webforms, building this picture was virtual impossible.

MVC5 support

The other package we are releasing today is Glimpse.MVC5. This is an incremental release for MVC and designed to match the latest release of ASP.NET MVC. With this release, you will get all the usual goodness you have come to expect from Glimpse.MVC*. The release also contains support for the new attribute driven routing that MVC5 brings to the table.

Attribute Drive Routing

Attribute Drive Routing

Glimpse Route Tab

Glimpse Route Tab

Release Notes

Beyond everything I have already covered in the above, this release includes a number of updates and fixes for a variety of issues. This release contains updates to following packages:

  • Glimpse.Core – Welterweight release 1.7.0
    • Improvement which allows Glimpse.axd to be protected by custom security policies
    • Fix History tab causing issues when invalid characters are present in a Session Name
    • Performance improvement Ensure client shell is forced into a new rendering layer within browser
    • Update Visual Studio solution to VS2013
    • Improvement to client which adds support for paddings when rendering structured layouts
    • Improvement to client to make array rendering more resilient
    • Improvement to client which ensures table headers have the correct default style applied
    • Improvement to client which brings better error management in master rendering engine
    • Switch assemblies to be marked as CLS-compliant
    • Switch Glimpse.axd over to use templates for generating the configuration resource
    • Ensure that Glimpse ignores BrowserLink’s preflight requests
    • Make sure HUD only displays Ajax requests that have a Glimpse Payload
  • Glimpse.AspNet – Welterweight release 1.5.0
    • Fix bug which caused the writing of log data during AppDomain unloading not to appear
    • Fix bug which meant that in some cases the end body tag couldn’t be located
    • Switch assemblies to be marked as CLS-compliant
  • Glimpse.MVC* – Middleweight release 1.5.0
    • Implemented support for MVC5
    • Switch assemblies to be marked as CLS-compliant
  • Glimpse.WebForms – Heavyweight release 1.0.0
    • Advent of the Control Tree and Page Life Cycle tabs
    • WebForms data now shows up in HUD (including ViewState size), in Timeline Tab and Trace Tab
  • Glimpse.Ado – Flyweight release 1.6.0
    • Improved SQL Tab layout so that the overall stats are displayed at the tab
    • Switch assemblies to be marked as CLS-compliant
  • Glimpse.Ef* – Bantamweight release 1.5.0
    • Switch assemblies to be marked as CLS-compliant

In terms of pull requests, I have to say a big thanks to:

  • Christophe Gijbels
    • #586 Securing default configuration resource
    • #563 Changed in-code html generation to template approach for configuration resource
    • #555 Fixed PreBodyTagFilter partial writes handling
  • Kelly Stuard
    • #565 Making Glimpse CLS-compliant.
    • #564 Fix race condition between message bus and subscribers
  • Jeff Burn
    • #580 Fix HUD for WebForms with no viewstate

And for the great issue reports, I want to thank:

We also had a few users who really hammered on early builds of the WebForms package to ensure that it would work well for the whole community. Thanks a million to:

Well I think that is a wrap. For a full list of changes, issues and commits see below:

Let us know if you have any thoughts or comments and I hope you enjoy this release.

Glimpse 1.6.1 released

Release 1.6.0 has been out for a little over a month now and so far so good. Generally speaking, our stability over the past few months has been pretty good and as a result we are starting to feel that Glimpse v1 is nearing an end and v2 is on the horizon! but more to come on that in the future 😀

In the mean time we noticed that the issue backlog has been building up and wanted to go on a bug bashing excises. Hence, we have been spending time knocking down out issues. We managed to get out outstanding issue count down from around 110 to under 40. As you might imagine, this has resulted in some updates and hence this release.

Hence, this release is a service update to fix a variety of issues. This release sees updates to following packages:

  • Glimpse.Core – Welterweight release 1.6.1
    • Switch images on Glimpse.axd page to their DataUri representations to avoid mixed content requests
    • Switch href over from using “#” to “javascript:void(0)”
    • Remove trailing commas in client
    • Switch logo on the About tab over to the new logo
    • Removed IpAddress as its not used anywhere
  • Glimpse.AspNet – Lightweight release 1.4.1
    • Removed IpAddress as its not used anywhere
    • Fixed possible null refernce exception when access clientId
    • Removed unused AspNet.Net35 Net35Backport
  • Glimpse.Ado – Flyweight release 1.5.1
    • Switched GlimpseDbTransaction over to be public
  • Glimpse.Ef* – Middleweight release 1.4.0
    • Added groundwork support for EF6

In terms of pull requests, I have to say a big thanks to:

And for the great issue reports, I want to thank:

Well I think that is a wrap. For a full list of changes, issues and commits see below:

Let us know if you have any thoughts or comments and I hope you enjoy this release.

Glimpse 1.6.0 released

Since our last release a fair bit of time has passed. Most of this has been taken up with speaking at MonkeySpace (expect a post on this in the future) and trying to take a good swat at knocking off a few key bugs that have been building up. That said we did manage to squeeze in a few useful new features.

Server Timing
We got a few requests come through to show the time on the server. This is useful for tracking down inconstancies in the time between the client and server or delta between the server and a trusted time source (some public NTP source for example). Time can also become important when dealing with things such as encryption / authentication, or when server has issues with wrong DST settings.

Here is a screenshot of what to expect:
TimeZoneDetails
This shows shows full server time, if DLS is in effect and delta between client and server time.

Environment Tab
We have also made some updates to the Environment Tab to show more version information. The thought process is that with Nuget packages that are starting to use the full SemVer spec (specifically pre-release and build metadata) just showing the standard version isn’t enough any more. Packages like EntityFramework have the same 6.0.0.0 version number during the whole pre-release cycle, but have different package versions. Hence now, we show the full version number that is used in Nuget if its available.

This is what the new details look like:
EnvironmentTab

This is useful when you want to confirm that the correct version of a package installed.

Release Notes

  • Glimpse.Core – Welterweight release 1.6.0
    • Add server “clock” time to HUD (shows full server time, if DLS is in effect and difference between client and server time)
    • Update to client to pulse tabs to try and show that the state context has changed
    • Update to client to show a loading message (instead of an error message) to give the data a chance to load
    • Update to client for Principal vs. Principle
    • Update to client to support object values having layouts
    • Fix bug where JSON.NET could screw up self reference loops
    • Fix small typo in update notification on glimpse.axd
  • Glimpse.ASP.NET – Middleweight release 1.4.0
    • Add server “clock” time to HUD (shows full server time, if DLS is in effect and difference between client and server time)
    • Update Environment tab update to show more version Info
    • Fixed issue where tabs could randomly disappear in some cases
    • Fixed issue where calls to HttpContext.Request in IIS7 Integrated mode threw exceptions
    • Fixed issue where query string parameters with a null key would throw an exception
    • Fixed issue to make Glimpse NuGet package discovery more stable
    • Update to make the injection of the the script tags into the rendered pages more robust
    • Update Environment tab to make it more realilant to exceptions in different protection modes
    • Update to make it easier to get Glimpse working when using dynamic compression
  • Glimpse.MVC* – Featherweight release 1.3.3
    • Minor adjustment to bring NuGetPackage inline with eachother
  • Glimpse.ADO – Lightweight release 1.5.0
    • Add support for profiling DbDataAdapter.Fill() correctly

Special Thanks
In terms of pull requests, I have to say a big thanks to:

And for the great issue reports, I want to thank:

Release Details
Well I think that is a wrap. For a full list of changes, issues and commits see below:

Side Note
We currently know there is an issue with our EF6 package being broken with EF6 Beta1. We hope to have this fixed soon.

Parting words
Let us know if you have any thoughts or comments and I hope you enjoy this release.

Extending your Tab – Your code, your plugins, part 3

So far we have covered a couple of different cases around how you could introduce custom Tabs into your system to gain a better understanding of how your system is operating (Creating a simple Tab – Your code, your plugins, part 1 and Creating a typical Tab – Your code, your plugins, part 2).

These tabs have been great to get up and running, but there is a chance that after a while, you may want to get more from your tab. Specifically, to extend its look and feel, and even to enhance the data that you are seeing inside the plugin.

New Concepts

  • Controlling the layout of your tab
  • Render compound/nested objects
  • Pivoting the root table layout

Use Case 3: Show the content of a shopping cart style component you might have written, using a custom layout

This time around, it’s the same use case that we saw in part 2 but we are adding on the fact that we would like to control the layout. We want to augment what we see so the layout is clear and the data representation matches our mental model, not just the object structure we happen to be dealing with. We want to control the headers/titles, order of the columns, prefixes/postfixes, styling, etc.

Existing code
I’m going to assume that you have seen how we got the base plugin up and running (if you haven’t, checkout part 2). The code in question is that of a typical Tab that returns an object collection.

public class TabCart : AspNetTab
{
    public override string Name
    {
        get { return "Cart"; }
    }

    public override object GetData(ITabContext context)
    {
        var cart = ShoppingCart.GetCart(context.GetHttpContext());
        var items = cart.GetCartDetials();

        return items;
    }

    public override RuntimeEvent ExecuteOn
    {
        get { return RuntimeEvent.EndSessionAccess; }
    }
}

Controlling the layout of your tab
Problem
By default when we return data from our ITab.GetData() method, the object contains no styling information. The rendering engine gets us pretty close to what we want to see but still doesn’t get us all the way there.

Solution
As it turns out Glimpse supports an extension model which favours Interface Segregation. This is just a fancy way of saying that extra functionality can be added to a Tab by making a Tab implement a given interface. This interface will augment the Tab and allow it to perform functions that a base Tab would would otherwise not be able to.

This is what we would like to see:
LayoutTab
You will note that it looks similar to the previous version of the tab we had, but its layout is different.

Sample Code
In this case we are going to add on the ITabLayout interface which requires that we add on a GetLayout() method. This method should return an object which describes how the data is to be structured or laid out. To help controlling these layouts we have a fluent API (which was created by Kristoffer Ahl of Fluent Security fame). The following gives you a basic taste of what you could do to achieve the above:

using Glimpse.AspNet.Extensibility; 
using Glimpse.AspNet.Extensions;
using Glimpse.Core.Extensibility;
using Glimpse.Core.Tab.Assist;
using MvcMusicStore.Models;

namespace MvcMusicStore.Framework
{
    public class TabCart : AspNetTab, ITabLayout
    {
        //NEW CODE
        private static readonly object Layout = TabLayout.Create()
                .Row(r =>
                {
                    r.Cell("{{albumTitle}} ({{albumId}})").AsKey().WithTitle("Album (Id)");
                    r.Cell("albumPrice").AlignRight().Prefix("$").WidthInPixels(100).WithTitle("Price");
                    r.Cell("genreName").WithTitle("Genre");
                    r.Cell("artistName").WithTitle("Artist");
                    r.Cell("count").Class("mono").WidthInPixels(70).WithTitle("Count");
                    r.Cell("dateCreated").WithTitle("Added");
                    r.Cell("recordId").WithTitle("Record Id");
                    r.Cell("cartId").WithTitle("Cart Id"); 
                }).Build();
        //NEW CODE
         
        public override string Name
        {
            get { return "Cart"; }
        }

        public override object GetData(ITabContext context)
        {
            var cart = ShoppingCart.GetCart(context.GetHttpContext());
            var items = cart.GetCartDetials();

            return items;
        }

        public override RuntimeEvent ExecuteOn
        {
            get { return RuntimeEvent.EndSessionAccess; }
        }

        //NEW CODE
        public object GetLayout()
        {
            return Layout;
        }
        //NEW CODE
    }
}

Render compound/nested objects
Problem
Having seen what the above has produced and the fact that we are starting to gain a real insight into how our shopping cart is operating, we have decided that we want to take things to a whole new level. We don’t want to repeat the shopping cart ID for every row (as we only want to see it once) and we want to see other aggregated information about out cart inside the tab (i.e. total value, etc).

Solution
As it turns out, Glimpse is capable of being able to render nested objects. When it detects a property which is a complex vs. primitive type, it recursively rips through that object and starts the rendering process again. For us, this means that we could construct an object that has the data we want listed above the table of cart entries.

Here is the next iteration of what we would like to see:
SummaryCartTab

Sample Code
Knowing that we want to show some more data, we can go back to the Tab and make some tweaks. Looking at the below, we can see that we have extended the model that we are returning and have added some more details to the meta data that’s returned.

public class TabCart : AspNetTab, ITabLayout
{
    //UPDATED CODE
    private static readonly object Layout = TabLayout.Create()
            .Cell("items", TabLayout.Create().Row(r =>
                {
                    r.Cell("{{albumTitle}} ({{albumId}})").AsKey().WithTitle("Album (Id)");
                    r.Cell("albumPrice").AlignRight().Prefix("$").WidthInPixels(100).WithTitle("Price");
                    r.Cell("genreName").WithTitle("Genre");
                    r.Cell("artistName").WithTitle("Artist");
                    r.Cell("count").Class("mono").WidthInPixels(70).WithTitle("Count");
                    r.Cell("dateCreated").WithTitle("Added");
                    r.Cell("recordId").WithTitle("Record Id");
                })).Build();
    //UPDATED CODE
     
    public override string Name
    {
        get { return "Cart"; }
    }

    public override object GetData(ITabContext context)
    {
        var httpContext = context.GetHttpContext();

        var cart = ShoppingCart.GetCart(httpContext);
        var items = cart.GetCartDetials();

        //UPDATED CODE
        var root = new
        {
            CartId = ShoppingCart.GetCartId(httpContext), 
            Total = items.Any() ? items.Sum(x => x.AlbumPrice).ToString() : "--", 
            Items = items
        };
        //UPDATED CODE

        return root;
    }

    public override RuntimeEvent ExecuteOn
    {
        get { return RuntimeEvent.EndSessionAccess; }
    }

    public object GetLayout()
    {
        return Layout;
    }
}

Pivoting the root table layout
Problem
As fate would have it, the above still isn’t good enough. We like the fact that the layout has progressed forward but, having seen other Tabs within Glimpse that are displayed more succinctly, we want to do more. In addition, the above rendering kinda squashes the Items table.

Solution
Another nice feature that the Glimpse rendering engine supports is the ability to pivot the way in which key/value Objects are displayed. When you do this, instead of seeing a key and value column, headings are rendered for the keys and the values are rendered in block under the corresponding header.

This time around, the below is what we would like to see:
PivotLayoutTab

Sample Code
Knowing that Glimpse can deal with nested objects and that we have the ability to pivot, we are going to group together the summary details. You will note that the pivot functionality is added by having our Tab implement the ILayoutControl interface. This is another example where we are using Interface Segregation to add functionality.

using System.Linq;
using Glimpse.AspNet.Extensibility; 
using Glimpse.AspNet.Extensions;
using Glimpse.Core.Extensibility;
using Glimpse.Core.Tab.Assist;
using MvcMusicStore.Models;

namespace MvcMusicStore.Framework
{
    public class TabCart : AspNetTab, ITabLayout, ILayoutControl
    {
        private static readonly object Layout = TabLayout.Create()
                .Cell("items", TabLayout.Create().Row(r =>
                    {
                        r.Cell("{{albumTitle}} ({{albumId}})").AsKey().WithTitle("Album (Id)");
                        r.Cell("albumPrice").AlignRight().Prefix("$").WidthInPixels(100).WithTitle("Price");
                        r.Cell("genreName").WithTitle("Genre");
                        r.Cell("artistName").WithTitle("Artist");
                        r.Cell("count").Class("mono").WidthInPixels(70).WithTitle("Count");
                        r.Cell("dateCreated").WithTitle("Added");
                        r.Cell("recordId").WithTitle("Record Id");
                    })).Build();
         
        public override string Name
        {
            get { return "Cart"; }
        }

        //NEW CODE
        public bool KeysHeadings
        {
            get { return true; }
        }
        //NEW CODE

        public override object GetData(ITabContext context)
        {
            var httpContext = context.GetHttpContext();

            var cart = ShoppingCart.GetCart(httpContext);
            var items = cart.GetCartDetials();

            var root = new
            {
                //UPDATED CODE
                Details = new {
                        CartId = ShoppingCart.GetCartId(httpContext), 
                        Total = items.Any() ? items.Sum(x => x.AlbumPrice).ToString() : "--"
                    },
                //UPDATED CODE
                Items = items
            };

            return root;
        }

        public override RuntimeEvent ExecuteOn
        {
            get { return RuntimeEvent.EndSessionAccess; }
        }

        public object GetLayout()
        {
            return Layout;
        }
    }
}

Working Sample
If you want to run what we have in the first sample, here is the link (94e9f99eda), or for the modified Tab, here is the link (e1fb2ca944), or for the finial pivoted Tab (e6d5eb04b2). As usual feel free to play around with it and modify.

Creating a typical Tab – Your code, your plugins, part 2

In the previous post – Creating a simple Tab – Your code, your plugins, part 1 – we looked at how we could take the data you store inside of a configuration object in your system, and create a tab which shows that data.

This time around we are going to be taking that a step further and looking at how we can customize how your Tab looks and how the data is displayed.

New Concepts

  • Creating a tab which renders a list of objects
  • Render data which is continuously changing
  • Controlling when a tab is executed

Use Case 2: Show the content of a shopping cart style of component you might have written

In this example, we have a shopping cart that our site uses to track items that a user is purchasing. When applying this to your own situation, think of the shopping cart as a generic representation of any component in your site that has transient state, based on the actions that the user performs.

For this case, our shopping cart is fairly simple and we wont be aiming to show more than the content of the shopping cart. In your own scenarios, you will likely be able to draw even more value than what we are showing here and start to apply some of the details/factors that exist in most real e-commerce solution (i.e. applied promotions, culture, discounts, markups, etc).

Existing code
Here is the general interface of the API that we are interacting with which manages the state of the cart:

public class ShoppingCart
{
    //...
    public static ShoppingCart GetCart(HttpContextBase context)
    {
        var cart = new ShoppingCart();
        cart.ShoppingCartId = cart.GetCartId(context); 
        return cart;
    }
     
    public string GetCartId(HttpContextBase context)
    {
        //Pulls cartId from Session
    }

    
    public List<CartItem> GetCartDetials()
    { 
        //Pull cart items from Cache
    }
    //...
}

public class CartItem
{ 
    public string AlbumTitle { get; set; }
    
    public decimal AlbumPrice { get; set; }
    
    public string GenreName { get; set; }
    
    public string ArtistName { get; set; }
    
    public int AlbumId { get; set; }
    
    public int Count { get; set; }
    
    public DateTime DateCreated { get; set; }
    
    public int RecordId { get; set; }
    
    public string CartId { get; set; }
}

Problem
Under normal circumstances, when developing this functionality within a site, its difficult to know whether the internal state of your model matches what you expect. Many different factors can contribute to what is stored, and and the cart summary page usually isn’t tailored to try to inform you about object state.

Solution
Assuming you have read part 1 in the series and had a crack at creating a basic Tab, you are becoming more adventurous and decide that a Glimpse Tab could hold the answer. You decide that to start with, you would like to show the basic content of the cart.

This is what we would like to see:
CartTab

Sample Code
As per usual, the runtime will detect any class in your solution that inherits from ITab. To produce what we have in mind with the awareness that you have access to the API described, the following is how we create your Tab:

public class TabCart : AspNetTab
{
    public override string Name
    {
        get { return "Cart"; }
    }

    public override object GetData(ITabContext context)
    {
        var cart = ShoppingCart.GetCart(context.GetHttpContext());
        var items = cart.GetCartDetials();

        return items;
    }

    public override RuntimeEvent ExecuteOn
    {
        get { return RuntimeEvent.EndSessionAccess; }
    }
}

In this example we have introduced a new concept with the override of ITab.ExecuteOn. This property dictates at what point in the request your Tab will be executed. By default, if you use the base classes Glimpse has, tabs run at the end of the request (RuntimeEvent.EndRequest). But in this case, we need to access a cartId which is stored in Session and in asp.net Session state is only available during the whole request. Hence we want to tap in at the last point which session is available.

Working Sample
If you are interested, here is the link (3a65662aea) to the MVC Music Store sample which has the commit for the above functionality. Feel free to play around with it and modify.

Creating a simple Tab – Your code, your plugins, part 1

When talking about Glimpse and extensions, a lot of attention goes towards the package ecosystem. This contains plugins which provide insights into the various frameworks you use. This makes it very easy to get up and running, and gain deep insights into your application and the systems it’s build on. The barrier to entry is very low and the reward is high, but you still aren’t getting the most out of Glimpse.

With very little effort, it’s possible to have this same instrumentation for the custom code in YOUR application. Image if your application could tell you its current state and give you a picture of logic its executed. What if people working on your project had a full diagnostics console which showed how the custom parts of your application is operating.

This would make dealing with parts of the system you hadn’t built much easier, and provide a much better onramp to those coming to your project for the first time. This woul bring the same level of understanding that you have come to expect from the standard Glimpse packages, right to the custom parts of your application.

For me some examples of what might be possible here are as follows:

  • Show the current state of a custom configuration object in your system
  • Show the content of a shopping cart style of component you might have written
  • Current state of a work flow that you have progressed through
  • Security checks that were conducted to build the page (what passed/failed)
  • etc…

This post is the first in a series of posts looking at your code and your plugins. We will be looking at how Glimpse can be leveraged to show specific details for your system. To start with, we are going to take the first example listed above and see what code it would take to make it work.

Use Case 1: Show the current state of a custom configuration object in your system

In this example, we have a database table called Configuration. The idea is that we want to store information like tax rates and markups in the database so we can update them easily. For this case, we are going to put aside that you could do this via the web.config and focus on the idea.

Existing code
Here is the code that makes up the static Configuration hook mentioned above:

public static class Configuration
{
    public static ConfigurationModel Current { get; set; }
}

public class ConfigurationModel
{
    public string Currency { get; set; }
    
    public double TaxRate { get; set; }
    
    public int DefaultCategory { get; set; }

    public double MarkupRate { get; set; }
}

Problem
Under normal circumstances, we would have very little idea about the state of these object. We could go to the database and query the table directly, but at that point we are assuming that this is the same as what the application has in memory.

In this case, because we aren’t happy with making this assumption and we want to know what we actually have in memory – the thought being:

  • Incase some exception caused only a partial load, or
  • we have some impedance mismatch between the database and the class, or
  • we have some sort of post processor which interprets/modifies the data before populating the object

With our current set of tools, we could set break points in our code so we can manually inspect the object or dump the object out to a log file. Unfortunately, these solutions are time consuming, cumbersome and less than ideal.

Solution
Having heard about Glimpse and used it in other projects, you decide to see if it has anything to offer. You find out that you can easily create Tabs to show arbitrary data. You decide that you would like to see a Tab which shows the state of your Configuration object.

This is what we would like to see:
CustomTab

Sample Code
Creating Tabs within Glimpse is incredibly easy. Once Glimpse has been added to your project, the runtime will detect any class in your solution that inherits from ITab. This process means that there is no configuration xml or registering of classes to get up and running.

This is the only code you would need to give Glimpse the data that you would like to populate your Tab:

public class TabConfiguration : AspNetTab 
{
    public override string Name
    {
        get { return "Setup"; }
    }

    public override object GetData(Glimpse.Core.Extensibility.ITabContext context)
    {
        return MvcMusicStore.Framework.Configuration.Current;
    }
}

Extra Code
For the sake of completeness, here is a trivial example of how you might manually go about populating the Configuration object in the first place (note, this is just one of many):

private void LoadConfiguration()
{
    var connectionString = ConfigurationManager.ConnectionStrings["MusicStoreEntities"];
    var factory = DbProviderFactories.GetFactory(connectionString.ProviderName);
    using (var connection = factory.CreateConnection())
    {
        connection.ConnectionString = connectionString.ConnectionString;
        connection.Open();

        MvcMusicStore.Framework.Configuration.Current = connection.Query<ConfigurationModel>("SELECT * FROM Configuration").First(); 
    }
}

protected void Application_Start()
{
    //...
    LoadConfiguration();
    //...
}

Working Sample
If you are interested, here is the link (4639363cff) to the MVC Music Store sample which has the commit for the above functionality. Feel free to play around with it and modify.

Glimpse 1.5.0 released

Well its that time again and we have another release ready to go. This one has a couple of cool new features and a whole bunch of fixes/improvements. Of late we have been pushing so hard to get new features out the door we decided that at a certain point “a chicken needs to come home to roost”.

Configuration Generator
This feature will hopefully make it more discoverable how to turn various features of Glimpse on or off, without having to go searching for it. It is also designed to help reduce the support burden we have by allowing people to discover and build the config they have. PLEASE NOTE, this only generates the config you need to copy over to your web.config, these changes aren’t made live to the system.

GlimpseConfigurationGenerator

From the highlighted sections, you can see how you can open the generator by clicking on the “Start Configuration Helper” button and then checking or unchecking the various checkboxes. What I really like about this helper is that its context sensitive to your system. As you can see, you are about to uncheck/check the tabs/policies/etc that are installed in your system.

If you have any thoughts about what else we can do here please let us know.

Host Tab Data Layout Change
Also in this release we have switched up the location of some of the data points in the Host tab. In previous releases there was some inconsistencies with where the data points where places in relation to the other HUD sections, hence the Host section has now been brought inline.

GlimpseHostTab

So don’t get caught out by these changes. Take the time to get reacquainted with the changes.

Popup Sections Spacing
The popup sections now have more space to play with. There were cases people would be caught out by having almost no width to play with and as a consequence have a very squashed data. This release sees a minimum amount allocated to each popup. This is a UX change we aren’t 100% sure about, so make sure you let us know if you have any thoughts.

Ajax Linking
This is a great pull request we accepted from Christophe Gijbels. In short it allows you to click on one of the requests in the Ajax mouseover and have Glimpse opened with that request already selected.

GlimpseAjaxLink

This is a really cool feature, so have a play around and let us know what you think. Expect to see more links like this appearing over time.

Release Notes

  • Glimpse.Core – Lightweight release 1.5.0
    • Added Configuration builder to Glimpse.axd
    • Allow HUD Ajax Request to click directly through to main HUD
    • Changed the position of data points in Host popup
    • Allow HUD mouse overs to take up more space if needed
    • Make HUD sections collapsible when mouse overs opened
    • Update to allow glimpse to work for request with a Content Type of “text/plain”
    • Minor fix where Host tab could throw exception if data was missing
    • Minor fix to remove some exceptions in the client that occurred in IE8
    • Minor fix to metadata which didn’t output in some rare cases
    • Minor optimization in the client for cases where tabs could rerender
    • Fixed UI glitch that would prevent Glimpse being opened once the HUD Ajax calls had been detected
    • Minor improvement to make tabs use explicit box-sizes
    • Minor fix to improve HUD processing of Ajax request that don’t have a Content Type
    • Minor fix for client error on Configuration Tab when connectionStrings is null
    • Update to glimpse.axd which showed Policies under the Inspectors heading
  • Glimpse.ADO – Flyweight release 1.4.1
    • Fix error calling what could occur when binding DataReader’s to controls
    • Made GlimpseDbDataAdapter public to allow it to be accessed in different cases
  • Glimpse.EF* – Middleweight release 1.3.1
    • Majorish feature where we now support DbSpatialServices (EF5 .NET45 and EF6)
  • Glimpse.ASP.NET – Bantamweight release 1.3.1
    • Remove styling from URL column in Route tab
    • Added defensive try/catch around some system call in Environment call to be more defensive

Other news
Also in this release cycle we had our Regular Town Hall where we discussed all the project happenings coming up. We try to have these once a month, so if you would like to join the next one, keep an eye out on the blog.

We also accepted Christophe Gijbels to the ranks of the Glimpse committers. If you get a chance, take a moment to congratulate him and welcome him to the team.

Special Thanks
In terms of pull requests, I have to say a big thanks to:

And for the great issue reports, I want to thank:

Release Details
Well I think that is a wrap. For a full list of changes, issues and commits see below:

Parting words
Let us know if you have any thoughts or comments and I hope you enjoy this release.

Glimpse Town Hall #3

Its been a little while, but as promised, we are back again with another Town Hall meeting!

Last meeting was quite successful, hence we are back again and hope to have even more content, and we are working through an agenda now. If there is something you’d like to share, see or hear about, please add a comment to this post.

Agenda

  • HUD roundup and future
  • Project management and our focus on openness
  • Welcome to our new Core Contributor
  • Look at what Glimpse could do with Azure
  • What’s happening next, what would people like to see?
  • Question and Answer

The meeting will be Tuesday, July 2nd at 4:00 PM (UTC-5:00). We’ll be on Google Hangout again, so bring along your microphone and web cam if you can! (Or just text chat with us…)

Hope to see you there!

Glimpse NDC talk and video up

Well its the end of another week and this one has been full of fixing bugs and addressing issues. Also, just catching up and taking stock of where we are at and what we are doing next.

In the mean time I would like to leave you with the video of the talk on Glimpse that I did at NDC earlier in the month:

Post

This video is worth watching as I go into the why’s and how’s of the problem space Glimpse is working in and motivations of what is driving our current direction.

Also here are the slides from the talk.

Let us know what you think.