Monday, November 23, 2009

CDs and DVDs - Why?

I remember when I saw my first CD, it was back in the mid-80s. Revolutionary, you could skip to different song within a second. But that was more than 20 years ago! DVDs delivered more storage, but the same issues as the CD – it easily scratches.

 I remember soon after the CD came out I spent ½ years worth of allowances to purchase my first high storage drive, the Commodore 1581. It could store a whopping 1 Meg of storage (great for my BBS – The Surf Board!), but what I remember distinctly is that it was the first time I used the 3 ½ floppy. Sure you can make fun of the disk now due to it’s low storage, but since the actual magnetic disk was encased in plastic, you could throw it across the room, rub sandpaper across it, and it would still work.

Last week my wife got a DVD from the library for our 3 year old son, Bear and the Big Blue House, and I was frustrated due to the frequent skips. How long does a DVD last with 3 year olds handling it? About 5 minutes I would guess. I feel we’ve advanced so far in all aspects of technology, yet we still seemed plagued with this bad storage medium.

Blue Ray? Slightly better, but still not adopted everywhere. Solid State HDs seem very promising, but I’m not seeing Bear and the Big Blue House on a 2 Gig stick at the library. Or a USB port on my TV that will allow me to play it.

I’m hoping soon CDs and DVDs will be relics on the wall, as for now I’ll continue to Fast Forward and rewind past bad frames…

Thursday, November 12, 2009

Asyncronous file upload in asp.net

I recently had a customer request a feature to upload files to their account.

It's an interesting architectural dilemma, since the file is on the client, the file is to be stored on the Server (in my case, not even the web server), and I definitely wanted to avoid postbacks since it was a rich web app and a postback would look/behave badly.

Some options are AjaxUploader, while it looks solid, I didn't want to pay for the service at the time since paperwork for this type of functionality was more work than coding from scratch.

Another option was the AsyncFileUploader which comes with the latest Microsoft Toolkit, screenshot below. It does an automatic upload on selection, and provides a mind-numbing green background on success, and a red background if it was unsuccessful (which is a nice feature!)


Unfortunately, this great control had errors with IE6. Since a lot of our users are on IE6, this is a show-stopper.

I adopted an idea from a co-worker, kludgy, but effective. Essentially, you put a file upload control in an iFrame (so a postback within the iFrame doesn't postback the entire page), then send a Javascript message from the code behind when the file upload is complete. There were several challenges with this:
  1. asp.net name mangling
  2. Lots of Javascript
  3. Updating the asp.net grid within the UpdatePanel so a full page refresh doesn't happen
Here was the result, works pretty well:

Notice that the filename can be clicked to be viewed, and the delete option, these are all done in the asp.net code behind and done without full postback since the grid is within an UpdatePanel.

So how do you update the grid on file upload?

I added a linkbutton on the grid with associated codebehind (I kept the LinkButton1 name for posterity):
  
protected void LinkButton1_Click(object sender, EventArgs e)
{
   LoadDocs();
}
Now, when the file uploads, simply call the javascript function uploadNotify, via ServerCode:
ClientScript.RegisterStartupScript(this.GetType(), "uploadNotify", script);
Now, the final step? Write the uploadNotify script on the parent page:
function raiseAsyncPostback() {
   __doPostBack("<%= this.LinkButton1.UniqueID %>", "");
}
The UniqueId is resolved to the mangled name (this nuisance now resolved in .net 4.0 - yay!)

That's what it takes! Kludgy, but effective, and gives you highly customizable options. Personally, I'd wait for the Toolkit version to be spiffed up, looks really good.

Thursday, November 5, 2009

Silverlight Autocompletebox with custom dropdown

I needed to create an Autocompletebox for selecting staff. I wanted a robust select so you can type in the first name of the employee, last name, staff id, or even the office the staff member resided in, and the list would be filtered and selectable in the dropdown.

Once selected, the box could fire an event that would load additional info about the employee. Here is what it looks like, this is before I put in pretty formating, keep in mind I'm a coder, not an artist. :)

I decided to get the staff member via a WCF call, here is the GetStaffList() call I defined and am returning a custom class so I can specify the exact search criteria.

[OperationContract]
public List GetStaffList()
{
   Csla.ApplicationContext.ClientContext["HostName"] = // I used CSLA, put address here;

   List staffList = new List();
   StaffViewListClass staffListClass = StaffViewListClass.GetStaff();

   foreach (StaffViewClass staff in staffListClass)
   {
      staffList.Add(new StaffSearchClass(staff.FullName, staff.FirstName,
                  staff.OfficeName, staff.StaffId));
   }
   return staffList;
}

And here is the custom class definition:

[DataContract]
    public class StaffSearchClass
    {
        [DataMember]
        public string FullName { get; set; }
        [DataMember]
        public string StaffId { get; set; }
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string OfficeName { get; set; }
        [DataMember]
        public string DisplayValue { get; set; }

        public StaffSearchClass(string fullName, string firstName, string officeName, string staffId)
        {
            FullName = fullName;
            FirstName = firstName;
            OfficeName = officeName;
            StaffId = staffId;
            DisplayValue = StaffId + " " + FullName;
        }
    }

Note the use of [DataContract] and [DataMember] attributes. These are important so the ServiceReference knows about them.

The next phase was to create a custom searchable Autocomplete box. Jeff Wilcox Microsoft MVP has a great "missing guide"

Step 1: In your Silverlight project, add a Service Reference to your WCF Service.

Step 2: Get the Staff Data Asyncronously. Here is my MainPage() method:
public MainPage()
        {
            InitializeComponent();

            SilverlightAuto.StaffService.StaffServiceClient client = new SilverlightAuto.StaffService.StaffServiceClient();

            client.GetStaffListCompleted += new EventHandler(client_GetStaffListCompleted);

            client.GetStaffListAsync();

        }

        void client_GetStaffListCompleted(object sender, SilverlightAuto.StaffService.GetStaffListCompletedEventArgs e)
        {
            List list = e.Result.ToList();
            uxAuto.ItemsSource = e.Result.ToList();

            uxAuto.ItemFilter += SearchStaff;

        }

Important to note: In my ServiceReference completed event, I've added an ItemFilter to my Autocompletebox control (uxAuto). This is necessary to custom bind my search criteria (remember that I wanted to search on First name, last name, etc). Autocompletebox can't assume what you want to search on, but makes it pretty easy to customize.

Here is the SeachStaff method, you can put whatever search criteria you want, but be aware of performance if you are parsing a lot of data.

bool SearchStaff(string search, object value)
        {
            search = search.ToLower();
            SilverlightAuto.StaffService.StaffSearchClass staff = value as SilverlightAuto.StaffService.StaffSearchClass;

            if (staff != null)
            {
                if (staff.StaffId.StartsWith(search))
                    return true;
                else if (staff.FullName.ToLower().StartsWith(search))
                    return true;
                else if (staff.FirstName.ToLower().StartsWith(search))
                    return true;
                else if (staff.OfficeName.ToLower().StartsWith(search))
                    return true;
            }

            return false;
        }

As a reference, here is the Xaml for the autocomplete box. Note you need to add the System.Windows.Controls.Input declarative.

  
        
            
                
                    
                        
                        
                    
                
            
        

So remember the requirement that I needed to populate some other stuff once the staff member has been selected? That was tricky, there is no obvious event to hook into when the user has been selected, but if you look, I have an event on DropDownClosed. Seems like an odd event to tie into, but works exactly like I wanted it to since when a staff member is selected the box closes!

Overall I am really impressed with this control. I used to have to do a lot of custom coding to re-create this behaviour in web forms, and it's really kludgy to do in AJAX, if you are lucky enough to get something close to this functionality.

Monday, November 2, 2009

Halloween candy consolidation?

It occurred to me while raiding looking through my son’s Halloween candy yesterday, that all people bought the same candy to give out to treaters. In fact, I think if I held up my son’s loot next to the Costco "mixed" snack size candy, they would be identical.

Apart from M and M’s, snickers, butterfinger, and Hersheys snack size candy, there were no unique candies. If I’m not mistaken, most of the treats came from the same manufacturer, Mars Inc. (or Hersheys). There were also a lot less houses participating, my guess is every second house did not give out treats. My era? 1 in 10 did not participate.

Next year I am going to search for some unique treats, and buy a lot of the full size bars for the cool costumes – let’s treat the kids right!