Monday, November 03, 2008

Google vote map wins 3 to 1, but I'll had to drive 3 hours

Apparently "Pulaski" is a common Ukrainian name, and they like to put American Citizens Clubs on streets with that name.

I saw Scott Hanselmans's tweet about Google's 2008 US Voter Info map.

For the heck of it, I tried my current address and 3 places I used to live, one of which being the town of Cohoes, outside of Albany NY (the capital city, in what is considered to be upstate NY).

Google suggested that I drive 170 mi to the Ukrainian American Citizens Club on Pulaski Avenue in Staten Island. Interestingly, the place I *did* vote 4 years ago was the Ukrainian American Citizens Club on Pulaski Street in Cohoes, NY. They had the right place, (almost) the right street name, just the wrong city.

It's a good thing I moved, or I'd have to forfeit my vote as the absentee ballot probably wouldn't get there in time.

Wednesday, October 15, 2008

Tron guy is a PC

Who says Microsoft doesn't have a sense of humor? Not only are they copying the image of John Hodgman's buttoned up "PC" from the Mac ads, a recent marketing email (obviously a long delayed rebuttal to those ads which accompanies the TV ad series) includes a thumbnail of none other than the Tron guy.

Thursday, October 02, 2008

Sometimes Google scares me

My parents just got a new dog.  They sent me a short note about it when it came home for the first time.  In the email the following words are mentioned that relate to dogs within the context of the message, those that could be understood to have to do with dogs outside the message context are in bold:
  • spayed
  • standard poodle
  • lab
  • brush
  • paw (lots of animals have paws, and it's a verb)
My gmail account showed some ads as it always does, they can be seen to the right.  This was one of the rare occasions that I actually looked at them.

Among the ads is one for "Australian Labradoodles".   My parent's new dog just happens to be a lab poodle mix.  However, nowhere in the message is that mentioned apart from the simultaneous occurrence of "lab" with "poodle" in the message.  Obviously though, any astute advertiser would pair those words for their labradoodle business.  Interestingly though, none of the ads seem to directly deal with having animals fixed.

It just amazes me how accurate the google ads can be given so little to go on.  I recently finished reading "The Google Story" which explains a bit about the general ideas behind google's methodologies of search ranking, but doesn't say too much about it's ad matching techniques apart from the word bidding concepts (understandably).  (Very good book, by the way, I highly recommend it.)

I wonder how similar the results would be if I wrote an email saying:
After I brush my teeth I'm going to paw through a catalog then take the poodle to be spayed.

Wednesday, September 10, 2008

Identifying servers in a web farm with IIS headers

Once your application has been deployed to a web server farm, it can become tricky to track down problems.  Particularly when a problem occurs intermittently.  Sometimes these intermittent problems are such because they are occurring on only one machine of a web farm.  

Identifying the problem server can be rather challenging.  Often the first attempt is to modify your local DNS (in Windows it's the HOSTS file) to point the site URL to a single machine.  Depending on how your web farm is set up you may not be able to do this because the individual machines may not be visible to you.  Only the farm's pool address is visible.  Furthermore, sometimes the problems we encounter do not manifest themselves when running on a single environment (otherwise we'd have caught them in development right??).  To complicate the matters moreso, often the only chance you have to identify on which machine the problem occurred is right when it occurred, as in, when you are staring at the application crash page.  Simply attempting to replicate the problem after you set up your tracking may not be enough.

A simple solution I have implemented on our staging and production web farms involves nothing more than the built in HTTP headers supplied by IIS.  First, just add an HTTP header to each machine in the farm that contains the name of the machine, or any other unique value that you can map to the machine:


Then, when you browse to the site or are looking at an error message, you can open a tool like Fiddler or FireBug to view the page's HTTP header information for the response.




Particularly with a tool such as FireBug or another DOM inspector, you can get immediate information without having to start any kind of tracking tool or needing to relaunch the site.

Thursday, September 04, 2008

Correction: Chrome does cheque speling

I recently posted about chrome and complained that it doesn't have spell check.  Apparently it does.  But it doesn't seem to work in Blogger.  Odd considering Google owns Blogger.

Spellcheck seems to work in regular textboxes, but Blogger's "compose" view doesn't use that it seems.  I'm not sure what it uses though.  I tried the Chrome page inspector but I can't see what it's doing.

Oh well, I suppose that's part of being beta.

Wednesday, September 03, 2008

Enriching .NET Windows Apps with the WebBrowser control

I am currently working on a desktop product upgrade project.  The old versions were developed on the .NET 1.1 platform.  They utilized a web browser control to display information for printing.  Unfortunately the support for hosting a web browser control in a windows form was poor so the original development team had to create their own control with hooks into the Internet Explorer objects and such to do it.  Among other changes, we are doing a complete re-write of this application in .NET 2.0.  (We still need to support some older platforms, so 3.0 wasn't an option.)

One of the requirements of the new version dictated that we need to do some more intricate display of the information.  The prime display control candidate for this information is a "tree-grid" hybrid.  The standard .NET 2.0 toolbox simply doesn't have a control that can handle what we need (a shame really).  There are many third party controls that could do this, but that introduced a learning curve that our project timeline simply wouldn't support.  Obviously, there is additional cost involved with such a control as well.  As I evaluated what we needed to achieve, and being a web developer, I naturally looked towards HTML as a solution.  The desired output could be executed very simply with standard HTML constructs.

While analyzing the current application architecture and scoping out how we were going to integrate the changes, we decided to change the data storage strategy as well.  The application uses a local MS-Access database with a small set of tables to store standard relational data.  Given that we really don't need relational access to the ancillary tables of the data model, we determined that we could simplify the whole thing greatly by reducing the data architecture to a single table with a blob of XML to represent the bulk of the record's detail.

Now that we have serialization going on for database storage, the natural step was to use that XML for display.  One of the great additions made in fx 2.0 is the System.Windows.Forms.WebBrowser control class.  This provides simple, native hosting of a web browser inside a windows form.  To solve the complex display problem, we placed a web browser control on the main user control, serialize the data model object instance to XML, apply an XSL transformation to it then feed the result directly to the web browser control in the form.  The browser control has the property "DocumentText" which you can write HTML directly to.  Elegant, simple and surprisingly fast.  A natural side effect of this strategy is that it becomes trivial to change the view of the data: simply develop a different style sheet and provide a switching mechanism.

While generating XML, transforming it to HTML and displaying it on the form was now very easy with the browser control, the big question was, how do we interact with it.  

In order for the browser to interact with the user control, it must be exposed to COM by being decorated with the COMVisibleAttribute class.

[ComVisible(true)]
public partial class OurUserControl : UserControl
{
...
}

This exposes the object to COM and thus allows the COM based browser to see and interact with it.  Now we need to tell the browser what to interact with.  The browser control has the property "ObjectForScripting".  You give this property any object in your windows application context.  In our case, when the user control is created, we hand the browser the actual control instance.

public OurUserControl()
{
InitializeComponent();
webBrowser1.ObjectForScripting = this;
}

This exposes the object to the web browser's window as "window.external".

In order for the browser context (i.e. the HTML DOM) to call the methods on the win form context scripting object (the windows user control), we need to make some methods visible.  This is simply a matter of making a public method on the object you have exposed to the browser:

//this is managed code in the win forms application
public void DoSomething(args...)
{
//do stuff in the windows app here
}

The browser can now call that method by calling the document window's "external" object.

/* This is "client-side" javascript living
 in the HTML sent to the web browser */
function doSomething(){
window.external.DoSomething();
}

Now you can call this javascript method as you would in normal HTML.

When it comes to argument types, there seems to be a certain amount of implicit conversion going on.  In my experiments, I found that a javascript based variable that was typed to a numeric value came into the managed method call as such.  So if you used "parseInt(...)" in javascript, you should expect that the managed call will receive a proper System.Int32 as the argument value.  In most cases what I'm dealing with are strings so the argument values slip right through without any fuss.  If the value type doesn't match up, you'll get an exception about it for sure.

The web browser control also allows you to access the browser's DOM.  The Document property returns an instance of HtmlDocument.  From here you can get at an instance of an HTML control and manipulate the DOM as you see fit from the managed code.  The browser control itself has many methods and properties to direct it as needed.

All in all, I'm finding the web browser to be a compelling tool for developing richer windows forms applications using my existing web knowledge and without the need for purchasing additional control libraries.  In a very short time, my team has been able to do some very good proof of concept work that is leading into rapid development of something that only a short time ago had me very concerned for the project timeline.  We did some initial tests with a basic prototype on various platforms to ensure we weren't getting into a snag.  The application ran happily on Windows XP, Windows 2000 and Windows Vista.  Those are our target platforms, so I'm pleased with the outcome.

The recent (yesterday) release of Google Chrome suggests that we might one day be able to integrate the open source WebKit rendering engine as an alternative to the embedded Internet Explorer browser control.  Aside from the obvious decoupling of our application from I.E., this could also mean that our application could potentially run on a non-windows .NET platform such as Mono.  However, we'll stick with I.E. and windows for now.  The enhancements we are making with the web browser rendering and .NET 2.0 upgrade are enough for this go around.

Google Chrome: Shiny, new and very cool

I just finished reading the 38 page comic style technical overview book on Chrome.  They implemented some pretty interesting things.  Of definite interest is the process isolation used to separate the tab and plugin processes.  As a GMail user, I notice the performance affects on the other tabs when I'm running GMail.  Also, with the bloated Flash and PDF plugins, it seems that so many page loads just bog everything down.  It will be interesting to see what the performance is like with Chrome.  

Other particularly interesting features are the "incognito" mode tab that does not log any history and the new-from-scratch javascript engine/virtual machine they are calling V8.

A couple things I've already noticed that I'm a little dissappointed with: There doesn't seem to be an automatic spell check like Mozilla has, and the zoom feature is only a text size changer, not a natural zoom like Opera or the latest Mozilla.  Perhaps they are still working on that.

Despite being currently beta, as are so many of Goggle's applications, it's pretty fair to say that it's still better than many other applications.  Being open source, it will be fun to see all the projects that spin off from the various pieces that make up this new browser.

I'm definately going to give Chrome a whirl and see how my web experience changes.  And of course, now I need to test all my web applications to see if they behave!

Saturday, August 30, 2008

MaxiVista as a Keyboard/Mouse switch

In order to connect to my workplace VPN, I am required to use my work laptop which has a custom VPN client. Unfortunately, they don't give us the VPN client so I'm unable to install it on another machine such as my home computer. I don't have the extra hardware or space at home to set up a full workstation for the laptop with my preferred keyboard and mouse. However, I have those set up on my home workstation and a copy of MaxiVista.

MaxiVista is a utility that allows you to use another physical PC connected to your LAN as an additional monitor. It's not capable of high speed graphics but quite suitable for development. When you move the mouse pointer across screen boundaries, you switch between your locally attached display and the network attached display. One of the features of MaxiVista is the ability to switch the remote screen between "additional monitor" mode and "remote control" mode. This basically allows you to use MaxiVista as an automatic K/M switch, using your primary PC (running the MaxiVista server) as the hardware host for the keyboard and mouse but work on the remote PC desktop.

So I fire up my laptop, connect to the work VPN, then use the remote control method of MaxiVista on my home workstation to use the better keyboard and mouse on my laptop. While working, I can instantly move over to my home workstation screens. This can be particularly helpful when I want to test web applications or .NET remoting scenarios I'm developing on the laptop. I can jump right to my home environment to test network behavior.