DataTable cannot equal DBNull

I've seen this a couple of times in code, so it's worth mentioning.  There seems to be some confusion around what DBNull is supposed to be used for.  DBNull is meant to test field values of a DataTable for a value of NULL.  If you're doing something like

If DBNull(myDataTable) = False Then
 ' do something with the DataTable
End If

Then you're setting yourself up for a possible exception. DBNull on anything other than a proper DataTable field will always return false.

Consider the following test

Imports System.Data
Imports NUnit.Framework
<TestFixture()> _
Public Class DBNullTest
    <Test()> _
    Public Sub CanDataTableBeIsDBNull()
        Dim dt As DataTable = Nothing
        Assert.IsTrue(IsDBNull(dt))
    End Sub
End Class

CanDataTableBeIsDBNull will fail because dt is a DataTable type and not a field value from the DataTable.  So if you have to check to see if a DataTable is a valid object after an operation to populate the DataTable, use a comparison with Nothing instead:

    <Test()> _
    Public Sub CanDataTableBeNothing()
        Dim dt As DataTable = Nothing
        Assert.IsTrue(IsNothing(dt))
    End Sub

Posted by: Jeff
Posted on: 1/17/2010 at 1:37 AM
Categories: VB.NET
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

When email notification is not working in ELMAH

Hopefully you've heard of ELMAH, (Error Logging Modules and Handlers) if you're doing ASP.NET work. This gem is priceless when trying to catch unhandled exceptions in your project.

I ran into an issue today when following the web.config guidelines in the elmah release (it contains a sample web.config with documentation for all the configuration).  I wanted to be emailed whenever an exception occurred on the site, so I put the appropriate settings into the errorMail element in the <elmah /> configuration.  I setup some test exceptions to make sure that ELMAH was working correctly, and could see the errors in elmah.axd, but the emails were not being sent.

It turns out that the modules registered under <system.webServer> <modules> need to be included in <system.web> <httpModules> as well:

<system.web>
<httpModules>
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"  />
</httpModules>
</system.web>

The example web.config mentions having to put these modules in additional modules in httpModules if mail reporting is desired, but since it was commented out in the example, I accidentally skipped over it.  After this change was made, the email notifications started coming through.  Hopefully this will help me remember in the future, or help someone who is having the same issue.


Posted by: Jeff
Posted on: 1/16/2010 at 12:13 AM
Categories: elmah
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Being careful with jQuery's bind() and introducing bindOnce

jQuery's bind() method is extremely useful. If you call $(myElement).bind('change',function(){...}) multiple times, you can chain multiple events on the same element.

$('a').bind("click", function() { alert('event 1'); });

$('a').bind("click", function() { alert('event 2'); });

These two calls will take all links on in your DOM and alert("event 1") and alert("event 2") when any of them are clicked. Fantastic!

However, there is the potential for an undesired side effect if you use bind unwisely.  For example, say you have a modal dialog popup in your application.  When you have to display the modal dialog, you perform some setup first:

   1:  function SetupModalDialog() {
   2:      $('select', '#dialogContainer').bind('change',function(){
   3:          alert('be careful what you wish for');
   4:      });
   5:  }
 

If for some reason you have to call SetupModalDialog multiple times (perhaps because some of the controls are dynamic based on other parts of the page), the drop downs will have this function bound to the change event each time this function is called.  What does this mean?  If you open your dialog twice, and change the selection on a dropdown in the dialog, you will see two alert windows saying "be careful what you wish for".

There are a couple of ways you can handle this situation. One would be to go back through the elements you've setup events on and call unbind. Having clean up code like this is ideal, but not always practical. Another solution which will minimize your code changes is to make sure you're not binding the same function more than once.

Introducing bindOnce

   1:  function bindOnce(element, event, handler) {
   2:      if (element === undefined || event === undefined || handler === undefined)
   3:          return;
   4:          
   5:      var jqueryObj = $(element);
   6:   
   7:      var events = jqueryObj.data('events');
   8:   
   9:      if (events === undefined) {
  10:          jqueryObj.bind(event, handler);
  11:      }
  12:      else {
  13:          if (events[event] === undefined) {
  14:              jqueryObj.bind(event, handler);
  15:          }
  16:          else {
  17:              var isBound = false;
  18:              $.each(events[event], function(i, eventHandler) {
  19:                  if (eventHandler.toString() === handler.toString()) {
  20:                      isBound = true;
  21:                      return false;
  22:                  }
  23:              });
  24:   
  25:              if (isBound === false) {
  26:                  jqueryObj.bind(event, handler);
  27:              }
  28:          }
  29:      }
  30:  }

bindOnce simply excepts and element, the event to handle ('click'), and the function to handle the event.  By using the jQuery.data("events") collection, we can determine if the event and function have already been bound to the element in question.

Of course what good reason is there to have a method to do the work that does not extend jQuery? None that I can think of, so here's the jQuery plugin:

(function($) {
    $.fn.bindOnce = function(event, handler) {
        if (event === undefined || handler === undefined)
            return;
 
        var events = this.data('events');
 
        if (events === undefined) {
            this.bind(event, handler);
        }
        else {
            if (events[event] === undefined) {
                this.bind(event, handler);
            }
            else {
                var isBound = false;
                $.each(events[event], function(i, eventHandler) {
                    if (eventHandler.toString() === handler.toString()) {
                        isBound = true;
                        return false;
                    }
                });
 
                if (isBound === false) {
                    this.bind(event, handler);
                }
            }
        }
    };
})(jQuery);

The usage is typical:

   1:  $('a').bindOnce('click', function() { alert('Hey...'); });

Enjoy.

Posted by: Jeff
Posted on: 1/12/2010 at 11:05 PM
Categories: jQuery
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed