Golden Rule of Winform Databinding

Rocky Lhotka had this over on his site:

The Golden Rule of Windows Forms data binding

Never directly interact with a business object while it is data bound – only interact with the bindingsource

http://forums.lhotka.net/forums/thread/22990.aspx

I have to say, I am guilty of doing this, and I didn’t even know it was considered a bad practice, but I do recall running into problems with the behavior in getting the UI to refresh as I would want it to.

I also found a nice article talking about how to speed up binding to the datagrid:
 

Why should you not use floats for actual decimal numbers?

I don’t think etrade has learned the lessons in my posts on floating point numbers/variables.

SQL Server Decimal/Money/Float datatypes

Javascript (and apparently other programming languages) can’t do math

Click here for a screen shot of the full page.

Here is a link to the page where I found it. I hope they fix it soon. It’s pretty sad.

But, on the other hand, I wonder what I will do with that extra .00000000000005 dollars?

Trying to find the WIFI Switch on the HP Elitebook 8730w?

It took me a while to figure out that I didn’t have a driver problem.

I was looking everywhere to find the switch for the wifi on this HP Elitebook 8730w, but it turns out the LED icon in the upper left that shows the WIFI status IS the button, but clicking it does nothing.. why?

Well, b/c HP is using “LAN/WLAN switching” which means that it automatically turns off the wifi connection if you are plugged in.

Just unplug your network cable and your wifi card will enable! 

 

SQL Reports RDLC Errors

Ever get this error?

More than one data set, data region, or grouping in the report has 
the name 'SOMENAME'.  Data set, data region, and grouping names
must be unique within a report. 

Basically what happened was, somehow VS lost track of an existing datasource you were using, why I don’t know. When you went to add a new field or change something it added a 2nd copy of the same datasource, and now you have 2 datasources with same name. You can’t do that. To fix this, when you are editing the report, choose Report –> Data Sources from the menu and remove one of the duplicate datasource names.

In a related error, you may notice that you can’t use some fields that are part of your dataset.  For example, in my app, I had a field called “CreatedDate”.  This was a public property of my object, and it showed up in my data source that I was using to bind to the report, but the report refused to acknowledge it.

So in this case you need to delete the original datasource using the same steps as above, and do something to cause it to add a new copy of the correct datasource (like drag a field onto the report).

Problems Upgrading VS Solutions to 2008 With CruiseControl.Net

Problem:

We have a server that gets all files from TFS and uses Nant w/ Visual studio to compile our projects.  Basically nant issues a command line statement to get VS to build a given solution.

Everything was working great, until I upgraded our clients to 2008.

I went through and upgraded all our solutions.

I installed vs 2008 on the server.  But when I try to build from the command line, it tells me that the solution file “is from a previous version of this application and must be converted in order to build in this version of the application.”

I tried directly copying my solution file (skipping the source control step) directly to the server but I get the same message.

If I try to build it from the command line with VS 2005 it tells me that the solution is too new!! 

So 2005 says the solution is too new, 2008 says it is too old!

The solution on the server has the “version 9” icon, just like on my laptop.

The solution file starts with:
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008

Resolution:

Even thought I compared the solution files and found them to be exactly the same using a diff compare tool, I allowed the server to run the “upgrade” process on the solutions.  I didn’t save any of the changes it made, but from then on it recognized those files as having been already upgraded.

I even replaced the “server upgraded” solution files with the old solution files that it didn’t like and it continued to work just fine.

There must be some other files stored somewhere that made it think that it hadn’t been upgraded yet.

This isn’t a great solution, but it works at least.

 

Using Asyncronous Tasks In ASP.NET

ASP.NET has a limited number of threads that it uses to service incoming requests.  Thes threads from the its thread pool, and when its collection of threads are busy, requests have to queue up waiting for an open thread.

But, what happens when you have threads that are blocking waiting for another process to complete?  This could we a database call, or a webservice call, or an IO operation etc.

Well, what happens is that the thread, while doing no real work, is unavailable to service requests.

So, if your database is crunching on some long queries, other simple web requests may be sitting in the queue unable to be handled, even though the webserver CPU is idle.

One solution to this is to use Async pages/methods in ASP.NET 2 or greater.

Async operations allow the thread to be returned back to the thread pool instead of blocking, while some process is executed.

 

There is more than 1 way to do async operations like this from asp.net pages. 

One is to use RegisterAsyncTask and the other to user AddOnPreRenderCompleteAsync as well as declare the page as Async=”true”.

I won’t go into all the details, but AddOnPreRenderCompleteAsync is probably simpler, but you can’t define a timeout, you can’t call it multiple times in parallel, and in the EndAsyncOperation event handler you can’t access things like the httpcontext object.

Here are 2 examples of pages that are asynchronously serving up a PDF document (which is itself served from a page DownloadPDF.aspx, which has a 5 second thread sleep in it to simulate the processing of the report on another server.

Using AddOnPreRenderCompleteAsync:

Imports System.Net
Imports System.IO

Partial Class AsyncServer
    Inherits System.Web.UI.Page

    Dim _request As WebRequest

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        AddOnPreRenderCompleteAsync(New BeginEventHandler(AddressOf BeginAsyncOperation), _
                                    New EndEventHandler(AddressOf EndAsyncOperation))
    End Sub

    Function BeginAsyncOperation(ByVal sender As Object, ByVal e As EventArgs, ByVal cb As AsyncCallback, ByVal state As Object) As IAsyncResult
        _request = WebRequest.Create(HttpContext.Current.Request.Url.Scheme & _
                                     "://" & HttpContext.Current.Request.Url.Authority & _
                                     Page.ResolveUrl("DownloadPDF.aspx"))
        Return _request.BeginGetResponse(cb, state)
    End Function

    Sub EndAsyncOperation(ByVal ar As IAsyncResult)
        Dim reportResponse As WebResponse = _request.EndGetResponse(ar)
        Dim reader As New BinaryReader(reportResponse.GetResponseStream())

        Dim buffer(reportResponse.ContentLength) As Byte
        buffer = reader.ReadBytes(buffer.Length)
        
        Response.Clear()
        Response.ClearHeaders()
        Response.ClearContent()
        Response.ContentType = "Application/pdf"
        Response.BinaryWrite(buffer)
    End Sub

End Class

 

But I prefer to use RegisterAsyncTask.  Now, keep in mind that many operations will already support async versions (webrequests, webservice calls, databases calls, file IO etc), but if there isn’t already built in support for an async call, you can make your own method work in this framework with an async delegate.  Check out the commented code below for how you could do this, but because webrequests already support making the call in an asynchronous fashion, I don’t need to.

Imports System.Net
Imports System.IO

Partial Class RegisterAsyncTaskServer
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Page.AsyncTimeout = New System.TimeSpan(0, 0, 8)
        Dim task As New PageAsyncTask(New BeginEventHandler(AddressOf BeginGetAsyncData), _
                                      New EndEventHandler(AddressOf EndGetAsyncData), _
                                      New EndEventHandler(AddressOf TimeoutGetAsyncData), "task1", True)

        RegisterAsyncTask(task)
    End Sub

    '*************** This is one way to do this if not using an async download method by creating an async delegate
    'Dim taskDelegate As AsyncTaskDelegate
    '' Create delegate.
    'Delegate Sub AsyncTaskDelegate()
    'Private Function BeginGetAsyncData(ByVal src As Object, ByVal args As EventArgs, ByVal cb As AsyncCallback, ByVal state As Object) As IAsyncResult
    '    Dim extraData As New Object
    '    taskDelegate = New AsyncTaskDelegate(AddressOf DownloadReport)
    '    Dim result As IAsyncResult = taskDelegate.BeginInvoke(cb, extraData)
    '    Return result
    'End Function
    'Private Sub DownloadReport()
    'End Sub

    Private reportRequest As WebRequest

    Private Function BeginGetAsyncData(ByVal src As Object, ByVal args As EventArgs, ByVal cb As AsyncCallback, ByVal state As Object) As IAsyncResult
        reportRequest = WebRequest.Create(HttpContext.Current.Request.Url.Scheme & "://" & _
                                          HttpContext.Current.Request.Url.Authority & _
                                          Page.ResolveUrl("DownloadPDF.aspx"))
        Return reportRequest.BeginGetResponse(cb, state)
    End Function


    Private Sub TimeoutGetAsyncData(ByVal ar As IAsyncResult)
        Response.Write("TIMEOUT")
    End Sub

    Private Sub EndGetAsyncData(ByVal ar As IAsyncResult)
        Dim reportResponse As WebResponse = reportRequest.EndGetResponse(ar)
        Dim reader As New BinaryReader(reportResponse.GetResponseStream())

        Dim buffer(reportResponse.ContentLength - 1) As Byte
        buffer = reader.ReadBytes(buffer.Length)

        Response.Clear()
        Response.ClearHeaders()
        Response.ClearContent()
        Response.ContentType = "Application/pdf"
        Response.BinaryWrite(buffer)
        Response.Flush()
    End Sub

End Class

Nice!