Google Maps vs Bing Maps

By alschneider at February 17, 2010 08:17
Filed Under: General, Web / Software Development

Google-bingFor the last couple of years I’ve been writing web applications and desktop software using mapping technologies. A couple of years ago when these projects started we had to make a choice between Google Maps and Microsoft’s Virtual Earth (now called Bing Maps). At the time, Google had a much more restrictive licensing model than Microsoft. The websites and software we were developing required a subscription to plot and view the data, but free users could use the map in any way intended without requiring the user to log in or enter an email address. Google also had restrictive limits on the number of hits that your account could absorb. We went with Microsoft’s Virtual Earth and it has worked very well for us over the years and Microsoft was very forthcoming and open about their licensing and how we intended to use the technology.

 

Skip ahead a couple of years and I have started to look at Google and Bing again. This time it is for a site that will feature new home information and mapping. Like I said, Bing has worked well for us over the last couple years providing aerial maps for 3 web sites and 1 desktop application, so we have no real reason to switch other than to ensure they are able to provide the services we need.

 

I started by checking Google Map’s licensing strategy, which was the deal killer for us a couple of years ago. It seems they have relaxed a lot of the per day restrictions (or eliminated them altogether). They have the same daily limit on geocoding addresses (providing the lat / long for a given street address), but the imaging is not restricted by hits. This means that you can provide the maps for your website visitors or for your applications without worry.

 

But wait, there’s more. Both Microsoft and Google have restrictions against charging for using the maps. In other words, you can’t use Google or Bing on a website that charges simply for using the map. You can provide basic functionality of the maps for use on your site and charge for overlays, plots, or other data that you provide. As an example, I designed a site that allows users to view Bing Maps and use all the features of it as provided by Bing. However, the customer provides data for overlays, boundaries, and plots that is proprietary to them. For that data to be displayed on the map, there is a charge. After a few calls to Microsoft, the client was able to get a clear and concise answer regarding the rules and regulations regarding Bing Maps, and the custom overlay charge was fine by them… Again, as long as users could freely use the Bing Maps general functionality as provided by Microsoft without paying for anything.

 

The one negative Bing has going for it is the abysmal default pins. Granted, I never use them and create custom PNG’s for the maps, but Google makes such a nice, simple pin that it would make my time spent developing the site a little less as well as providing an already well recognized image on the screen. People see it and immediately think “Oh, there’s one of what I’m looking for” instead of “What’s that gelatinous blob trying to say?”

 

Both offer 3d views, or Bird’s Eye View as Bing called it. They are both reasonably accurate with the plotting of geocoded points, but examples of mistakes are documented and lamented all over the net on both sides.

 

My Ratings:

  Google Maps Bing Maps
Data orngestrorngestrorngestr orngestrorngestrorngestrorngestr
Developer Resources orngestrorngestrorngestrorngestr orngestrorngestrorngestrorngestr
Documentation orngestrorngestrorngestrorngestr orngestrorngestrorngestr
Browser Support orngestrorngestrorngestr orngestrorngestr
Accuracy orngestrorngestr orngestrorngestrorngestr

 

Right now Google gets a little more exposure since Orbitz, Redfin and Trulia are all using the current version of the API on their websites. But Bing has made some serious inroads in the last year by providing more up to data data and a more relaxed licensing strategy.

What’s new in Visual Studio 2010

By alschneider at January 27, 2010 04:36
Filed Under: Web / Software Development

Just one year ago I upgraded Visual Studio 2005 to Visual Studio 2008. There were a number of enhancements that are ‘behind the scenes’ and some notable improvements to intellisense and AJAX, which motivated me to finally upgrade. Well, that and support for .NET 3.5. But it seems that just as soon as I upgraded I started receiving information about Visual Studio 2010.

 

I took some time to research the product (still in Beta) to see if the list of changes was significant enough to warrant me spending another couple hundred bucks on yet another upgrade. Here’s some of the things I found.

 

Code Editor

The new Code Editor makes code easier to read. You can zoom in on text by pressing CTRL and scrolling with the mouse wheel. Also, when you click a symbol in Visual C# or Visual Basic, all instances of that symbol are automatically highlighted.

 

Better tools for Web Development

To me, this is reason enough to upgrade. The publishing and FTP portions of Visual Studio past were a far cry from what Dreamweaver offers. Now with enhanced publishing and rebuilding web.config on the fly, it looks like they have finally caught up.

 

  • Creating Web packages

    The Web Deployment Tool, also known as MSDeploy, enables you to package your Web application for deployment to an Internet Information Services (IIS) Web server. A Web package is a .zip file or a folder structure that includes everything a Web server needs to host your application. It contains Web content, IIS settings, database scripts, components, registry settings, and certificates. The Web Deployment Tool has been integrated into Visual Studio and enables you to create Web packages with one click.

  • One-Click Publish

    You can now publish to a server by using the Web Deployment Tool, FTP, folder copying, or FrontPage Server Extensions in one click. Visual Studio stores all the setting information, such as publish method, server information, and user credentials.

  • Web Configuration Transformations

    You can now configure your project to transform the web.config file during deployment. When you deploy the project, the settings in web.config automatically match the settings on your debug, staging, and production servers.

  •  

    It also includes something completely new:

    Visual F#

    Visual Studio 2010 includes F#, a new .NET Framework language that supports functional programming and traditional object-oriented and imperative (procedural) programming. F# combines the succinct, expressive, and compositional style of functional programming with the runtime, libraries, interoperability, and object model of .NET. In other words, you get the best of both paradigms.

     

    Right now I don’t have the time or patience to try another development product so an actual ‘hands on’ review is not coming anytime soon. For now, I’ll have to rely on what I’m reading in order to form an opinion. I think I’ll also wait for the product to go through it’s first service pack release before upgrading. Maybe by then they’ll have the kinks worked out.

    Validating email address format on your ASP webpage

    By alschneider at January 24, 2010 13:42
    Filed Under: Web / Software Development, Marketing

    If you’ve been a web developer for more than 5 minutes you know that you can’t create any type of website without getting a user to enter their email address. Sometimes this is done for marketing purposes or to add them to an email list for subscriptions, but whatever the reason the need is there on almost any website to prompt, validate, and record a visitors email address.

     

    An easy way to do this is with a JavaScript chunk of code that will look at the value the user entered and ensure it adheres to certain rules regarding how a standard email address is formatted. This will not validate that the email is a working account at the domain specified (that’s another post), but it will at least catch user input errors they might not be aware of when entering the address in the field.

     

    Test the code out on our email Format Test Page!

     

    Download the ASP and Javascript code used on the test page here: emailFormatExample.zip (2.48 kb)

     

    This file, emailTools.js, contains several functions that take a passed parameter and check the syntax to ensure it is formatted properly.

       1: function checkValidation(emailAddr) {
       2:     var message = 'OK';
       3:     if (stringEmpty(emailAddr)) {
       4:         message = "Error! There is no input value entered.";
       5:     } else if (noAtSign( emailAddr )) {
       6:         message = "Error! The address \"" + emailAddr + "\" does not contain an '@' character.";
       7:     } else if (nothingBeforeAt(emailAddr)) {
       8:         message = "Error! The address \"" + emailAddre;
       9:         message += "\" must contain at least one character before the '@' character";
      10:     } else if (noLeftBracket(emailAddr)) {
      11:         message = "Error! The address \"" + emailAddr;
      12:         message += "\" contains a right square bracket ']',\nbut no corresponding left square bracket '['.";
      13:     } else if (noRightBracket(emailAddr)) {
      14:         message = "Error! The address \"" + emailAddr;
      15:         message += "\" contains a left square bracket '[',\nbut no corresponding right square bracket ']'.";
      16:     } else if (noValidPeriod(emailAddr)) {
      17:         message = "Error! The address \"" + emailAddr + "\" must contain a period ('.') character.";
      18:     } else if (noValidSuffix(emailAddr)) {
      19:         message = "Error! The address \"" + emailAddr;
      20:         message += "\" must contain a two, three or four character suffix.";
      21:     }
      22:     return (message);
      23: }
      24:  
      25: function checkEmailValid (formField) {
      26:     if( checkValidation(formField) == 'OK')
      27:         return true;
      28:     return false;
      29: }
      30:  
      31: function stringEmpty (formField) {
      32:     // CHECK THAT THE STRING IS NOT EMPTY
      33:     if ( formField.length < 1 ) {
      34:         return ( true );
      35:     } else {
      36:         return ( false );
      37:     }
      38: }
      39:  
      40: function noAtSign (formField) {
      41:     // CHECK THAT THERE IS AN '@' CHARACTER IN THE STRING
      42:     if (formField.indexOf ('@', 0) == -1) {
      43:         return ( true )
      44:     } else {
      45:         return ( false );
      46:     }
      47: }
      48:  
      49: function nothingBeforeAt (formField) {
      50:     // CHECK THERE IS AT LEAST ONE CHARACTER BEFORE THE '@' CHARACTER
      51:     if ( formField.indexOf ( '@', 0 ) < 1 ) {
      52:         return ( true )
      53:     } else {
      54:         return ( false );
      55:     }
      56: }
      57:  
      58: function noLeftBracket (formField) {
      59:     // IF EMAIL ADDRESS IN FORM 'user@[255,255,255,0]', THEN CHECK FOR LEFT BRACKET
      60:     if ( formField.indexOf ( '[', 0 ) == -1 && formField.charAt (formField.length - 1) == ']') {
      61:         return ( true )
      62:     } else {
      63:         return ( false );
      64:     }
      65: }
      66:  
      67: function noRightBracket (formField) {
      68:     // IF EMAIL ADDRESS IN FORM 'user@[255,255,255,0]', THEN CHECK FOR RIGHT BRACKET
      69:     if (formField.indexOf ( '[', 0 ) > -1 && formField.charAt (formField.length - 1) != ']') {
      70:         return ( true );
      71:     } else {
      72:         return ( false );
      73:     }
      74: }
      75:  
      76: function noValidPeriod (formField) {
      77:     // IF EMAIL ADDRESS IN FORM 'user@[255,255,255,0]', THEN WE ARE NOT INTERESTED
      78:     if (formField.indexOf ( '@', 0 ) > 1 && formField.charAt (formField.length - 1 ) == ']')
      79:         return ( false );
      80:  
      81:     // CHECK THAT THERE IS AT LEAST ONE PERIOD IN THE STRING
      82:     if (formField.indexOf ( '.', 0 ) == -1)
      83:         return ( true );
      84:  
      85:     return ( false );
      86: }
      87:  
      88: function noValidSuffix(formField) {
      89:     // IF EMAIL ADDRESS IN FORM 'user@[255,255,255,0]', THEN WE ARE NOT INTERESTED
      90:     if (formField.indexOf('@', 0) > 1 && formField.charAt(formField.length - 1) == ']') {
      91:         return ( false );
      92:     }
      93:  
      94:     // CHECK THAT THERE IS A TWO OR THREE CHARACTER SUFFIX AFTER THE LAST PERIOD
      95:     var len = formField.length;
      96:     var pos = formField.lastIndexOf ( '.', len - 1 ) + 1;
      97:     if ( ( len - pos ) < 2 || ( len - pos ) > 4 ) {
      98:         return ( true );
      99:     } else {
     100:         return ( false );
     101:     }
     102: }

    Create a file called emailTools.js ( or download the sample .ZIP file above ) and place it in your sites root directory.

     

    In your .ASPX file, include a reference to the script file by adding the following line of code, preferably toward the bottom with other parts of your scripts.

       1: <script type="text/javascript" src="emailTools.js"></script>

    Next, add the textbox control to your page that will hold the email address the user enters

       1: <asp:TextBox ID="emailaddr" runat="server" MaxLength="50" Style="vertical-align: middle"
       2:     TabIndex="1" Width="300px" CausesValidation="True"></asp:TextBox>

    After the textbox control code that will contain the email address the visitor enters, you need to add a custom validator. Place it on the form so that if the user enters an address that is invalid, the message shows up on top of or below the email address textbox. This way the user can easily see the text when it pops up and make the necessary corrections. The first validator simply reminds the user that they need to enter an email address in order to continue. The second custom validator is what checks to see if the address is formatted correctly.

       1: <asp:RequiredFieldValidator ID="rfvFullname" runat="server" ControlToValidate="emailaddr"
       2:     ErrorMessage="Please enter your email address" Font-Bold="True" Font-Size="12pt" />
       3: <asp:CustomValidator ID="cvEmail" runat="server" Font-Bold="True" Font-Size="12pt"
       4:     ClientValidationFunction="checkEmailAddr" ControlToValidate="emailaddr" ErrorMessage="Email address is not formatted properly. Please correct." />

    Change the ControlToValidate value to the name of your email address textbox control on the form.

     

    Place a button on your form for the user to press when they are done.

       1: <asp:Button ID="Button1" runat="server" Text="Click to continue" OnClick="OnAddEmail" />

    Notice how the button has an OnClick variable that tells it to run our C# code block called OnAddEmail() and not our validation script? That's because the control will never fire the OnClick event until the validation specified in the CustomValidator and RequiredFieldValidator occurs and everything checks out. In our code behind, we have two functions. One to take care of the PageLoad and set our previous page variable, the second is the actual OnAddEmail function that records the users email and returns them to the page that sent them here. I have placed the code within the ASPX file and not in a separate file, but you can do it either way.

       1: <script runat="server">
       2:     public static string sPrevPage = "";
       3:     protected void Page_Load(object sender, EventArgs e)
       4:     {
       5:         // Save the originating page so we can send the user back whe done
       6:         if (!IsPostBack)
       7:         {
       8:             if (Request.ServerVariables["HTTP_referer"] != null)
       9:                 sPrevPage = Request.ServerVariables["HTTP_referer"].ToString();
      10:             else
      11:                 sPrevPage = "~/Default.aspx";
      12:         }
      13:     }
      14:  
      15:     protected void OnAddEmail(object sender, EventArgs e)
      16:     {
      17:         // Use this function to write the email address to a file
      18:         try
      19:         {
      20:             string sFilePath = Request.MapPath("~/emails/") + "visitor.log";
      21:             using (System.IO.StreamWriter sw = new System.IO.StreamWriter(sFilePath, true))
      22:             {
      23:                 sw.WriteLine(emailaddr.Text);
      24:             }
      25:         }
      26:         catch { }
      27:         Response.Redirect(sPrevPage);
      28:     }
      29: </script>

    Now comes the fun part… Insert the code at the bottom of the ASPX file to call the function(s) in our emailtools.js file that will tell us whether or not the email address is at least formatted OK.

       1: <script language="javascript" type="text/javascript">
       2:     var alreadyChecked = false;
       3:     function checkEmailAddr(sender, args) {
       4:         var retVal = checkEmailValid(document.getElementById('<%=emailaddr.ClientID%>').value);
       5:         if (retVal == true && alreadyChecked == false) {
       6:             alert("Your address appears valid. You will now be taken back to the previous page...");
       7:             alreadyChecked = true;
       8:         }
       9:         args.IsValid = retVal;
      10:     }
      11: </script>

    Now, when the user presses Enter or the submit button, the validation scripts fire. If they fail, they warn the user and lets them fix the errors on the form. Once a valid email is supplied, the name is recorded in the Visitors.log file, and they are returned to the previous screen or you can change the code to take them to a “Thank you” type page.

     

    You may be wondering about the variable alreadyChecked. It is needed because the checkEmailAddr function actually fires twice when the user enters a valid email address… Once for the validation and again for the form submission. This variable ensures our textbox message only gets displayed once.

     

    I hope this example helps and / or makes sense enough to help you with validating some of the user input.

    Singleton Class – C#’s MVP

    By alschneider at January 20, 2010 16:15
    Filed Under: Web / Software Development

    What is a singleton class? Well basically it's a class that can only be instantiated ONE TIME within the confines of an applications space. Why is this useful? Well, it's a great place for creating and managing single point code logging functions or holding global data that requires a bit to retrieve.

     

    For example, I wrote a program for a user that read data from an Access database. When the program started, I instantiate a singleton and run a query to get the version of the data (within a table / row). This value is stored in the singleton upon startup. Now, when the dozens of custom reports are run, this information is printed on the header by simply referencing the singleton variable as opposed to running this query every time that value is needed.

    In the example below, I am going to create a singleton class that contains one of my most used functions, WriteToLog.

     

    First, lets create a singleton class in Visual Studio by right clicking the project name in the "Solution Explorer" pane and selecting "Add New Item." Select "Class" and type in a name for your new singleton class (example: LocalEnv). Enter this in the source code window:

       1: using System; 
       2: public class LocalEnv 
       3: { 
       4:     private static LocalEnv instance = null;
       5:     private LocalEnv() {}
       6:     public static LocalEnv Instance 
       7:     {
       8:         get
       9:         {
      10:             if (instance == null)
      11:             {
      12:                 instance = new LocalEnv();
      13:             }
      14:             return instance;
      15:         } 
      16:     } 
      17: }

    Notice how the constructor is private? This means that the class can only be instantiated internally by using the "new" command and referencing it through the instance variable. If an instance of this class already exists in memory, it will simply return the already instantiated instance. If not, it creates a new instance of the class. Be sure to note the differences in the Instance variable and the instance variable (upper and lowercase 'i' versions). They are two seperate things.

     

    Next, we'll need to create a function within our LocalEnv class that will write a message to a log file. In this example, I will assume that this is a website and that we want to write all of our logs to a subdirectory under the App_Data directory (or wherever you want) and that the log filename will be the date the event occurred.

       1: public void WriteToLog(string sBaseDir, string sText)
       2: {
       3:     string sLogFilename = sBaseDir + "/MyWebLogs/" + 
       4:         string.Format("{0:d}{1:d2}{2:d2}.log", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
       5:     StreamWriter myStream = null;
       6:     sText = DateTime.Now.ToShortDateString() + " "+DateTime.Now.ToShortTimeString() + ": " + sText;
       7:     using (myStream = new StreamWriter(sLogFilename, true))
       8:     {
       9:         myStream.WriteLine(sText);
      10:     }
      11: }

    Now, in our .aspx file, we can write any message to the generic text log as follows:

       1: LocalEnv.Instance().WriteToLog(Request.MapPath("~/App_Data"), "A new user was added");

    Whenever we call the function, it will write a single line to the log file in the directory we specify. It will write all log entries into a single file for the day. The result in our log file file (example: c:\inetpub\wwwroot\App_Data\MyWebLogs\20100114.log) will look like:

    01/14/2010 17:54:14: A new user was added

    Windows 7 Upgrade Horrors

    By alschneider at January 20, 2010 10:25
    Filed Under: Computers, Web / Software Development

    I have been using Windows 7 (both BETA and RC version) for several months now on a test machine. I purchased a full copy of Windows 7 over the Christmas break so that I could upgrade my development desktop from Vista and keep it current. Let’s just say the upgrade was less than spectacular.

     

    I had a 32 bit version of Vista but noticed I had 2 DVD’s in my Windows 7 packet… One was 32 bit the other was 64 bit. I thought since I recently upgraded to a dual core Intel I would take advantage of the 64 bit now available to me. Without warning or hesitation, the installation started in a flash but then soon bogged down into a quagmire. After waiting over 6 hours for files to copy, the screen showed it was only 12% done. Something was clearly wrong.

     

    I aborted the upgrade and attempted to boot into the remaining scraps of Vista that may still be lurking. No luck. The install had wiped it too clean on the Vista side and only installed 20% on the Windows 7 side.

     

    After much investigation I found that you cannot upgrade from 32 bit Vista to 64 bit Windows 7. Thanks for telling me! Some kind of warning or denial screen would have been nice. Luckily I backed up everything and had to proceed with a complete re-installation of Windows 7… Which isn’t a bad thing. It’s always best to start with a clean slate, but I have SO much software, dev tools, add-ons, and utilities that it took a day and a half to install them all.

     

    So be warned that even though your fresh new packet of Windows 7 comes with both versions, you can only upgrade to a version you currently have installed. I wonder how Windows 8 with 128 bit support will handle updates?

    IIS7 And URL Rewrite Reveals The Tricks Of Heavy Hitter Blog Sites

    By alschneider at January 18, 2010 10:13
    Filed Under: Marketing, Web / Software Development

    Have you ever wondered how blog and other advertising sites create an unending stream of URL's that contain the title? For example, our blog uses a trick called URL Rewrite, an add-on for IIS7. With this tool, you use regular expressions to create a filter that parses the info for you and redirects it to another page that can use that data to fill in the blanks.

     

    For example: You can have a bot / SEO friendly URL like

    http://www.esourcedevelopment.com/BlogPosts/3548/Windows_7_upgrade_horrors

    which will actually be rewritten as:

    http://www.esourcedevelopment.com/ShowRealPost.aspx?id=3548?title=Windows_7_upgrade_horrors

    The URL that IE and Firefox show in the browser address space is the same as the first one requested, but the page actually displayed is the second one.

     

    Setting up IIS7 to handle URL Rewrite

    • Go to IIS Manager
    • Select “Default Web Site”
    • In the Feature View click “URL Rewrite“
    • In the “Actions” pane on right hand side click on “Add rules…”
    • In the "Add Rules" dialog, select the "Blank Rule" and click "Ok"

    Now you must define the actual rewrite rule. In the URL rewrite module, a rewrite rule is defined by specifying four required pieces of information:

    • Name of the rule;
    • Pattern to use for matching the URL string;
    • Optional set of conditions;
    • Action to perform if a pattern is matched and all conditions checks succeed.

    Naming a rule
    In the “Name” text box enter a name that will uniquely identify the rule, for example: ”Rewrite to article.aspx”.

    Defining a pattern
    In the “Pattern” text box enter the following string:

    ^blogposts/([0-9]+)/([_0-9a-z-]+)

    This string is a regular expression that specifies that the pattern will match any URL string that meets the following conditions:

    • Starts with the sequence of characters “blogposts/”.
    • Contains one or more numeric characters after the first “/”.
    • Contains one or more alphanumeric or “_” or “-” characters after the second “/”.

    Notice that certain parts of the regular expression are within parentheses. These parentheses create capture groups, which can be later referenced in the rule by using back-references.

    Defining an action
    Since the rule that we are creating is supposed to rewrite the URL, choose the “Rewrite” action type that is listed in the “Action” group box. In the “Rewrite URL:” text box, enter the following string:

    ShowRealPost.aspx?id={R:1}&title={R:2}

     

    This string specifies the new value to which the input URL should be rewritten. Notice that for the values of the query string parameters we used {R:1} and {R:2}, which are back-references to the capture groups that were defined in the rule pattern by using parentheses.

     

    Now your actual page can decipher the QueryString values for ID and / or for title to search your database and display the article in question.

     

    The entire tutorial on this setting can be found at http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-the-url-rewrite-module/

     

    This site features a lot of 'how-to' information on IIS and is invaluable for any web developer.


    Looking for more stories? Check out
    Shoutwire Shoutwire - Internet News for the Masses

    Help us out by visiting our sponsors!
    Thank you

    Rifftrax


    Recent Posts

    Recent Comments

    Comment RSS

    What We're Playing




    Who's Watchin' Me?