Tuesday, September 08, 2009
Javascript and the Document Object Model have revolutionized the way we do business on the web, so it's ironic how painful some of the simple stuff still is. There are many libraries out there to accomplish common tasks, but if you are stuck in a situation where you need to roll your own, then here's a less-discussed technique for managing events in Javascript. This method also works well with Windows controls.

Consider the problem: because of the differences in direction in which events flow (from innermost element to outermost, or vice versa depending on browser), tracking mouseover and mouseout events for complex structures can be difficult and unreliable.

Case in point...If I have a menu structure made up of DIVs, hyperlinks, images, etc, the OnMouseOut event will fire each time I leave the element it is attached to, even if I am entering a child element. This leads to constantly having to check for hierarchy to determine whether or not the event was fired from inside the bounds we actually care about or not. Images with an alpha channel(as of this writing) contribute to the problem in Internet Explorer 7 in that the browser can become confused as to where the "solid" layer ends and even fire events who claim to have come from an element completely outside and underneath them (lower z-index).

The purpose of this discussion is not to cover the intricate and disparate nature of events in Javascript in various browsers, but to throw out one simple idea.

Instead of caring about hierarchy, trap mouseover/mouseout on the root element of the item in question. So if you have a DIV with a bunch of other DIVs in it, track mouse events on the outermost DIV. Then, when an event is raised, look at the X,Y coordinates of the mouse. Compare those coordinates with the bounds of the element. If the point falls within the bounds, you know that the mouse is over the element. If the point falls without the bounds, you know that mouse has left the element. The element fired the event, but the mouse is no longer within its bounds.

function AttachMouseOut( element )
    {
        element.onmouseout = function( e )
        {
            if( e == null )
            {
                //
                // Get the IE event object if the argument provided
                // to this delegate was null.

                e = window.event;
            }
           
            var x = 0;
            var y = 0;

            if( e.pageX || e.pageY )
            {
                //
                // W3 Standard

                x = e.pageX;
                y = e.pageY;
            }
            else if( e.clientX || e.clientY )
            {
                //
                // IE

                x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
                y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
            }
           
            if( !TestBounds( someElementToTest, x, y ) )
            {
                // perform action here, such as hiding an element or highlighting it
            }
        };
    };
   
    function TestBounds( element, x, y )
    {
        if( element == null )
        {
            return false;
        }
       
        //
        // Get a rectangle for the element in its
        // current location.

        var top = element.offsetTop;
        var left = element.offsetLeft;
        var bottom = element.offsetTop + element.offsetHeight;
        var right = element.offsetLeft + element.offsetWidth;

        //
        // See if the provided point falls inside the
        // rectangle we have determined for the element.

        if( x > left && x < right && y > top && y < bottom )
        {
            return true;
        }
   
        return false;
    };



This method still requires some cross-browser code, but it eliminates the need to do hierarchy traversals and also eliminates the need to deal with the event objects in the browser for anything other than X,Y coordinate retrieval.

--Tim Medora
posted on Tuesday, September 08, 2009 1:29:36 AM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Friday, June 19, 2009

Written by: Chris Szabo, Senior Software Engineer

I came across some interesting information that took me a lot of digging to find.  I thought I would share in case anyone runs into a similar situation.  This applies specifically to SQL Server 2005 Enterprise edition.  The results are slightly different in 2008.

In a 64 bit environment, Microsoft’s documentation on SQL Server indicates that enabling the use of AWE memory allocation is not necessary, and will in fact be ignored by SQL Server.  When AWE is disabled, if you look at the SQL Server process in task manager, you will see that the working set allocates as much memory as possible, or whatever the configured values are.

 

While administering a client’s environment the other day, I found that the process was consuming approximately 180 MB of memory.  This was on a server that had 6 GB of memory available.  When I saw this, the first thing I did was execute the following command:

 

DBCC MEMORYSTATUS

 

Here is part of the result set:

 

Memory Manager                  KB

------------------------------ --------------------

VM Reserved                    8519776

VM Committed                   114064

AWE Allocated                  6397784

Reserved Memory                1024

Reserved Memory In Use         0

 

Notice that a great deal of memory is allocated using AWE, something that is contrary to the documentation that Microsoft provides.  After some further digging I found out why.

 

In a 64 bit environment, it is recommended that the Lock Pages in Memory user right is assigned to the SQL Server service account.  This user right allows SQL Server to allocated memory and refuse to give it back to the operating system when requested.  SQL Server can choose to release the memory, but granting this user right allows SQL Server to control what happens, not the operating system.  As a result of this, the operating system cannot page out SQL Server’s buffer pool when it thinks it’s necessary.

 

What you won’t find easily in any documentation is that this user right actually compels SQL Server to use AWE for memory allocation, which is consistent with the results above.  This was apparently confusing to someone because if you execute the same command in a 64 bit environment using SQL Server 2008, you’ll get the following results:

 

Memory Manager                           KB

---------------------------------------- -----------

VM Reserved                              10583068

VM Committed                             76928

Locked Pages Allocated                   65536

Reserved Memory                          1024

Reserved Memory In Use                   0

 

The point of all this is that AWE memory allocation in a 64 bit environment is still used by SQL Server.  It is not just a setting used in 32 bit environments to allocate more than 2GB of memory to SQL Server.  It’s actually how pages are locked in SQL Server after being allocated.

 

posted on Friday, June 19, 2009 3:23:58 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Tuesday, November 18, 2008
List does not exist error when creating an alert from workflow
posted on Tuesday, November 18, 2008 9:59:47 AM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Sunday, September 21, 2008

Reflection in .Net is fairly commonplace and I've written it into dozens of applications.  Tonight I found a new case that I had not yet encountered: Creating a type that has a generic template parameter such as MyType<T>.

Without reflection, you would simply say: MyType<string> = new MyType<string>();.  But it is a bit more complicated creating the class dynamically at runtime, albeit very doable.

I found some helpful information online, but I really wish someone had just posted the following:

Activator.CreateInstance(Type.GetType(typeName).MakeGenericType(typeof(string)));

Let's deconstruct. 

- Activator.CreateInstance() creates an object from a type definition.  There are several ways of creating an object on the fly; this is only one of them.  You will need to add a reference to System.Reflection.

- Type.GetType(typeName) creates an object from a string definition of a type.  Again, many ways of doing this, but in this example, typeName = "namespace.namespace.className`1, fully-qualified assembly name", e.g. "NFC.Web.CustomType`1, NFC.Web".  Of course, your type name will be different, just make sure to use the fully-qualified class name and assembly name, seperated by a comma.

Note the red-highlighted code above; a generic class string must contain the `1 to indicate that it is a parameterized class.  If you had three generic parameters, you would mark it as `3 and so on.

- .MakeGenericType(params) - the crux of this solution.  Retrieves a type as a generic with the specified list of arguments.  In this example, we know the template argument and use typeof(x) to return its Type, but you could easily pass any (valid) type to this method.  In addition, as this method takes a params[], you can pass as many different template types into it.

 

- Tim Medora

 

posted on Sunday, September 21, 2008 8:40:45 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Saturday, August 02, 2008

Tonight I had a few orphaned sessions to a remote machine that were not being enumerated by Terminal Services Manager or a remote connection (from Computer Management).  I almost gave up and drove to the physical machine, but I found this trick online first.

Here's a handy way to view and manage sessions from the command prompt.

To List All Sessions

Start->Run->cmd

query session /server:xxx.xxx.xxx.xxx

To End a Session

Start->Run->cmd

reset session 1 /server:xxx.xxx.xxx.xxx

Note that "1" represents a session id.  You can see all available sessions from the previous "query" command.  Insert the correct number to terminate it.

Once you know these few commands, its actually quicker to manage remote sessions from the command prompt.

- Tim Medora

posted on Saturday, August 02, 2008 8:19:22 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Friday, July 25, 2008

Little tip I thought I'd share...as of the date of this posting (7/2008), when building connection strings to access a MaxDB instance, the password must be changed to all uppercase.

For anyone who's wondering, it is possible to connect to MaxDB with ASP.Net/C#.  Use the System.Data.Odbc library and a DSN to connect with only a few lines of code.

- Tim Medora

 

posted on Friday, July 25, 2008 1:19:54 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Monday, May 26, 2008
Today I was happily coding a .Net 3.5/SQL Server 2005 web application when things came to a grinding halt with the error:

A severe error occurred on the current command.  The results, if any, should be discarded.

I googled the error (of course), but found a dozen different answers and many of them required installing service packs or hotfixes.  While I'm not opposed to that, I knew that it shouldn't be necessary.

I'm sure there are many causes for this error, but here was mine:

BEGIN TRANSACTION;

BEGIN TRY

    IF( @UserId < 1 ) BEGIN

        IF( (SELECT count(UserId) FROM [User] WHERE Email = @Email) > 0) BEGIN
            SET @Status = 1;
            RETURN;

        END

...

See the problem? I'm returning without committing or rolling back my transaction.  While this is a stupid mistake on my part, the error message is quite ambiguous, but thankfully the solution is simple.  Before returning, insert cleanup GOTO cleanup such as:

BEGIN TRANSACTION;

BEGIN TRY

    IF( @UserId < 1 ) BEGIN

        IF( (SELECT count(UserId) FROM [User] WHERE Email = @Email) > 0) BEGIN
            SET @Status = 1;
            GOTO NoSuccessReturn;

        END

...


NoSuccessReturn:
    IF( @@TRANCOUNT > 0 )BEGIN   
        ROLLBACK TRANSACTION;
    END

    RETURN;


Hope this helps someone!

--Tim Medora


posted on Monday, May 26, 2008 2:50:51 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]
 Monday, May 05, 2008

Most ASP.Net developers quickly learn that web.config file settings percolate from the top down.  This is commonly used to provide global configuration for a single web application, but it's pretty easy to forget that web.config settings can be inherited across different virtual directories.

For example:

1) Create a website in IIS.
2) Create a virtual directory for a second site underneath the IIS website.
3) Reference a type in the web.config for site #1, such as in a HttpHandler block.
4) Unless the second site has the type referenced in #3 (or it is in the GAC), second site will now immediately throw an exception, "Cannot load type xxx.xxx.xxx".

In web.config #1
<
httpHandlers>
   <add verb="GET" path="*.css.ashx" type="NFC.PublicWeb.UILogic.PathResolver,NFC.PublicWeb"/>
</httpHandlers>

This issue is caused because every virtual directory underneath the top-level website is inheriting settings from the top-most web.config.  Many of these inherited settings would go unnoticed, but as soon as the child virtual directory hits something it can't handle, it immediately throws a show-stopping (as all config errors are) exception.

Quick Solution?
Wrap application specific blocks of code in the LOCATION tag.  Obviously this must be used judiciously, but it's a useful fix to a sneaky problem.

<location path="." inheritInChildApplications="false">
   <
system.web>
      <httpHandlers>
         <add verb="GET" path="*.css.ashx" type="NFC.PublicWeb.UILogic.PathResolver,NFC.PublicWeb"/>
      </httpHandlers>
   </system.web>
</location>

For a detailed discussion of this topic, see this useful article on www.aspdotnetfaq.com.

posted on Monday, May 05, 2008 7:38:57 PM (US Mountain Standard Time, UTC-07:00)  #    Comments [0]