My Resume | Contact Me | RSS Feed | Follow Me on Twitter

Code Capers

The Ninja Coding Dojo
RSS Feed Twitter Email

Building a Url Shortener with the bit.ly API

clock January 30, 2010 by author Michael Ceranski

It seems like url shorteners have become very popular these days. Especially with applications like twitter who limit your messages to only 140 characters. The cool thing is that most of the URL shorteners have API's that you can use if you want to integrate them into your application. If you are interested in test driving the bit.ly engine then here are the steps:

Go to the bit.ly website and create a free account. Once registered you will receive a username and an API key. You will need these later on when we write the code so make sure you keep these values handy. Since I am using jQuery for this project you will need to add a reference to the jQuery library. I like to use the Google CDN servers when possible but you can always download your own copy of jQuery.

<SCRIPT type=text/javascript src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></SCRIPT>

Now we can create the HTML that will allow the user to enter a long url, click the "Shorten" button and get the bit.ly version:

<table>
    <tr>
        <th>Long Url:</th>
        <td>
            <input id="longUrl" style="width: 250px;" value="http://www.codecapers.com" type="text">
            <input id="btn" value="Shorten" type="button">
        </td>
    </tr><tr>
        <th>Short Url:</th>
        <td><input id="shortUrl" style="width: 150px;" type="text"></td>
    </tr>
</table>

Now, we need to write the jquery code to invoke the bit.ly shorten method. Replace the variables username and key with the values you received from creating your bit.ly account.

$(document).ready( function() {
    var username = "<your username>";
    var key = "<your api key>";        
    
    $("#btn").click( function() {          
        var longUrl = $("#longUrl").val();                
        $.post( "http://api.bit.ly/shorten", { version : "2.0.1", longUrl : longUrl, login : username, apiKey : key }, 
        function( data ) {            
            if( data == "" ) {
                alert( "failed to shorten url. No data returned" );
                return;
            }
                
            eval( "var info = " + data );                
            $("#json").html( data );                    
            if( info.statusCode == "OK" ) {                                    
                $("#shortUrl").val( info.results[longUrl].shortUrl );                                                                                            
            }
            else {
                alert( info.errorMessage );
            }
        }); 
    });
});


Here is the breakdown: In the jQuery document.ready event we wire an event that gets fired when the user click on the button. When the button is clicked an Ajax call is made to http://bit.ly/shorten. The shortenmethod takes a series of parameters which are passed in as an object array in the secondary parameter of the post method. When the event is returned, the anonymous function is called and we inspect the variable naned data to see if we got a response. If the response is not empty we use the eval function to serialize the string into a object. Once we deserialize the string we can check to see if a valid status code was returned. If the status code is "OK" we know the url was shortened and we can display the value in the shortUrl textbox, otherwise an error message is shown.

Just for informational purposes, here is a sample result of the shorten method:

{ "errorCode": 0, "errorMessage": "", "results": { "http://www.cnn.com": { "hash": "4qzXdz", "shortCNAMEUrl": "http://bit.ly/aPTRhZ", "shortKeywordUrl": "", "shortUrl": "http://bit.ly/aPTRhZ", "userHash": "aPTRhZ" } }, "statusCode": "OK" }

Pretty cool for a couple lines of html and a little jQuery!



Do You Live to Program or Program To Live?

clock January 28, 2010 by author Michael Ceranski

ninja coderOver the years I have noticed that there are two different kinds of developers. Developers that live to program and developers who program to live. A Developer who lives to program is someone who is very passionate about thier job. They don't stay up to date on programming techniques and trends because they have to, they do it because they want to. These are the people who stay up late at night churning out code, they run blogs about programming and are constantly hungry for more information. On the flipside, we have developers who program to live. In other words, they code out of necessity. It pays the bills and they get absolutely no enjoyment out of it.

People Who Program To Live

From personal experience the people who program to live are generally poor programmers. They lack the motivation and inspiration to become ninja coders. These are the people who are always saying things like "I don't have time to learn new things" and "I hate change". These are also the people who hate coming to work and are always making excuses when people ask them to work on a project.

People Who Live To Program

A person who lives to program, typically feels empty unless they are writing code or learning something new about programming. These are the self proclaimed nerds on twitter who tweet about MVC, ASP.NET, JQuery or whatever else they happen to be experimenting with that day. These are the people who stand around the water cooler and argue about topics like WebForms vs MVC until they are red in the face. These are the people who generally write bitchin code!

Closing Arguments

During interviews, you can generally detect a non-coder by asking them questions like "What kind of programs do you like to build in your free time?". If they say they they only write code at work then send them packing. In my humble opinion, there is nothing worse then a programmer who codes out of obligation.

I personally have to be dragged off the computer some days. Luckily, I have a very understanding wife who tolerates me. Live to Program or go home!



Dynamic Select Lists with MVC and jQuery

clock January 27, 2010 by author Michael Ceranski

Update 1/28/2010: This article is Scott Guthrie approved (Corporate Vice President in the Microsoft Developer Division).

Scott Gu Article RT


There are occasions when you are developing a form and you need to have a drop down list that dynamically populates based on the value of another control. The classic example is a contact form that dynamically populates the states and provinces list when a country is selected. For example, when I select "United States" I want the child drop down to have entries like New York, Alabama, Texas and etcetera. When I select "Canada" I would expect to see provinces like Nova Scotia and Ontario. Fortunately, this functionality is very easy to build using ASP.NET MVC and jQuery. Best of all, we can do this without any postbacks using the jQuery Ajax functions.

To get started make sure you have a reference to the jQuery library, preferably in the HEAD section of your html. For the purposes of this example I am using jQuery version 1.4. You can either download jQuery locally or reference it directly from Google:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript"></script>

OR

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js" type="text/javascript"></script>

Now, that our jQuery reference is set we can build some HTML for our View page. The "countries" dropdown is already pre-populated but notice that the states combo is empty.

<table>
    <tr>
        <th>Country:</th>
        <td>
            <select id="countries">
                <option>-- Select a Country -- </option>
                <option value="1">United States</option>
                <option value="2">Canada</option>
            </select>
        </td>
    </tr><tr>
        <th>State:</th>
        <td>
            <select id="states">
            </select>
        </td>
    </tr>
</table>

Moving on, we will build the controller method which will get the states or provinces for a specified country.

public JsonResult GetStates(int countryID)
{
    var list = new object[] { };

    switch (countryID)
    {
        case 1:
            list = new object[] {
                new { value = 1, name = "Alabama" },
                new { value = 2, name = "Alaska" },
                new { value = 3, name = "California" }
            };
            break;
        case 2:
            list = new object[] {
                new { value = 1, name = "Ontario" },
                new { value = 2, name = "Quebec" },
                new { value = 3, name = "Nova Scotia" }
        };
        break;
    };

    return Json(list);
}

This code is static and obviously geared for a demo but you could just as easily loaded these object arrays from a database table. Please take notice of the method signature. We have a single parameter named countryID which determines what data should be returned. Also notice the return type is JsonResult. This means the object array will be serialized as JSON (JavaScript Object Notation) which can easily be consumed by jQuery. Now that the controller code is completed we can write the jQuery code.

<script type="text/javascript">
    $(document).ready(function() {    
        $("#countries").change(function() {     
            $.post("/Home/GetStates/", { countryID: $(this).val() }, function(data) {
                populateDropdown($("#states"), data);
            });
        });
    });

    function populateDropdown(select, data) {
        select.html('');
        $.each(data, function(id, option) {
            select.append($('<option></option>').val(option.value).html(option.name));
        });       
    }
</script>

Here is a breakdown of the jQuery code. First, we wire an event to the country drop down list. When a country is selected we make an asynchronous call to the GetStates method in the Home controller. The selected item in the country drop down is passed in as a variable to the method: { countryID: $(this).val() }. When the data is returned from the GetStates method we pass it off to the populateDropdown function. The populateDropDown function clears the drop down (in case it previously had values for a different country) then populates the combo dynamically. This is done by creating an option item and setting the value and text.

If you want to try this code out for yourself, then download the sample project below.

DynamicDropDown.zip (37.28 kb)



Software Development Do's and Don'ts

clock January 25, 2010 by author Michael Ceranski

My first encounter with programming was around 1992 when I developed my first website. The website was complete with frames, flashing gifs and marquee tags. It was an absolute nightmare! Anyway, I gradually learned enough about computers and coding that I suckered a small company into giving me an internship. Although, I was hired to fix computers and maintain the test lab, I secretly always wanted to write code. Eventually, I convinced my boss to let me take home the Delphi 4 CD and a few months later I was hired full time as a software engineer.

Between my first hello world program and now, many things have changed. Programming languages have come and gone. We went from waterfall to agile and from extreme programming to test driven design. Nonetheless there are certain ideas and principals around computer programming that never seem to change. That is really the whole idea behind this post.

Never write code with the intention that you will fix it later - Chances are you will never have the time or opportunity to fix it later. Once code rolls into production, the maintenance windows become scarce. Like my Dad always said "Do it right, or don't do it at all".

Think large write small - When we develop new applications we generally start out with a few users and a little bit of data. For example, your application may start out with a thousand records but two years from now you may have 2 billion records. So think twice about queries that do a "select *" or methods that read in large datasets. Write your code with the anticipation that you will eventually have many users and lots of data.

Be "green" with your data - In general, I try to "Lazy Load" data whenever possible. There is no sense loading data that you may never use. My theory is load late and drop early.

Caching is also very important, especially with static information like lookup lists. For web development this could mean that you store some data in the Application or Session variables.

Also, don't store static lists in the database unless absolutely necessary. As a DBA, I have seen people store ridiculous things in a database such as month names or days of the week. Last time I looked those did not change!

Pick good defaults - Make the program usable in its default state. Most users do not read XML and aren't interested in editing it. By adding extraneous configuration settings you are only adding complexity to your application. Usable defaults are the way to go. If there are parameters that need to be modified by the end user then give them a user interface to change them.

Don't Overdesign - Every programmer has probably been guilty of overdesigning something. Sometimes we get tempted by fancy patterns and practices. In addition, some of us tend to abuse things like inheritance and abstraction. Most of the time its best to keep things simple. It is a rare occasion when I need to have more than 2 layers of inheritance.

Overdesign is also very common with databases. People get hung up on rules like "third normal form". Sometimes when you over-normalize a database is makes it impossible to query the data later on. If your application is going to require reports, sometimes its better to design the database with the reports in mind. In other words, let the reports dictate how the data is stored.

Code is not self commenting - I can't tell you how many times I have written a piece of code only to return to it a few years later and ask myself "What was I thinking? or "Why did I do that?". Nothing is worse then spending an entire day rewriting a section of code only to roll back the changes because you discover the original reason of why you wrote it that way.

And Finally, "Software is never finished. It is only abandoned" - One of my old co-workers told me this about 10 years ago and it stuck. The statement is absolutely true. There is always something that can be improved, optimized or re-written.

If you have any philosophies or rules that you developed over the years then please leave a comment. It is always fun to hear your thoughts!



Building a Dashboard Using The Microsoft Chart Controls

clock January 22, 2010 by author Michael Ceranski

Most experienced developers will tell you that end users tend to "judge an application by its cover". In other words, they don't care how long you spent building an application or what techniques you employed to build it. They are only concerned with how it looks. I can recall a few times in my life where I spent many endless days and nights building an application just to meet a deadline and the first remark from the end-users was "can you change the color of that label" or "can you put our logo on the main page". They don't care that the application meets the specifications or that the project was on time and under budget, that was expected. They are more concerned with the way things look.

In my current job, I built an ASP.NET MVC application to track server inventory. Overall the application is a huge improvement over the previous tracking tools. Which by the way, consisted of a few excel spreadsheets stored on a remote file share. Strangely enough, the first comment I got from my management after rolling out my application was "Can you make a dashboard?". I guess, they really craved something visual and interesting on the main page to give them a warm and fuzzy feeling about the application. So after some research I stumbled upon the Microsoft Chart Controls. A couple of hours later I had a dashboard created and here is the result:

Integrating the chart controls into your ASP.NET MVC application is very easy. To get started, you will need to modify a few keys in the appSettings and httpHandlers section of your web.config file. Most likely you will just cut and paste my settings without giving it a second thought. However, it is important that you configure the value of the ChartImageHandler key according to your environment. The are three different storage modes which are: session, file and memory. Ultimately, your choice will need to be based on your architecture, available server resources and other weighing factors. For a complete explanation of the settings and possible values please view this blog post by Delian Tchoparinov.

<appSettings>
    <add key="ChartImageHandler" value="storage=file;timeout=20;URL=/App_Data/MicrosoftChartControls/" />
</appSettings>
...
<httpHandlers>
  <!-- Microsoft Chart Controls -->
  <add verb="*" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler,     System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>    
  <add verb="*" path="Reserved.ReportViewerWebControl.axd" type="Microsoft.Reporting.WebForms.HttpHandler,     Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"   />

Now that the configuration is out of the way we can start building some charts. In my case, I created a new class named DashboardModel which will be returned to the View by the controller. When a new instance of the DashboardModel class is created I immediately establish a connection to the database and load all the data I need to build my charts. My dashboard has five pie charts but the data is collected with a single LINQ query. Since I iterate over the data a few times to summarize the data into different buckets I cache it in a List (named pieChartdata). If you are experienced with LINQ then you probably know that LINQ will typically execute a query each time you iterate over the results. By converting the results of my query to a List, I can avoid the need to repetitively pound on my database server for the data. Why? Because when I converted it to a list I forced it into memory. Now I can query that data all day long without making a round-trip to my database server. Admittedly, I am a bit of a performance freak. I blame this on my DBA background and from getting code reviews from people who learned how to program on mainframes. Anyways, if you are still unclear about why I converted my query to a list then please read this post.

public class DashboardModel
{
    DBAInventoryDataContext db = new DBAInventoryDataContext();
    List<DBASummary> pieData;
    List<DBASupportMetric> metrics;

    public DashboardModel()
    {
        pieData = db.usp_DBADashboardMetrics().ToList<DBASummary>();
        metrics = ( from x in db.DBASupportMetrics
                    orderby x.SampleDate ascending
                    select x ).ToList<DBASupportMetric>();
    }

Since I am making a total of five pie charts I decided to abstract the code that creates them. To start, I needed a common data structure that I could use to populate each chart. Therefore, I created an internal class named PieChartData. It has a Title, xValues, yValues and then an array of objects called Data that I used to populate tooltips and other miscellaneous properties. I marked it as an internal class because I have no intent of using it anywhere other than from within the DashboardModel class. I am a firm believer of only exposing classes and methods unless it is absolutely necessary.

internal class PieChartData{
    public string Title { get; set; }
    public DBASummary[] Data { get; set; }
    public string[] xValues { get; set; }
    public decimal[] yValues { get; set; }
}

Now its a simple matter of instantiating a PieChartData object and passing it to another function called BindChartData which assembles the chart:

private Chart BuildDatabasePieChart()
{
    var data = new PieChartData
    {
        Title = "Databases: " + (from y in pieData select y.PrimaryDatabases).Sum().ToString(),
        Data = (from x in pieData orderby x.PrimaryDatabases descending select x).ToArray(),
        xValues = (from x in pieData orderby x.PrimaryDatabases descending select x.LastName).ToArray(),
        yValues = (from y in pieData orderby y.PrimaryDatabases descending select y.PrimaryDatabases).ToArray()
    };

    return BindChartData(data);
}

private Chart BuildServerPieChart()
{
    var data = new PieChartData
    {
        Title = "Servers: " + (from y in pieData select y.PrimaryServers).Sum().ToString(),
        Data = (from x in pieData orderby x.PrimaryServers descending select x).ToArray(),
        xValues = (from x in pieData orderby x.PrimaryServers descending select x.LastName).ToArray(),
        yValues = (from y in pieData orderby y.PrimaryServers descending select y.PrimaryServers).ToArray()
    };

    return BindChartData(data);
}


private Chart BindChartData(PieChartData data)
{
    Chart chart = new Chart();
    chart.Width = 150;
    chart.Height = 300;
    chart.Attributes.Add("align", "left");

    chart.Titles.Add(data.Title); // Display a Title  
    chart.ChartAreas.Add(new ChartArea());

    chart.Series.Add(new Series());

    chart.Legends.Add(new Legend("DBAs"));
    chart.Legends[0].TableStyle = LegendTableStyle.Auto;
    chart.Legends[0].Docking = Docking.Bottom;

    chart.Series[0].ChartType = SeriesChartType.Pie;
    chart.Series[0]["PieLabelStyle"] = "Inside";
    chart.Series[0]["PieLabelStyle"] = "Disabled";
    chart.Series[0].BackGradientStyle = GradientStyle.DiagonalLeft;
    chart.Series[0].BackSecondaryColor = System.Drawing.Color.LightGray;
    chart.Series[0]["PieLineColor"] = "Black";
    chart.Series[0]["PieDrawingStyle"] = "Concave";

    for (int i = 0; i < data.xValues.Length; i++)
    {
        string x = data.xValues[i];
        decimal y = data.yValues[i];
        int dbaId = data.Data[i].ContactID;
        int ptIdx = chart.Series[0].Points.AddXY(x, y);
        var c = data.Data[i];
        DataPoint pt = chart.Series[0].Points[ptIdx];
        pt.Url = "/Instance/Index/" + dbaId.ToString();
        pt.ToolTip = c.FirstName + " " + c.LastName + ": #VALY";
        pt.LegendText = "#VALX: #VALY";
        pt.LegendUrl = "/Contact/Details/" + dbaId.ToString();
        pt.LegendToolTip = "Click to view " + c.FirstName + "'s contact information...";
    }

    chart.Series[0].Legend = "DBAs";
    return chart;
}

Finally, I created a public property called PieCharts which creates all five pie charts and populates a list.

public List<Chart> PieCharts
{
    get
    {
        List<Chart> charts = new List<Chart>();
        charts.Add(BuildSQLPieChart());
        charts.Add(BuildOraclePieChart());
        charts.Add(BuildDatabasePieChart());
        charts.Add(BuildServerPieChart());
        charts.Add(BuildClusterPieChart());
        return charts;
    }
}

Now its time to build the controller method. I instantiate a copy of the DashboardModel object and return it to the View:

public ActionResult Index() {
    DashboardModel model = new DashboardModel();
    return View(model);
}

In the view we iterate over the pie charts and add them to a Panel.

<%@ Page Title="Support Dashboard" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
    Inherits="System.Web.Mvc.ViewPage<DashboardModel>" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Support Dashboard</h2>
    <% 
        foreach ( System.Web.UI.DataVisualization.Charting.Chart pie in Model.PieCharts)
        {
           pieChartPanel.Controls.Add(pie);
        }
        supportChart.Controls.Add(Model.SupportMetricChart);        
    %>
    <asp:Panel ID="pieChartPanel" runat="server"></asp:Panel>
    <br />
    <asp:Panel ID="supportChart" runat="server"></asp:Panel>
</asp:Content>

And Voila! We have a dashboard!

Additional Resources:



About the author

MikeMy name is Michael Ceranski. I am a software developer from Buffalo NY. I have been writing code for over 10 years starting with Borland Delphi and later migrating to the .NET stack. I enjoy blogging about .NET, MVC and jQuery and I hope to spread my enthusiasm for technology by sharing my thoughts and ideas with you.

View my resume

Cumulus

This will be shown to users with no Flash or Javascript.

Sign in