Wednesday, May 07, 2008

RC4 encryption for classic ASP stops working 

This was an interesting gotcha which I'd like to blame on Visual Studio 2008, but it is undeserved.

Microsoft dropped support for Intellisense and color-coding for classic ASP in Visual Studio 2008, but I still use it to maintain some old sites.

Well, after some minor changes to an old site, suddenly, the RC4 encryption code, by Mike Shaffer, that I was using didn't work any more. The answer really surprised me.

To make a LONG story short, I opened the site in VS08 and created a new include file for a page I was modifying. I included the file into the primary page and that caused the RC4 code to stop producing the correct output.

Visual Studio 2008 created the new include file using UTF-8 encoding. Well, for some reason that broke the RC4 encryption code. I guess it's because each character would be 2 bytes instead of 1? I thought that was just Unicode and classic ASP won't even process a Unicode file (UNICODE ASP files are not supported). I don't know.

My resolution was to make sure the classic ASP page and all its includes were saved as ANSI text. Here Notepad++ (Menu > Format > Encode in ANSI) came in very handy again.

Maybe someday I will understand The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character. Scott Hanselman also has an interesting post on the CodePage versus the CharSet in classic ASP.

Microsoft Drops Classic ASP Support in Visual Studio 2008 

I upgraded to Visual Studio 2008 as soon as it came out. I was tempted to get rid of Visual Studio 2005 since VS08 had multi-targeting support and I assumed that the new Visual Studio had all the functionality of previous versions. Well, I was wrong.

For better or worse, I still have to support some Classic ASP and VBScript code, well Microsoft dropped Intellisense and color-coding for classic ASP. Recommended solution: Keep my 2.5 GB install of VS05 around for those days when you need it.

I can't believe it myself. How detrimental or hard was it to maintain even just basic syntax highlighting? Even an open source product like Notepad++ offers that. Wow.

I recently found another gotcha which I will include in another post.

UDPATE [5/12/2008]: Looks like VS08 SP1 will bring back support for classic ASP. Cool!

Labels: , , , , ,


Friday, January 18, 2008

HttpFileCollection Always Zero 

I ran into and interesting problem recently trying to get an AJAX style file upload working with an HttpHandler. The HttpFileCollection (Request.Files) was always empty with a count of zero.
(Request.Files == 0) == true

I was using the AjaxFileUpload, a jQuery plug-in intended to be paired with PHP, but compatible with any server side handler. Since I use ASP.NET, I wrote an HttpHandler to receive the form post, save the file on the server, and send a JSON response.

Without investigating too closely, it looks like the AjaxFileUpload creates an iframe, moves the html file input into the iframe and submits it to specified handler. I didn't want to user "runat='server'" controls so I just put a plain html input tag in the page like so.

<input type="file" id="AjaxFileInput" />

I ran my project and everything seemed to be working and submitting, fine, but the HttpFileCollection always had a count of 0.

I created a simple page with no ajax that posted back to itself to test the plain HTML inputs, and the Request.Files collection was still empty. I tried adding the "runat='server'" attribute and it suddenly worked, of course. I didn't want to user server controls, because I wanted to add new inputs as needed with client script.

It seemed like the Request.Files collection would only be populated if I used the ASP.NET server controls, but I could not think of any reason why. Finally, I looked at the code rendered by the server controls and discovered the answer.

Every site I found said there were 2 things you needed to get the HttpFileCollection to populate.

1) Make sure the form method is "POST"
2) Make sure the form enctype is "multipart/form-data"

The AjaxFileUpload code dutifully had this right, however there is one more thing that ASP.NET needs.

3) The HTML file input must have a "name" attribute.

Here is a final sample of an accurately constructed plain HTML form that will populate the Request.Files collection.

<form action="" method="POST" name="form1" id="form1" enctype="multipart/form-data">
    <input type="file" id="AjaxFileInput" name="AjaxFileInput" />
</form>


This seems like a bug, to me, and I don't know if .NET 3.0-5 fixes this. This document does not reflect what I have found to be true.

Wednesday, October 31, 2007

Print Page from IE without Prompt 

This code should send a page straight to the printer without prompting the user. It worked in IE6, but I don't know about IE7. I am sure there are some security concerns with it.


<html>
<head>
<script language="javascript">
    function ieExecWB(intOLEcmd, intOLEparam)
    {
        var WebBrowser = '<OBJECT ID="PrintBrowser" WIDTH=0 HEIGHT=0 CLASSID="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2"></OBJECT>';
        document.body.insertAdjacentHTML('beforeEnd', WebBrowser);
        if ( ( ! intOLEparam ) || ( intOLEparam < -1 )  || ( intOLEparam > 1 ) )
        { 
            intOLEparam = 1;
        }
        PrintBrowser.ExecWB(intOLEcmd, intOLEparam);
        PrintBrowser.outerHTML = "";
    }
</script>
</head>
<body>

<p><a href="javascript:ieExecWB(6, -1);">print</a></p>

</body>
</html>

NOTE: I don't know where I found this code so if someone needs attribution or it violates a copyright or something, let me know.

Saturday, August 11, 2007

Optional Radio Buttons 

It has always bugged me that you can't really make radio buttons optional on web form. You can load all the radio buttons in a group as un-checked, but as soon as the user selects one then a value from that check box group will be submitted.

You can get around this problem by adding one option to the group and labeling it "N/A" or something. This gives the user an out. Incredibly, I have never been able to convince any of my customers to go that route. In fact, even if the radio group is required they will want the all of the options unchecked initially.

Most people get around this by writing their own logic over check boxes, but I decided to take a different approach. I finally wrote some JavaScript which will un-check a radio button if the button you click is already checked, thus allowing the user an escape route.


function RadioClick(radio)
{
var inputs = document.getElementsByTagName("input");
var checked = (radio.getAttribute("shadow") == "true");
for(var i = 0; i < inputs.length; i++)
{
if (inputs[i].getAttribute("type") == "radio" && inputs[i].name == radio.name)
{
inputs[i].setAttribute("shadow", "false");
}
}
if (checked)
{
radio.checked = false;
}
else
{
radio.setAttribute("shadow", "true");
}
}


All you have to do is add this script to your page and then just add "RadioClick" to the radio button's onClick event, like so...


<input id="ctl01" type="radio" name="GroupName" value="ctl01"
checked="checked" onclick="javascript:RadioClick(this);" />


You could easily make this script unobtrusive by adding a method that assigns onClick event by group name when the page loads.

Friday, October 13, 2006

DataFormatString Doesn't Work 

I think this might be old news, but it was new to me. If you are using a GridView (and potentially any DataBoundColumn) and you take advantage of the DataFormatString you will be in for a surprise--it may not work.

[Here is the "bug" report]

You must also set the HtmlEncode attribute to false. The explanation in the bug report doesn't make sense to me though. So what if the bound value is HTML encoded. Can't the format string still be applied? I guess if the datatype is changed to string then special format strings like "{0:C}" for currency or "{0:MM/dd/YYYY}" for DateTime won't work.

Wednesday, September 06, 2006

Generic HttpContext Singleton 

Joel Ross has an interesting post about implementing the singleton pattern for objects used during the lifecycle of a web request.

This got me thinking about the Generic singleton implementation that I have used before. I wondered if you could combine the two to make a Generic HttpContext singleton. Here is my first attempt. I think it should work, but I have not tried it.

I guess the key is the "key". It may be better to use the fully qualified class name for the key instead of just using the generic type's name. It may also make sense to add a "Singleton_" prefix to the name to give it a namespace within the HttpContext.


    1 using System;

    2 using System.Collections.Generic;

    3 using System.Web;

    4 using System.Runtime.Serialization;

    5 

    6 namespace jedatu

    7 {

    8     public class ContextSingleton<T> where T : ISerializable, new()

    9     {

   10         protected ContextSingleton() { }

   11 

   12         public static T Instance

   13         {

   14             get { return Factory.Current.Instance; }

   15         }

   16 

   17         private class Factory

   18         {

   19             static Factory() { }

   20 

   21             internal static Factory Current = new Factory();

   22 

   23             internal static readonly T _instance = new T();

   24 

   25             internal T Instance

   26             {

   27                 get

   28                 {

   29                     if (HttpContext.Current == null) { return null; }

   30                     if (HttpContext.Current.Items[_instance.GetType().Name] == null)

   31                     {

   32                         HttpContext.Current.Items[_instance.GetType().Name] = _instance;

   33                     }

   34                     return (T)HttpContext.Current.Items[_instance.GetType().Name];

   35                 }

   36             }

   37         }

   38     }

   39 }


Wednesday, August 02, 2006

PowerShell Baby Step: Change File Attributes 

I really think there is a lot of potential wrapped up in PowerShell, but since I have rarely used Linux and rarely write batch files, I have hard time getting my head around how to use PowerShell.

I do know that I hate the limitations of batch files and have thought about using Ruby and now PowerShell instead. I installed ShinyPower to help me navigate the PowerShell help. I read some tutorials. Gradually, I was getting ready to do something.

Well, today I finally wrote my first PowerShell code and this is why.

I use a fantastic program called TimeSnapper. It saves an image of my screen at a pre-determined interval--in my case every 5 minutes. This helps me keep track of what I have been working on. Well, I copied the image files to a new location and the CreateDate changed. This meant that TimeSnapper thought all the images were captured at the same time each day. Ugh. Then I thought, "this sounds like a job for PowerShell"

After a little exploration I came up with a script to fix the problem with the files.

ls | foreach { $_.CreationTime = $_.LastWriteTime }

Breakdown:
Step1 [ ls ] Call the ls alias to list the files in a given directory.
Step2 [ | ] Pipe the resulting list of FileObjectInfo objects to a for each statement
Step3 [ foreach { ] Begin the for each
Step4 [ $_ ] Reference the current object in the collection
Step5 [ .CreationTime = $_.LastWriteTime ] Set the CreationTime equal to the LastWriteTime
Step6 [ } ] End the for each

In the end, it's a pretty simple one-line script, but it helped me make some progress understanding the PowerShell syntax.

Here's some other cool PowerShell tricks. "Can your programming language do this?"

This page is powered by Blogger. Isn't yours?