Joshua Stengel

Everything...Is going...
To be okay!
"Gmail is temporarily unable to access your Contacts." How do they know?

image

So, Gmail seems to be having problems again.  They seem confident that this is "temporary", but how do they know that and how do we know that they haven't just decided to pull the plug on this free "beta" service?

Is Gmail still good enough?

My Netbook...90 days later

I decided to jump into the netbook arena when I saw a nice brown (yes, I also have a brown Zune) Acer One for under $300 (got mine for $270 before they became more popular).  With 1gb RAM and a 16gb SSD for a hard drive I figured I'd see what it could do. It came with XP home and an Office 2007 trial pre-loaded. My first impression was that I was actually kind of impressed with the performance. Web-browsing, document manipulation, and general futzing around seemed on par with your average 2+ year old PC.

I started getting a little bored.  I was reading about the virtues of Ubuntu, a Linux-based OS.  Long story short, I loaded fresh install of the Ubuntu Netbook Remix and found it to be...meh? Sure, the UI was a little snappier in a few areas.  I really liked the Desktop and how that worked.  Finding Windows-equivalent applications was relatively easy once I figured out software installation works in Ubuntu (pretty nifty, by the way).  I had a few challenges finding the right drivers for some stuff, but all-in-all it was pretty straight-forward.

Time to take it on the road.  After all, that's why I got the thing right?  Well, it travels well and made my standard laptop seem like a "luggable" from back in the day.  Battery life isn't stellar with my 3-cell battery, but I did make it all the way through "Paul Blart: Mall Cop" on the plane--unfortunately. The 6-cell obviously has a longer life but makes it all heavier and sticks out funny. Wi-fi picked up hotspots with ease.

The rub. I'm a gadget-man and not ashamed to admit it.  I love it when gadgets work and hate it when they don't.  On my first trip traveling with the Ubuntu netbook, I found out that I couldn't get several of my favorite gadgets to work with Ubuntu.  My dive computer, GPS watch, and Zune (yes, the brown one) did not have compatible drivers and/or software. Maybe it's possible under various flavors of emulators, but I tried really, really hard with no luck.  The other major issue I had with Ubuntu was with OpenOffice.  While I admire the efforts of that community, OpenOffice acts and feels like imitation crab. It's a workable substitute, but you won't enjoy it.

After the road trip, it was back to XP.  I installed a netbook-friendly "flavor" of XP, reloaded all my favorite Windows-friendly apps and...well...now the thing ran like crap.  DON'T USE NTFS ON AN SSD DRIVE!

Thanks to the good folks at PartitionMagic, I was able to drop down to Fat32 and things were back to smooth sailing.  Replacing the 512mb RAM module with a 1gb module was a bit of a chore but probably worth the $20.

Now let's crank things up...

What would happen if I wanted to use this bugger as an emergency web-dev tool?  I loaded all of my basic "go-to" development apps including: .NET Frameworks 2.0 & 3.5, Web Developer Express 2008, SQL Server Express 2008 + Management Studio, IIS 7.0, Silverlight 2 & 3, and some other lightweight apps).

The verdict?  It works! Realistically, I'm not going to use this for day-to-day work, but as an on-the-road-in-a-pinch, I would feel confident in being able to pound out some inspired code on the fly or jump in to work on an emergency situation.

When tech gets in the way of the process...back off!

In a recent focus group meeting I was helping to facilitate I was once again reminded of the importance of realizing when you're trying to force something that is getting in the way of the primary objective.  Our negotiated contract with the client was to use the focus group to help construct a logic model that the agency could begin to use to focus themselves. 

What rapidly became apparent was that there was little understanding or appetite in the group for building a logic model and the meeting had to shift to a new process--fast.  The beauty was that the client loved it and the participants never noticed.  Though they were initially sold on the the "logic model", the resulting process was organic and brought the group to a place beyond what people were expecting.  We can build the logic model in the background based on the information we got, but we couldn't have gotten the level of information we needed had we tried to pound through the logic model as a group.

I'm as guilty as anyone for finding new technologies that have so much potential yet may not be the right thing at the right time.  Forcing implementation under these circumstances is painful and frustrating for everyone.  I find that, if I stay open from the start to the possibility that, no matter how cool the technology, if things start feeling "forced" I know it's time to back off. Just bust out the sticky notes, markers, white pads and start kickin' it old school until things are back on track.

Google Voice: Highs & Lows

I recently got my invitation to try out Google's new Voice service.  Once again, the price is free and you can get your own invitation here.  Setting up yet another dependency on a free beta product from Google concerns me but not enough to keep me from trying it out.

Getting setup is pretty simple.  You can pick a phone number for yourself ($10 fee to change it later, so don't screw up!).  I did a search for the last four digits of my current mobile number and got a number that was very similar--don't know why this was important to me, but it was.  Once I picked my number, I was able to add the phones I wanted to associate with that number.  I have only one phone for everything, so that part wasn't terrible exciting.

The Highs

  • Easy to setup
  • Seems like plenty of numbers to chose from
  • Numbers will be portable (an initial concern of mine)
  • Price is right.  I might even pay a bit for some premium feature down the line.
  • Love the SMS feature.  Allows text messaging online even if you can't access your phone!
  • Familiar GMail-style layout
  • Able to create custom greetings just for the Google voice number (top feature for me)
  • Nice privacy features
  • Voicemail to email and call notifications

The Lows

  • Limited to one number per GMail account (maybe a nice premium feature for the future)
  • Didn't see any 800 number options (another nice premium feature for the future)
  • No direct tie-in to GMail
  • Had mixed results with the voice transcriber
  • No real app for Windows Mobile yet
  • Further pwnership by Google

Why this service works for me?

I have a consulting side to me that I like to keep somewhat separated from my personal side.  As previously mentioned, I use one phone for everything and don't want that to change. Google voice gives me a separate number that I can use to identify and triage calls coming to my phone.   My voicemail greetings make sense depending on the number people use to contact me, and I can answer the phone in a manner that also makes sense for the context of the caller.

I'm sure there will be many creative uses for this service and I am interested in hearing any you might come up with.

Getting paid enough?

30,055 participants contributed to the "A LIST APART" survey of people who are building the web (developers, designers, etc.).  Topics covered include things like, education, compensation, experience, age, ethnicity, vacation days, etc.

My favorite statistic, 13.8% of us have had a blog or personal site/blog for over a decade. 

What stood out to you?

Would you like a FREE book?

Help me spend my gift cards wisely and you can keep what I buy.

You pick them out. I buy them. I read them. I mail them to you--free of charge.

The rules are:

  1. The book(s) must be available from http://borders.com
  2. The book can be technical, fiction, audio, non-fiction, sci-fi, whatever, but it needs to be something I haven't read or don't already own.
  3. I will buy the most interesting recommendations first until my gift cards are spent, so sell me on why I should pick your recommendation.
  4. No reference books.
  5. Movies are okay, but picking a good movie that I haven't seen or don't own will be tough.
  6. If I pick your book, I'll email you to get your shipping info.  After I read your book, I'll send it to you or someone else on your behalf.
  7. USA delivery only.

Here are some things I might be interested in:

  • Books about successful businesses or business people
  • Interesting biographies
  • Comedies
  • New technical books

Tip! Get others to vote for your recommendation to improve your odds.

What the heck is the "Microsoft Web Platform Installer?"

In my TechNet Flash this morning I see this section:

Download the New Microsoft Web Platform Installer

The Microsoft Web Platform Installer lets you create a Web platform on your server. The Microsoft Web Platform is a reliable, high-performance Web stack that is capable of hosting both ASP.NET and PHP applications on a single server, and can scale to run the largest sites on the Web.

Question #1: "What is the Microsoft Web Platform?"
Question #2: "Why does it need an installer?"
Question #3: "How is it different that what I currently use to host my websites?"

So I did some reading...

Answer #1: The "Microsoft Web Platform" is nothing more than the collection of Microsoft products that might typically be installed on a web server (i.e., IIS, .NET Framework, SQL Server, VisualStudio, etc.).  It would be the equivalent of calling MS Office the "Microsoft Office Productivity Platform"--which I think is possibly how they (MS) will be referring to Office "12". 

Answer #2: The "Microsoft Web Platform Installer" is also kind of like the installer that comes with MS Office.  It allows you to selected the components you want to install, configure some settings, and carefully read through all the EULAs for the individual components before sitting back and enjoying a nice long progress bar.

Answer #3: Since you can "roll y'er own" Microsoft Web Platform by simply installing and configuring all the individual components manually, nothing is particularly special about the installer other than it is supposed to make it easier to setup a new web server.

In conclusion...

Dear Microsoft,

Thank you for providing us with fancy-smancy batch file. The fewer progress bars I have to look at the better.

However, "Boo...hiss", on the cheesy marketing description.

<rollingEyes>
The Microsoft Web Platform is a reliable, high-performance Web stack that is capable of hosting both ASP.NET and PHP applications on a single server, and can scale to run the largest sites on the Web.
</rollingEyes>

Sincerely,

Long-time "Microsoft Web Platform" Assembler

SEE ALSO:

"Just do it!", New Report Tells Government Execs about Web 2.0

In a recent report from the IBM Center for the Business of Government, government executives are strongly urged not to ignore the use of Web 2.0 technologies in their agencies and to re-think the way they serve the public.

The report is targeted at executive and management-level readers in the U.S. government and provides a nice outline of Web 2.0 technologies, how they are being used, and how the government can and should be leveraging them. Information is conveyed in a non-intimidating but firm manner using terminology and concepts common to the government world.

In my opinion, lacking from the report seems to be a good strategy for self-motivating the government to adopt Web 2.0 practices.  The government is not motivated by money in the same manner as businesses and therefore needs a realistic strategy for accepting risk as an acceptable part of innovation.

For much of the government, Evidence-Based Practice (EBP) is substantially the driving force. Unfortunately, acting only on ideas that provide evidence of a sufficient level of effectiveness creates a polarity with innovation. Therefore, what motivation does government have for adopting the always-beta, rapidly changing, and open elements found in Web 2.0?

Government, especially on a national level, typically has measures in place to determine how well it is serving its purpose. Feedback is the profit/loss performance indicator of the government world (at least in the USA). While politics and power-mongering are also forces in the system, as an ordinary citizen, feedback is how we help the government measure its customer service.

The next time you use a government service, don't just accept poor service as being "good enough for government work". If you see improvements in a government service, don't just be surprised and say nothing.  In a democracy, the government must hear from the public before it can respond.  We are not limited to a little booth on election days to talk to the government.  Every government survey, feedback form, comment card, and formal complaint is vote. Don't waste your opportunity to provide the government with the motivation they need to serve the public effectively.

Avoiding Duplication When Dynamically Adding Scripts and Styles to A Webpage

Recently, I had a project where I was wanting to be able to create a reusable UserControl to display tooltips throughout the application. The control would need to access the jQuery framework, a jQuery plugin, required some inline scripting, and had its own class of styles.  Not every page in the application would have tooltips but the pages that did use them would have a lot of them.

If I added all the references to the JavaScript and styles in the Master page, I would be introducing unnecessary bloat for the majority of the application.  So, I needed a way to request these resources in the UserControl so they would only be added to the page "on demand".

As you might image, adding them directly into the UserControl would mean that the resources would be requested for EVERY instance of the UserControl on the page.  If I used the control 10 times, the jQuery framework would get requested 10 times.  Not the most efficient design.

Fortunately, the .NET framework has a nice way of dealing with this by providing a way to dynamically add resources AND check to see if they are already loaded. 

Dynamically Adding JavaScript

If we just dynamically added links to script files, we would still have the same problem as adding them inline. So, here is a method that checks to see if the script has already been loaded and loads it only if needed:

   1: Protected Sub AddScriptFileToPage(ByVal ID As String, ByVal URL As String)
   2:     If Not Page.ClientScript.IsClientScriptIncludeRegistered(ID) Then
   3:         Page.ClientScript.RegisterClientScriptInclude(ID, URL)
   4:     End If
   5: End Sub

The one thing to note is that you need to provide some kind of ID for the script.  This ID is how .NET checks to see if the script has already been added to the page.  Personally, I think that using the filename of the JavaScript helps keep things consistent and kind of makes logical sense but it doesn't really matter as long as it will be unique to that resource.

If you need to add a block of inline JavaScript, no problem.  It's basically the same process with a tiny little tweak:

   1: Public Sub AddScriptBlockToPage(ByVal ID As String, ByVal Script As String)
   2:     If Not Page.ClientScript.IsClientScriptBlockRegistered(ID) Then
   3:         Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), ID, Script, True)
   4:     End If
   5: End Sub

 

Dynamically Adding Stylesheets

Though not as simple as adding scripts, we can do the same thing for our styles.  There are probably a number of way to do this but I chose to check the page header for an existing instance, and add a literal with the link to the stylesheet if it's not found.

   1: Public Sub AddCSSFileToPage(ByVal ID As String, ByVal URL As String)
   2:     If Page.Header.FindControl(ID) Is Nothing Then
   3:         Dim lit As New Literal()
   4:         lit.ID = ID
   5:         lit.Text = "<link rel=""Stylesheet"" type=""text/css"" href=""" & URL & """/>"
   6:         Page.Header.Controls.Add(lit)
   7:     End If
   8: End Sub

 

Making it Practical

You might be wondering why you would go through the trouble of doing all this. Lets make this a bit more useful by creating a class to help us use this functionality efficiently. I created a little ResourceLoader class in my application that looked something like this:

   1: Namespace Sample
   2:     Public Class ResourceLoader
   3:  
   4:         Public Shared Sub AddScriptFileToPage(ByVal ID As String, ByVal URL As String)
   5:             Dim p As Page = CType(System.Web.HttpContext.Current.Handler, Page)
   6:             If Not p.ClientScript.IsClientScriptIncludeRegistered(ID) Then
   7:                 p.ClientScript.RegisterClientScriptInclude(ID, URL)
   8:             End If
   9:         End Sub
  10:  
  11:         Public Shared Sub AddScriptBlockToPage(ByVal ID As String, ByVal Script As String)
  12:             Dim p As Page = CType(System.Web.HttpContext.Current.Handler, Page)
  13:             If Not p.ClientScript.IsClientScriptBlockRegistered(ID) Then
  14:                 p.ClientScript.RegisterClientScriptBlock(p.GetType(), ID, Script, True)
  15:             End If
  16:         End Sub
  17:  
  18:         Public Shared Sub AddCSSFileToPage(ByVal ID As String, ByVal URL As String)
  19:             Dim p As Page = CType(System.Web.HttpContext.Current.Handler, Page)
  20:             Dim lit As New Literal()
  21:             lit.ID = ID
  22:             lit.Text = "<link rel=""Stylesheet"" type=""text/css"" href=""" & URL & """/>"
  23:             If p.Header.FindControl(ID) Is Nothing Then
  24:                 p.Header.Controls.Add(lit)
  25:             End If
  26:         End Sub
  27:  
  28:     End Class
  29: End Namespace

Quick Note: In a class, you can't directly access the Page.  So, note how you can declare a Page and then use it in a class environment.

Now that we have this functionality in our application, we can efficiently request resources without having to worry about duplicating what has already been requested for the page.  For example, going back to my tooltip UserControl, here is how I could safely make sure that my resources are being requested but not duplicated:

   1: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
   2:    Sample.ResourceLoader.AddScriptFileToPage("jQuery.js", "Script/jQuery.js")
   3:    Sample.ResourceLoader.AddScriptFileToPage("jQuery.ClueTip.js", "Scripts/jQuery.ClueTip.js")
   4:    Sample.ResourceLoader.AddScriptBlockToPage("Tooltip.ascx", "$(document).ready(function() {$('a.Tooltip').cluetip({splitTitle: '|'},{cursor: 'pointer'});});)")
   5:    Sample.ResourceLoader.AddCSSFileToPage("jQuery.ClueTip.css", "CSS/jQuery.ClueTip.css")
   6: End Sub

Notice that every instance of the control will make sure that the jQuery framework, the plugin, the inline script, and the custom styles are loaded but, thanks to our handy-dandy ResourceLoader class, no duplication will take place.

 

Final Thoughts

Even though we aren't duplicating resource requests, we are adding more objects to the page and this potentially introduces latency issues.  It also introduces the opportunity to look at how we might extend this technique to combine everything before page makes the request.  I've been reading a few ideas on how this might done and, if I end up with a good solution, I'll write a follow up.

If you have any ideas, comments, criticisms, or suggestions please share.

Posted: Aug 01 2008, 05:23 PM by jstengel | with 1 comment(s)
Filed under: , ,
UserAgent Fix for the RSSToolkit 2.0.0.0

I frequently use the RSSToolkit to consume and display RSS feeds from other blogs.  Recently, I've noticed problems with the RSSToolkit not being able to display feed from some external sources.  In particular, I've been having trouble consuming feeds from external blogs like Blogspot and Feedburner.  The symptoms appeared over the past month or two and included the disappearance of consumed blogs and new blog posts.

After some digging, I found this entry on Obishan's blog that gave me a clue. Using Web-Sniffer, I was able to verify that if no UserAgent was provided for the request, the request was redirected (302).  This redirection seems to the source of my problems with the RSSToolkit and I'm not the only one.

This wasn't my first crack at fixing an issue with the RSSToolkit, so I spent some time tracking done how to fix this issue. Basically, I needed to find out where the RSSToolkit was actually requesting the RSS and find out how to modify the request so that it included a UserAgent. In my fix I am hardcoding in the UserAgent.  Ideally, this would be set through a property in the control.

The Fix

Step 1: Download the Source

Step 2: Update the Code

Open RSSToolkit > RSS > DownloadManager.cs and replace the DownloadFeedDom() with the following:

private CacheInfo DownLoadFeedDom(string url)
        {
            //// look for disk cache first
            CacheInfo dom = TryLoadFromDisk(url);

            if (CacheReadable(dom))
            {
                return dom;
            }

            string ttlString = null;

            //MODIFICATION: Some RSS sources like Facebook and Feedburner look
            //for a UserAgent (browser/OS information)

            String userAgent = @"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
            httpRequest.UserAgent = userAgent;
            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            XmlDocument doc = new XmlDocument();
            doc.Load(httpResponse.GetResponseStream());
            httpResponse.Close();
            doc.Save(Console.Out);

            //END OF MODIFICATION

            if (doc.SelectSingleNode("/rss/channel/ttl") != null)
            {
                ttlString = doc.SelectSingleNode("/rss/channel/ttl").Value;
            }

            //// compute expiry
            int ttlMinutes = GetTtlFromString(ttlString, _defaultTtlMinutes);
            DateTime utcExpiry = DateTime.UtcNow.AddMinutes(ttlMinutes);

            //// save to disk
            return TrySaveToDisk(doc, url, utcExpiry);
        }

Step 3: Rebuild the Project and use the new RssToolkit.dll

(Optional) Step 4: Download my copies.  My versions also include my fix for Atom feeds.

More Posts Next page »