title
Robot
29 Sep

Where have I been?

Wow, it appears that its been roughly 5 months since I last blogged. I have been pretty busy the last few months. Doing what you may ask?

  • Speaking at Code Stock 6/26/2009
  • Speaking at the Grand Rapids .NET users group 7/14/2009
  • Helping organize the Lansing Day of .NET 8/1/2009
  • Launching a new Michigan High School Athletic Association Web Site    8/1/2009
  • Speaking at Dev Link 8/14/2009
  • Finishing a book (Testing ASP.NET Web Applications)
  • Appearing in a recent episode of .NET Rocks 9/8/2009 (show #479)
  • Appearing in a recent episode of Deep Fried Byte 9/10/2009 (Episode 36)

 

The major project has been the book, which will be released 11/02/2009. Completing the book has left me with an abundance of free time. I’m hoping to post more to the “So you think you’re a web developer” series, step outside my comfort zone and learn about Ruby, Drupal, and graphic design, and start contributing more to a few open source projects. I also plan on trying to stick a vacation in there at some point also.

image 
image
10 May

Where do I work

For the past nine months I have been working at Web Ascender. Web Ascender was started by Ryan Doom and Kevin Southworth roughly three years ago. I knew Ryan and Kevin before they started the business and when they stared Web Ascender I admired their courage. Over the past three years Web Ascender has grown into a company of six, I was hired on in July of 2008 and was a bit concerned because it was such as small company. During my first week at Web Ascender, any hesitations about if the company would succeed was negated by one thing I noticed, the relationships with the clients.

Every employee treats the clients very professionally, bending over backwards in some situations to make the clients happy, not just happy extremely happy. This is going to sound very cheesy, but many of the clients we have are friends, we laugh and joke with them, go to lunch together, and even do things outside of work with some of our clients (one of our clients plays on the Web Ascender Soccer Team).

A few weekends ago, all of the employees of Web Ascender participated in the Lansing Give Camp. A give camp is a weekend long event that matches a team of developers with a local charity that needs custom software developed. This was the first year we held this type of event in Lansing and it was a success. The event was held at the Impressions 5 science center in Lansing, where we had 24 hour access to create the applications for charities. With over fifty developers, we were able to create applications for thirteen different charities.  I was the co-organizer of the event, and anytime I was stressed out the Web Ascender staff would help out in any way they could. Multiple times during the event I would look out and see the Web Ascender staff working with the charities and other developers in the community and think “wow what a great company I work for”. Every single employee of Web Ascender was at the event with five of us leading teams.

Amelia
Amelia has a background in design and creates the most amazing designs for websites I have ever seen. During the first week of work, I remember a conversion between her and Matt about shades of black and when to use each one. They swear they don’t remember the conversion, but it happened. I remember this conversation because it was different than the conversions I normally heard in developer shops. I was now working at a place where design mattered.

Amelia lead a team at the give camp of three people and had a charity representative that stayed all weekend with her to help her with the application. Out of all the teams, I think this was the best match of personalities. Also I think the site she made was the best looking one there (no big surprise there though)

Mike
Mike is the “jack of all trades” from Dot Net Nuke, Joomla, PHP, Photoshop, <insert other random technology here>, Mike has worked with it to some level.  Mike and I shoot our crazy ideas back and forth and it even paid off one time. With an idea I had,  he went off and created a caller id application for the Android phone and had success with it (over 250,000 downloads)

Mike collected the requirements for two charities during give camp and his team created two applications. Mike’s leadership during this weekend was amazing, taking on two projects was a heavy task, but he stepped up to the plate and deliver two web sites that where great.

Ryan
Ryan is extremely active in the local community, so active I think he knows everyone in the Greater Lansing area. The way Web Ascender treats clients is mostly due to Ryan’s influence. His down to earth/ techy personality helps make clients feel at ease and willing to work with us. Ryan has a very good business sense, if he doesn’t think a project is a good fit for Web Ascender, he will tell the potential client that it’s not a good fit, and help find a company that is a good fit. I have seen Ryan do this on numerous occasions.

For the Lansing Give Camp, Ryan did so much. Using his wide range of contacts, he single handedly recruited at least five the charities that applied for applications to be created. He used his contacts to help get hosting of the applications donated from Liquid Web, and even collected requirements for a charity.  Throughout the weekend, I would see Ryan and Kevin at different teams, helping them out. To get an idea of Ryan’s business sense, they even brought the Web Ascender banner and put it up by their teams table.

Kevin
Kevin is one of the best developers that I know. He is extremely smart, humble and never hesitates to answer your questions, even if it’s the fifth time you have asked the same thing. I made the comment during the give camp weekend, I don’t know how I could work anyplace else without Kevin.  Web Ascender has done so much Dot Net Nuke work over the past few years, I would put good money on it that Kevin knows more about Dot Net Nuke then most of the developers on the core DNN team.

During this weekend Kevin worked on a team with Ryan and two other developers they did not know. Over the past few months Kevin has been asking the other developers at Web Ascender about their opinion of using the Microsoft Entity Framework with MVC, I have not had experience with EF so I was not much of a help. During that weekend, in true Kevin style, their team used EF and MVC with success. I haven’t talked with him about his experience with it yet and if he would recommend using it in the future.

Matt
This leaves us with Matt. Matt is the part time employee Web Ascender who is going to Michigan State to complete a teaching degree. Matt is the youngest of the group, at 22. Matt is always full of energy, willing to help whenever you need it. Matt reminds me of myself when I was that age in many ways. Matt, my wife Carla and I have developed a really good friendship, we meet at coffee shops outside of work and he studies, I work on my book, and Carla would work on give camp stuff.

During this weekend he worked on an application for a charity that I collected the requirements for.  He was able to complete the application early, so he even worked on a secrete project for Impressions 5.  Matt kept morale up as always and provided comic relief late into the night.

Where do I fit in at Web Ascender? I am the guy is trying to catch up with the talent of the rest of the group. I’m trying to absorb everything that each one of these talented people has to offer.  I help with marketing by always wearing a Web Ascender t-shirt, most people think I don’t own any other t-shirts.
I get to write code every day, manage projects, help with marketing and do a bunch of really cool things. I get to try new things out on projects, and have a ball where I work. Web Ascender is a company to watch over the next few years, expect great things.

 

Web Ascender Employees

(Left to right) Carla , Matt, Mike, Jeff, Ryan, Kevin, Amelia

Update: I originally wrote this post right after the Lansing Give Camp, but did not post it. During the time between the Lansing Give Camp and today, I have made another observation that makes Web Ascender a great place, that is the employees significant others.

Not only do I feel a sense of friendship with all of the Web Ascender employees, there is a friendship between everyone’s significant others. With activities such as watching John (Amelia’s boyfriend) play hockey (professional hockey in the IHL), everyone helping with the Web Ascender office move last week, playing on a soccer league together, and going to see Star Trek this weekend, everyone gets along very well together, and are friends.

02 Apr

Pittsburgh Code Camp Talk on Saturday

Testing for the Web

codecamplogo.png 
I will be speaking at the Pittsburgh Code Camp in Pittsburg PA, this Saturday.
 
Where: Department of Computer Science Sennott Square University of Pittsburgh Pittsburgh, PA 15260
When: Saturday April 2st. My session is at 1:00PM University of Pittsburgh Pittsburgh, PA 15260

21 Jan

Detroit MSDN Developer Conference

MSDN I will be speaking at the Detroit MSDN ConferenceThursday 1/22/2009, at the Detroit Renaissance center. I’m expecting this event to be pretty cool. All of the sessions are “repeats” from sessions at PDC. If you were not able to make it to PDC, now is your chance to get much of the same content for a discounted price.

When: Thursday 1/22/2009 3:30
Where: Detroit Renaissance Center
What: ASP.NET Road Map

   
17 Jan

Agile Estimating and Planning

AgileEstPlanning Title: Agile Estimating and Planning
Author: Mike Cohn
ISBN: 0131479415

I finally was able to finishing reading Agile Estimating and Planning today. Normally I’m able to read a book this size (368 pages) in a few days, but this one took me about a month to get through. As with all books, I read them thoroughly, dog earring pages and highlight interesting information for future use. The book was great and contained a ton of information about estimation I plan to use in the future. The estimating portion, took me the longest to get though, It wasn’t the authors writing style, the subject was just dry and not very fun to read about.The book goes into detail about how to create stories, how to estimate them using ideal days, and how to estimate using points. The book talks in detail about release plans, iteration plans and burn down charts . The book closes with a fictional case study, which walks the reader through the start of an Agile project, which is great for readers who are not familiar with the process.

I recommend this book for new members of an Agile team, or someone looking to learn about estimating on Agile projects. During an Open Space session at CodeMash last week, I heard the term “fraken-gile” (I think it was James Avery that said it) which hit home to me. I’ve seen many teams try to adapt Agile processes and turn it into a mess. Many of them abandon the process because of the mess they have created. Most of the times, teams start to implement these processes after reading a book such as Agile Estimating and Planning.  For someone looking to introduce Agile process into their team, I recommend consulting with an Agile Coach. If your company is not willing to foot the bill to bring in an Agile Coach, I recommend shadowing an Agile team, attending conferences such as Agile Coach Camp, and reading as many books as possiable. The Agile Manifesto states “People over Process”, so in most cases Agile teams are more than willing to have you observer there process.

16 Jan

SYTYAWD #4 Using Regular Expressions In Java Script

The next installment of the So You Think Your A Web Developer series will talk about Regular Expressions in Java Script. Many developers cringe at the site of Java Script, and even more run and hide with the mention of Regular Expressions. As a web developer, it is your responsibility to write sites that load fast, and often times string manipulation is the cause of bottlenecks on web sites. String manipulation is most efficient when Regular Expressions are used. If you are unfamiliar with Regular Expression syntax, check out SYTYAWD #3 about Regular Expression Syntax.

Regular Expressions in Java Script

One you have the Regular Expression syntax down working with it inside of Java Script is a breeze.

Inside of Java Script Regular Expression can be created in two ways. As literals or by calling the constructor of the RegExp object. In most cases I prefer calling the constructor, because I find it makes the code more readable.

As a literal:

var re = //bjeff/b/;

Calling the constructor:

var re = new RegExp(“/bjeff/b”);

Perform a search on a string, and then write the results to the page.

var printArray = function (x) {document.writeln(x + "<br>");}
var stringToSearch = "dood this is soo cool";
var re = new RegExp ("d(o+)d", "g");		// return any o’s that are between d and the full word
var matches = re.exec(stringToSearch);

matches.forEach(printArray);

Perform a string substitution, and then write the results to the page

       var stringToSearch ="dood this is soo cool, doooooood";
      	var re = new RegExp("/dood/g");
      	var processedString = stringToSearch.replace(/dood/g, "dude");	// replace the full word dood w/ dude

      	document.writeln(processedString);

The Java Script RegExp object has the following methods that are useful.

exec A RegExp method that executes a search for a match in a string. It returns an array of information.
test A RegExp method that tests for a match in a string. It returns true or false.
match A String method that executes a search for a match in a string. It returns an array of information or null on a mismatch.
search A String method that tests for a match in a string. It returns the index of the match, or -1 if the search fails.
replace A String method that executes a search for a match in a string, and replaces the matched substring with a replacement substring.
split A String method that uses a regular expression or a fixed string to break a string into an array of substrings.
Tip #1 Use Regular Expressions For Client Side Validation

Wire your onBlur or keyPress event to call a function that runs a Regular Expression on the content of the control. Below you will find a bunch Regular Expressions for common validation needs.

Date Format (m/d/y) ^([\d]|1[0,1,2])/([0-9]|[0,1,2][0-9]|3[0,1])/\d{4}$ 01/21/2008
Decimal Number ^\d*[0-9](\.\d*[0-9])?$ 178.685
Document Filenames ^[a-zA-Z0-9-_\.]+\.(pdf|txt|doc|csv)$ jeff.txt
E-mail Address ^([0-9a-zA-Z]+([_.-]?[0-9a-zA-Z]+)*@[0-9a-zA-Z]+[0-9,a-z,A-Z,.,-]*(.){1}[a-zA-Z]{2,4})+$ jeff@mcwherter.net
HTML Color Codes ^#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$ #8C9EAA
Image Filenames ^[a-zA-Z0-9-_\.]+\.(jpg|gif|png)$ robot.png
IP Address ^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$ 192.168.0.1
MySQL Date Format ^\d{4}-(0[0-9]|1[0,1,2])-([0,1,2][0-9]|3[0,1])$ 2008-01-04
Postal Code ^([A-Z][0-9]){3}$ V2B2S3
Time Format (HH:MM) ^([0-1][0-9]|[2][0-3])(:([0-5][0-9])){1,2}$ 12:56
URL ^(http[s]?://|ftp://)?(www\.)?[a-zA-Z0-9-\.]+\.(com|org|net|mil|edu|ca|co.uk|com.au|gov)$ http://www.mcwherter.net
Phone Number ^(([0-9]{1})*[- .(]*([0-9a-zA-Z]{3})*[- .)]*[0-9a-zA-Z]{3}[- .]*[0-9a-zA-Z]{4})+$ 1.517.455.7837
Tip # 2 Tools For Regular Expressions in Java Script
10 Jan

SYTYAWD #3 Are You Using Regular Expressions

The Basics of Regular Expressions

As web developers we tend to manipulate text often. This text is often HTML or XML, and in many cases the manipulation is done inefficiently. For text manipulation and searching you should be using Regular Expressions, but many developers do not. Do regular expressions look like cartoon characters swearing to you? Often times, I have ran into string manipulation code that contained loops, inside of loops, inside of loops which could have been avoided with a Regular Expression that would have been more performant and more readable? Wait, What a Regular Expression that is readable, yes once you get the basics of Regular Expressions down, they are more easier to interpret then stepping threw a bunch of control statements trying to figure out what they do.

re

Simple Searches
Find “jeff” jeff
Find “jeff” as a whole word \bjeff\b
Find “jeff” followed by “mcwherter” \bjeffb.*\bmcwherter\b
Special Characters
Match any character except newline .
Match any alphanumeric character \w
Match any whitespace character \s
Match any digit \d
Match the beginning or end of a word \b
Match the beginning of the string ^
Match the end of the string $
   
Find words that start with the letter a \ba\w*\b
Find repeated strings of digits \d+
Find six letter words \b\w{6}\b
Negation

Sometimes we need to search for a character that is not a member of an easily defined class of characters. The following table shows how this can be specified.

Match any character that is not alphanumeric \W
Match any character that is not whitespace \S
Match any character that is not a digit \D
Match a position that is not the beginning or end of a word \B
Match any character that is not x [^x]
Match any character that is not one of the characters aeiou [^aeiou]
Positive Lookaround
    Next we look at the lookahead or lookbehind assertions. They look for things that go before or after the current match without including them in the match. It is important to understand that these expressions match a position like “^” or “\b” and never match any text. For this reason, they are known as “zero-width assertions”. They are best illustrated by example:

    The beginning of words ending with “ing” \b\w+(?=ing\b)
    The end of words starting with “re” (?<=\bre)\w+\b
    Three digits at the end of a word, preceded by a digit (?<=\d)\d{3}\b
    Alphanumeric strings bounded by whitespace (?<=\s)\w+(?=\s)
Negative Lookaround

Earlier, I showed how to search for a character that is not a specific character or the member of a character class. What if we simply want to verify that a character is not present, but don’t want to match anything? Negative lookarounds will match a position and does not consume any text. As with positive lookaround, it can also be used to match the position of an arbitrarily complex subexpression, rather than just a single character.

Search for words with “q” not followed by “u” \b\w*q(?!u)\w*\b
Three digits not followed by another digit \d{3}(?!\d)
Strings of 7 alphanumeric not preceded by a letter or space (?<![a-z ])\w{7}
Text between HTML tags (?<=<(\w+)>).*(?=<\/\1>)
Greedy and Lazy

When a regular expression has a quantifier that can accept a range of repetitions (like “.*“), the normal behavior is to match as many characters as possible. If the first Regular Expression in the table below is used to search the string “aabab”, it will match the entire string “aabab”. This is called “greedy” matching. Sometimes, we prefer “lazy” matching in which a match using the minimum number of repetitions is found. If we apply the second regular expression in the table below to the same string “aabab” it will first match “aab” and then “ab”.

The longest string starting with a and ending with b a.*b
The shortest string starting with a and ending with b a.*?b
Repeat any number of times, but as few as possible *?
Repeat one or more times, but as few as possible +?
Repeat zero or one time, but as few as possible ??
Repeat at least n, but no more than m times, but as few as possible {n,m}?
Repeat at least n times, but as few as possible {n,}?
Tip #1 Try Expresso

Expresso is a free tool to aid in Regular Expression Development. Created for “.net Regular Expressions”, I have found it to be a very valiable tool. One of the best features is the Regex Analyzer. In the screen shot below, towards the right of the screen you will see the feature. This feature has helped me figure out exactly what Regular Expressions created by someone do, without pulling out my hair.

expresso

Tip #2 Start Slow

You are not going to master this skill over night, Regular Expression syntax takes time to learn, and even longer to master. Start using Regular Expressions when ever you can for simple matches or substitutions. As you become more familiar with the syntax you will find places to use Regular Expressions and make your code or efficient.

Reference: Expresso Help Documentation

03 Jan

Browser Market Share

The other day I read that the market share for Internet Explorer dropped below 70% for the first time in eight years.

browsers

Looking at my Google Analytics statistics, this is not the case for my domain McWherter.net. The image below shows the market share for the past few years. Since my blog caters to web developers, its no surprise that Firefox is higher.

Untitled

Another observance was the number of people still using Internet Explorer 6. Recently a co-worker of mine at Web Ascender, Matt Hall, blogged about the importance of updating your browser. Below are the Internet Explorer version statistics for McWherter.net, which are close to the numbers Matt mentions in his post. Ok come on who is still using Internet Explorer 5.5?

Untitled

02 Jan

SYTYAWD #2 Are you Scared of JavaScript

Continuing with the So You Think You’re A Web Developer series, as a web developer you should realize that trips back  to the server are an expensive resource, and you should try avoid these trips. In the past few years AJAX techniques have been gaining in popularity, but I still find web developers who avoid Java Script like the plague.

JavaScript has been around for years (roughly 13 years), and originally was named Live Script. Because of the addition of Java to Netscape back in the mid 90’s, someone thought it would be a good idea to rename Live Script to Java Script, even though the syntax only contained similarities(similarities as in any c based language). In my option, JavaScript is a great language, it combines OO principals and a few functional programming principals to make a language that is very robust. I think JavaScript is pretty simple to learn, its the intracies of the DOM (document object model) and the BOM (browser object model) that cause developers the most head aches.

Tip #1 What JavaScript is good for
  • Restricting data entered into a text box

Often times you will want to restrict what type of data is entered into an input box. The Java Script function below is called on the KeyPress event of a button, and will only return the character if its a valid number.

function OnlyAllowNumbers(field, e)
{
    // Special keyboard keys - Netscape 6 passes these to onkeypress
    // {{Home, End, Delete, Arrow Keys}, {Backspace}, {Enter}}
    var reKeyboardChars = /[x00x08x0D0]/;

    // Numeric characters
    var reValidChars = /d/;

    // Grab event key code and character (method depends on browser)
    var keycode = window.Event ? e.which : e.keyCode;
    var strChar = String.fromCharCode (keycode);

    // Block non-numeric characters and non-special keys
    if (!reValidChars.test (strChar) && !reKeyboardChars.test (strChar))
    {
        // Invalid character, reject key press
        return false;
    }  

    // Valid character or special key, allow key press
    return true;
}
  • Adding days to a date

Recently a client asked for a feature to extend a date in a text box by 4 weeks. Something this simple does not make sense to make a trip back up to server, so I wired a button to call a function that contained code that looked similar to below.

	var startDate = new Date('12/30/2008');     var daysToAdd = 28;                            // 4 weeks
	var newDate =  new Date(startDate.getTime() + daysToAdd*24*60*60*1000);        // get the milliseconds for days to add, then add

	// add 1 to the month because js months start at 0
	var formattedDate = newDate.getMonth() + 1 + "/" + newDate.getDate() +"/" +   newDate.getFullYear();

There are far to many business cases to list, but as a rule of thumb, think before you wire a control that goes back to the server, can this functionality be done on the client?

Tip #2 Tools for debugging

While throwing an alert box in every few lines, may get the job done but its not the most efficient way to debug issues.

  • Firebug

Firebug is a plug in for Firefox that contains a great Java Script debugger.

FireBug

Firebug adds a global variable named “console” to all web pages loaded in Firefox. This object contains many methods that allow you to write to the Firebug console to expose information that is flowing through your scripts.

var daysToAdd = 28;                            // 4 weeks
console.log("daysToAdd=%d ",daysToAdd);

Console

  • Visual Studio

Visual Studio 2008 ships with a JavaScript debugger also. I have had issues in the past setting break points, and actually having them break correctly. When this happens, I just use the debugger Java Script statement. When testing with Internet Explorer, Visual Studio will present the Debugger box, if using Firefox with Firebug installed this will throw you right into the Firebug debugger.

Visual Studio

  • Firefox

Many times I just need to test if a small script works. Instead of creating an html file to test my logic, I will just copy my script into the Firefox address bar

javascript: var foo=’my javascript test’; alert(foo);

FireFox

Tip #3 Testing Frameworks

Most developers don’t create automated test’s for server side code, let alone tests for Java Script. Below are a few testing frameworks to be aware of. Keep an eye out for a SYTYAWD post about qUnit.

Tip #4 Java Script Frameworks

There is common logic that we as Web Developers do often, show/hide content in a div tag, perform a calculation on an object and dump the result into a text box. There are a bunch of tools out there that wrap this common logic into an easy to use API. Often times these tools cause religious wars between developers, on which one is the best to use.

I suggest you try out a few tools and get comfortable with one. I personally use jQuery as my tool of choice. Also Microsoft has recently made the announcement that they will ship jQuery in Visual Studio 2010.

01 Jan

2008 Q3 and Q4 in Review

In order to see where you are going often times its necessary to see where you have been. I try to do this every six months, I think about events, new technologies and accomplishments. Below is a list of a few of these that I have been thinking back too:

Mid-Michigan Tweet Up’s

July marked the first of many of Tweet-Ups that occurred in the past six months in the Lansing area. The Mid-Michigan Tweet Up was started by Jennifer Midland, Betsy Weber and Casey Anderson Its a great way to get out to the local pub, enjoy a few drinks and make some new friends, outside of the tech community.

Codestock

Held down in Tennessee and organized by Michael Neel, Wally McClure and Alan Stevens. What I remember most about this event, was the people. A few people traveled a great distance to make this event, James Avery, Rachel Appel, Scott C Reynolds a few names that helped make this event enjoyable.

Dev Link

A few weeks after Code Stock, the car was packed up again for another trip down to Tennessee. This year Alan Stevens organized the Open Spaces and they where great. It was the first .net event in the Midwest that I truly feel nailed what an open space conference was.

Job Move To Web Ascender

In July, I joined Web Ascender, a web development firm started by friends of mine Ryan Doom and Kevin Southworth. It was a great move. Kevin and Ryan foster a great learning environment, where everyone is eager to learn about new things.

Web Ascender Becomes a Microsoft Certified Partner

Soon after staring at Web Ascender, I was able to help the company become a Microsoft Certified Partner, this was my second time going through the steps of this process and with all the certifications that the guys at Web Ascender already had, made it a breeze.

MVP Award

On an early October day, I received an email entitled “Congratulations MVP 2008”, for a Most Valuable Professional award in ASP.net from Microsoft. 

Ann Arbor Day of .net

A few weeks before Halloween Jason Follas, John Hopkins, Scott Z, Chris Woodruff and few others, put on a great conference at the Washtenaw Community College. I believe this was the 4th year, and those guys really know how to run an event, its like clock work every year.

PDC

Its always great when you are able to attend conferences on this scale, plus October is a great a great month to have an event.  It was great to see so many friends, make new friends and learn as much as I did. The memory that sticks out most is at the attendee party, Dave Bost suggesting that we go on the “Movie Tour Ride” because Jennifer Marsman didn’t like the haunted attractions, turned out to be the scariest haunted attraction I had ever been to, it was great. . 

Great Lakes Software Excellence Conference

This event is in Grand Rapids Michigan, and my first year attending/speaking. The conference attracts project managers, QA and a few developers. There were very few people that I had already met, so it was a great opportunity to meet a new group of friends.

Web Ascender Becomes a Microsoft Certified Gold Partner

After only being a certified partner for about 5 months, Web Ascender was able to achieve Microsoft Gold Partner Status. With only six employees this makes Web Ascender one of the smallest Gold Partners in the country.

© 2010 Jeff McWherter | Entries (RSS) and Comments (RSS)

GPS Reviews and news from GPS Gazettewordpress logo