Amazon Web Services

by Peter Tyrrell Wednesday, November 08, 2006 11:00 AM


So I went to the Victoria .NET Developers Association meeting last night, and their guest speaker was a dev evangelist from Amazon Web Services. That is not to say, but rather the computing services division that is the public face of the vast infrastructure that has been built over the years to support and its satellite businesses. Web Services now has a life of its own, and is attempting to move the goalposts closer together in the web computing game.

S3 - Simple Storage Service

S3, or Simple Storage Service, houses data safely and securely across their distributed network. That doesn't sound very exciting until you start to realize how incredibly cheap, reliable and powerful it is compared to DIY data storage. As to cheap, 15 cents per GB per month, and 20 cents per GB to move data in or out. As to reliable, their network is so large the entire continent of North America would have to sink beneath the waves before your data was lost. Due to the fact that you do not rent space on any particular machine, you are not tied to a given machine's success or failure. Most larger organizations have a data center facility with backup, redundancy, and failover machines, but it's very expensive! As to powerful, bandwidth is very large, and there is literally no practical limit on the amount of data you can store. Terabyte? Sure. The speaker gave some examples of web businesses that had saturated either their SAN storage facility or their bandwidth, and removed the bottlenecks at a stroke by relying on S3 instead.

EC2 - Elastic Computing Cloud

EC2, or Elastic Computing Cloud, is in beta, but will be something to watch. It's a web service that runs virtual server instances. As many as you want, for cheap: 10 cents per hour per instance. Again, all the benefits of S3 apply. At this point only Linux based virtual machines are supported, so I hope it opens up to Windows instances in the future. The speaker had a new webserver instance going in 10 minutes. Woah!

These services are really going to be hard to ignore, for both large and small web-based businesses. It's just so much power and convenience for so cheap.


Query String tips with C# 2.0

by Peter Tyrrell Thursday, November 02, 2006 3:11 PM

I switched from VB.NET to C# a few months ago because of the JetBrains Resharper Visual Studio add-in.

C# has been a joy for the most part. I am occasionally stumped because it is stricter than VB.NET, but working through such challenges makes me understand the C# language and .NET framework better.

Ted and I, and I guess other developers, work with query strings a LOT. I discovered a couple of new methods in .NET 2.0 that are helping me out with the HttpRequest.QueryString collection.

String.IsNullOrEmpty(string): bool

A typical scenario is to init a string, pass it a query string value, and then check to see that the string has a value. I'm always trying to remember whether a non-existent query string key returns null, or an empty string. Or if the key is there but has no value, is that null or an empty string? With String.IsNullOrEmpty, I don't have to think:

string CheckId = Request.QueryString["ID"];

if (string.IsNullOrEmpty(CheckId) == false)


    //do stuff


Int32.TryParse(string, out Int32): bool

In the code example above, I want an ID value, which I need to be a integer. I want to test that it is a number before proceeding, and I also want to actually convert it to an integer. In the past I would use VB.NET's IsNumeric, and then Int32.Parse(string) in a try/catch block. What a pain. Int32.TryParse simultaneously tests the input string for integericity, returning a boolean, and outputs the integer result (zero if the string can't be parsed):

int i;

if (int.TryParse(CheckId, out i))


    //do stuff with i



Field names in XML: CS vs. DB/WebPublisher

by Peter Tyrrell Thursday, November 02, 2006 2:39 PM

Tip: avoid spaces in field names.

When a field is referenced in WebPublisher XML, any space in the field name is replaced. In DB/Text WebPublisher XML, the space is replaced by a hyphen: "-". In CS WebPublisher XML, the space is replaced by an underscore: "_".

Thus, when converting an existing DB/Text Webpublisher XML-based service to CS, if the service expects field names with hyphens, things tend to go "boom crumple bang squish".

Reminder: avoid spaces in field names.


Desktop scripting: link on ID, but search by name

by Peter Tyrrell Wednesday, November 01, 2006 9:50 PM

I've been using this technique a lot lately, so why not share it?

When linking a textbase to another, it's best to link on a unique ID: something that won't change over time. The plus side is that the link from primary to secondary textbase will not be easily broken. This is just good sense and a long-time database design golden rule. (What if you linked to a Name field and someone changed their name?)

The down side is that an ID is not people-friendly. When the time comes to link out to the secondary textbase, a number like "123" means a lot less to human eyeballs than "Smith, John". Inmagic gives you the ability to browse the available items to link to, but a list of numbers is next to useless. How do you know that "123" is the Record ID for "Smith, John"? You don't.

To retain the strength of the link-on-ID and the user-friendliness of browse-by-name, we call upon JAVASCRIPT. Hurrah. Here's what I do in edit forms. I'll use an example based on a library sign-out page: there is a Catalog, a Borrowers textbase and a Loans textbase. The Loans textbase is primary, but links to Catalog and Borrowers textbases as secondary textbases. I want to create a loan record that links to the Borrower via Borrower ID, but I don't want the user to have to know the Borrower's ID. I want them to search by borrower name to make the link.

Fig. 1. Link is made on Borrower ID, but user can search by Borrower name or barcode and the script will make the link.

In this case I give the user the opportunity to search either by name or barcode. If the script finds a single match, it automatically populates the Borrower ID field. If it finds multiple matches, it displays the top 5 so the user can either re-search with a more specific search or copy-and-paste the ID themselves.

Fig. 2. User has searched for "doe" and found 2 matches.

Here is the script which performs the search on borrower name. I have defined an object of type "Borrrower" to encapsulate all the information I need about a borrower and this function returns an array of these Borrower objects.


function GetBorrowersByName(name) //returns array of Borrower


    var names = name.replace("\r", " ").split(" ");

    var rs;

    var fldBorrowerID, fldBarcode, fldLastName, fldFirstName, fldMiddleName, fldPatronType, fldPatronStatus;

    var strNames = names.join(" / ");

    var output = [];


    rs = Application.newRecordset(userTextbase, Application.activeTextbase.path, userPassword);

    if (rs != null)


        rs.Open("Find (LastName ct " + strNames + ") or (FirstName ct " + strNames + ") or (MiddleName ct " + strNames + ")");

        DebugLog("Find (LastName ct " + strNames + ") or (FirstName ct " + strNames + ") or (MiddleName ct " + strNames + ")");

        if (rs.Errors.Count > 0)


            DebugLog("GetBorrowersByName: " + rs.Errors(0).Description);


        else if (rs.RecordCount > 0)



            while (!rs.EOF)


                fldBorrowerID = rs.Fields("RecordID");

                fldBarcode = rs.Fields("Barcode");

                fldLastName = rs.Fields("LastName");

                fldFirstName = rs.Fields("FirstName");

                fldMiddleName = rs.Fields("MiddleName");

                fldPatronType = rs.Fields("PatronType");

                fldPatronStatus = rs.Fields("PatronStatus");

                output[output.length] = new Borrower(fldBorrowerID.Value, fldBarcode.Value, fldFirstName.Value, fldMiddleName.Value, fldLastName.Value, fldPatronType.Value, fldPatronStatus.Value);







    return output;       



 Fig. 3. GetBorrowersByName function, searches Borrower textbase and returns an array of Borrower objects

Here is the script which contains the logic to decide what to do with the results. Again, if single match is found, the Borrower ID is populated automatically, and if multiple matches are found, the top 5 are shown to the user in the gray background box (called boxBorrowerInfo in the script).


function ShowBorrowerResults(results)


    if (results.length < 1)


        selectedBorrower = null;

        Form.boxes("boxBorrowerID").content = "";

        Form.boxes("boxBorrowerInfo").content = "No match found";


    else if (results.length == 1)


        selectedBorrower = results[0];

        Form.boxes("boxBorrowerID").content = results[0].BorrowerID;



    else if (results.length > 1)


        selectedBorrower = null;

        Form.boxes("boxBorrowerID").content = "";

        Form.boxes("boxBorrowerInfo").content = "Matches:";

        for (i = 0; i < results.length;i++)


            if (Form.boxes("boxBorrowerInfo").content != "")


                Form.boxes("boxBorrowerInfo").content += "\n";   


            Form.boxes("boxBorrowerInfo").content += results[i].BorrowerID + "  " + results[i].Barcode + "  " + results[i].LastName + ", " + results[i].FirstName + " " + results[i].MiddleName;





In the single-match-found scenario, the Borrower ID is populated with the found Borrower ID, and the window is refreshed so that any secondary link information shows up.

Fig. 4. A single match has been found for "notdoe". The Borrower ID has been populated, and the secondary fields (name and borrower type) based on the link are showing.

And there you have it. Get to know the Inmagic recordset object and you can query any textbase from any other textbase.


Month List