IE7's Inanimate GIF

Posted by Ryan Baxter Wed, 11 Jun 2008 12:06:00 GMT

Animated GIFs are most often used as activity indicators in modern AJAX (asynchronous JavaScript and XML) enabled websites. I decided to use a GIF (Graphic Interchange Format) from ajaxload.info on an application that I’ve been developing at work. The application performs server-side processing on files uploaded by employees. Processing time varies depending on the size of the file. Larger files take longer.

I wanted the animated GIF to appear when the file upload button was clicked so I placed the image within a DIV tag and hid it by setting a blank CSS display property. OnClick of the upload button, a JavaScript function toggled the display value to “block”, making the DIV appear. This worked as expected in Firefox and IE6, but not in IE7. The DIV appeared in IE7, but it’s GIF wasn’t moving.

A little googling turned up a helpful comment on Rick Strahl’s blog.

I’ve run into a problem with animated gifs inside of a hidden area of a Web page that is hidden with style.display=’none’. When the area is made visible again, in Internet Explorer this causes the image to not be displayed an animated GIF whatever I try. [sic]

Apparently IE7 doesn’t like to animate hidden GIFs. User submitted comments on Rick Strahl’s blog provided many solutions, but only a couple worked in my situation. The first uses the JavaScript setTimeout method to populate the image’s SRC attribute 200 ms after the function call. The second sets the DIV’s innerHTML to a string containing an IMG tag with the animated GIF.

<script language='javascript'> 
    function ShowLoading(elementId) 
    {
        document.getElementById(elementId).style.display = "block"; 
        setTimeout('document.images["loadingImage"].src = "../images/loading.gif"', 200); 
    } 
</script>

Neither solution is ideal, but setting the element’s innerHTML felt a little bit cleaner to me.

<script language='javascript'>
    function ShowLoading(elementId)
    {   
        var element = document.getElementById(elementId);    

        element.innerHTML = "<img src='../images/loading.gif'>";    
        element.style.display = "block";
    }
</script>

*IE7 may have animations disabled. Go to Tools > Internet Options > Advanced > Multimedia. Checking “Play animations in webpages” may affect how IE7 renders your animated GIFs.

Temporary Identity Impersonation in ASP.NET

Posted by Ryan Baxter Tue, 27 May 2008 16:01:00 GMT

Uploading files in an ASP.NET application is relatively easy to do. Uploading to a remote machine is a little bit trickier, but certainly doable. I followed a set of instructions on aspalliance.com, but rather than declare an account to impersonate in my web.config file, I decided to do it in code. That way I could use impersonation only when needed and encapsulate it for later use.

I referred to an article on Microsoft’s Help and Support website about how to implement impersonation. Their code worked great, but I decided to put it in a class to help keep things DRY.

using System;
using System.Web;
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace Utilities
{    
    public class ImpersonateUser
    {
        public const int LOGON32_LOGON_INTERACTIVE = 2;
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        WindowsImpersonationContext impersonationContext;

        [DllImport("advapi32.dll")]
        public static extern int LogonUserA(String lpszUserName,
            String lpszDomain,
            String lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            ref IntPtr phToken);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
            int impersonationLevel,
            ref IntPtr hNewToken);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public bool ImpersonateValidUser(String userName, String domain, String password)
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                            return true;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return false;
        }

        public void UndoImpersonation()
        {
            impersonationContext.Undo();
        }
    }
}

After referencing my Utilities namespace I was then able to impersonate the account required for uploading:

if (FileUpload1.HasFile)
{
    ImpersonateUser impersonateUser = new ImpersonateUser();

    if (impersonateUser.ImpersonateValidUser("userName", "", "password"))
    {
        FileUpload1.SaveAs(Server.MapPath("~/files/fileName.txt"));
        impersonateUser.UndoImpersonation();
    }
    else
    {
        throw new Exception("Identity impersonation has failed.");
    }   
}

*The SaveAs method of the FileUpload control requires a root path. Using Server.MapPath will provide the root path of your IIS virtual folder.

System.Drawing.Color Hex Values

Posted by Ryan Baxter Wed, 16 Apr 2008 23:29:00 GMT

Do you know the hexidecimal value of PapayaWhip? How about BlanchedAlmond? Me either. I’m not a big fan of the System.Drawing.Color structure in the Microsoft .NET Framework. I don’t think the addition of color names makes good framework design sense. Unless you’re an Interior Designer; the majority of these colors won’t make sense to you either.

I’ve recently spent time reworking a few design elements of an ASP.NET website. All design related ASP.NET attributes were replaced with Cascading Style Sheets (CSS) where applicable. Unfortunately the website was spattered with named colors from the System.Drawing.Color structure. To help replace these named colors with hexadecimal values, I found the following resource extremely helpful.

http://www.opinionatedgeek.com/DotNet/Tools/Colors/default.aspx

ASP.NET AJAX Control Toolkit: Transparent Tab Control Images

Posted by Ryan Baxter Thu, 10 Apr 2008 15:18:00 GMT

I’ve found a use for the Tab Control that is included with the ASP.NET AJAX Control Toolkit. The control’s default style is passable for now, but I’ve grown tired of looking at the white borders surrounding active tabs. If your background is not white, you’ve probably noticed this too.

To fix this, I’ve edited the images and posted them here. I’m not sure why the two active tab images were missed when all of the other images have transparent borders. Here are the before and after shots. Please don’t use these.

Before   After
 

Setting Focus in ASP.NET Ajax Pages

Posted by Ryan Baxter Mon, 31 Mar 2008 22:24:00 GMT

At the new job I’ve been using a lot of ASP.NET Ajax to help ease the transition of users from VB6 desktop applications to web applications on our company intranet. In doing this, the UpdatePanel has become my new best friend. Albeit charming, my old ASP.NET 2.0 friends were not as impressed.

With ASP.NET 2.0, came the long-awaited Focus method that allowed developers to set the page focus without having to write any JavaScript. Developers loved it and all was right with the world. That is until ASP.NET Ajax showed up.

I recently spent way too much time trying set the page focus on a page that contained just a few TextBox controls and an UpdatePanel. My site’s ScriptManager was located in a MasterPage, but more on that later. My obligatory googling turned up many work arounds, but none as simple as the following:

// Example

if (Page.IsPostback)
{   
    // Use the GetCurrent method if your ScriptManager is located
    // in a MasterPage. Word.
    ScriptManager.GetCurrent(this.Page).SetFocus(TextBox1);
}
else
{
    // Here is the money.
    AjaxControlToolkit.Utility.SetFocusOnLoad(TextBox2);
}

The above example is a two-fer. The ScriptManager’s SetFocus method is handy, but remember that only one ScriptManager is allowed per page and if you’ve put your ScriptManager in a MasterPage, then you’ll need to access it in code using the GetCurrent method of the ScriptManager class.

Two. The ASP.NET 2.0 UpdatePanel is not the only Ajax control. Download the ASP.NET Ajax Control Toolkit. With this toolkit, you’ll have access to dozens of controls and best of all – the SetFocusOnLoad method. Located in the Utility class, the SetFocusOnLoad method is the answer to your !Page.IsPostback problems.

Cannot convert type 'ASP.login_aspx' to 'System.Web.UI.WebControls.Login'

Posted by Ryan Baxter Thu, 28 Feb 2008 18:38:00 GMT

Just a quick fix. If you’re experiencing the error message, Cannot convert type ‘ASP.login_aspx’ to ‘System.Web.UI.WebControl, try renaming your page from Login.aspx to something else.

I ran across this earlier this morning when attempting to deploy an ASP.NET 2.0 WebSite project. My code worked great locally (isn’t that always the case). I haven’t had time to really dig into why this happens, but maybe someone else can provide an answer.

Expect the Unexpected: bool IsInRole(string role)

Posted by Ryan Baxter Tue, 10 Jul 2007 02:34:00 GMT

Running some tests yesterday, I was alarmed by an Exception that read, “The trust relationship between the primary domain and the trusted domain failed.” What?!? This code worked a few weeks ago! The method in question called Page.User.IsInRole(“DomainName\RoleName”) to determine if a user was assigned to an administrator’s role. bool IsAdministrator(). Simple and efficient. Why is this happening?!?

IsInRole

In short, the role that I was supplying Page.User.IsInRole with contained a typo. What is interesting is the results of my test case found below. Pay attention to the method signatures and their outcome.

Page.User.IsInRole(“DomainName\RoleName”) returns true
Page.User.IsInRole(“RoleName”) returns true

Page.User.IsInRole(“DomainName\TypoRoleName”) returns false

But…

Page.User.IsInRole(“TypoRoleName”) throws the Exception

Huh?

I haven’t had time to dig further into this, but I’d definitely be interested in hearing some opinions.