Monday, 2 November 2009

Linq GetEnumerator.reset and new MS Chart charting controls

So I thought I would try out the new Microsoft charting controls for ASP.Net and winforms...

Looks fantastic but when I came to do some runtime databinding to a simple linq collection (selecting an x and y value into an enumerable anonymous type...) it failed miserably with an obscure error message.

With a bit of snooping I found that the problem is that the chart control always calls .Reset() on its IEnumerable(Of T) datasource before iterating the collection. Unfortunately the System.Linq.Enumerable.Iterator(Of TSource) that Linq returns as a concrete IEnumerable throws a "NotImplementedException" in its implementation of IEnumerable.Reset() - good one MS! (Check it out in Reflector)

Simple answer - call .ToArray() on your Linq collection and hey presto your Linq query will work as a chart datasource.

UPDATE - Click here and vote for MS to fix this bug!!!

Friday, 13 March 2009

An Improved MsgBox for Asp.Net

Often times a simple messagebox is required at the client under ASP.Net. This is easy to do by sending back a JavaScript Alert(). However, this does not work so well if the user navigates around using the back and forward buttons, as they will see the message multiple times. Also, we would like our msgbox to be usable from AJAX enabled apps, so that an asynchronous postback can also trigger an alert.

The below 3.5 code meets these criteria:

Module PageExtensions
    <extension()> _
    Public Sub MsgBox(ByVal aPage As Page, ByVal aMessage As String)

        Dim timeStr As String = "msgbox" & Date.Now().Ticks.ToString

        ' Set a cookie after showing alert so as will not re-show if back button or refresh is used.

        Dim alertScript As String = "if (document.cookie.indexOf('" & timeStr & "') == -1) {"
        alertScript &= "alert(""" & aMessage & """);"
        alertScript &= "document.cookie = '" & timeStr & "=deleted';}"

        System.Web.UI.ScriptManager.RegisterStartupScript(aPage, GetType(String), aMessage, alertScript, True)

    End Sub

End Module

To use within a page, you can now simply type:
MsgBox("Hello World"), just like in a Windows App.

A temporary cookie is set for each msgbox invoked so that the msgbox will only be shown once. The method is an extension method of the Page class, so needs to be contained within a Module, or used without the attribute.

Note also you will need a reference to System.Web.Extensions in your project.