Add ‘Tweet This’ button to your Asp.Net site. Twitter + url shortening

Adding your own ‘Tweet This’ buttons so your visitors can post to twitter (complete with URL shortening using is really easy.

Just add a page ‘twitter.aspx’ to your site and remove all the HTML from the page.

Add this code:

Imports System.Net

Partial Public Class Twitter

    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If Request.QueryString("url") <> "" And Request.QueryString("com") <> "" Then

            TweetThis(Request.QueryString("url"), Request.QueryString("com"))

        End If

    End Sub

    Private Sub TweetThis(ByVal sIWTFURL As String, ByVal sComment As String)

        Dim sShortURL As String

        Dim sFullTweet As String

        sShortURL = ShortenURL(sIWTFURL)

        sFullTweet = sComment & " - " & sShortURL


    End Sub

    Private Function ShortenURL(ByVal sURL As String) As String

        Dim sJSON As String

        Dim oWebClient As New WebClient

        Dim sBitlyURL As String

        Dim sShortURL As String

        sBitlyURL = "" & Server.UrlEncode(sURL) & "&login=bitlyapidemo&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07"

        sJSON = oWebClient.DownloadString(sBitlyURL)

        sJSON = Mid$(sJSON, InStr(sJSON, Chr(34) & "shortUrl" & Chr(34)) + 9)

        Do While sJSON.ToLower.StartsWith("http://") = False

            sJSON = Mid$(sJSON, 2)


        sShortURL = sJSON.Split(Chr(34))(0)

        ShortenURL = sShortURL

    End Function

    Private Sub SentToTwitter(ByVal sComments As String)

        Dim sURL As String

        sURL = "" & HttpUtility.UrlEncode(sComments)

        Response.Redirect(sURL, False)

    End Sub

End Class

Note: I am using the default login in the example, you should sign up for your own account so you can track usage of your links.

Now you just need to add some javascript to your html pages:

<a href="#" onClick='javascript:PostToTwitter()'>Tweet This</a>

function PostToTwitter()
var sTweet = 'This is the default text that will appear in the tweet';
var ShareURL = window.location.href;''+encodeURIComponent(ShareURL)+'&com='+encodeURIComponent(sTweet));
return false;

We Got Domain - over 10,000 aged domains for sale

We Got Domain is a quick site that I built to make buying domains from forums like dnforum, digitalpoint etc easier. It extracts domain names from the sale threads and then finds out extra info like Backlinks, Pagerank, Creation date etc. Domains can only be bought on the forums so hopefully We Got Domain will save time for people buying domains while driving extra traffic to the forums (and they get tons of do-follow links as a small bonus).

The site was partly inspired by a the post Purchasing Domains on as well as Shoemoney Marketplace and

I hope you find the site useful - send me an email if you have any suggestions or improvements.

Your own Lolcats widget (I Can Has Cheezburger?)

OK, I’m the first to admit that the whole lolcats thing might not be for everyone. But it’s for me. If it’s for you, too, then enjoy :)
If you would like this widget on your site/blog, just add the code:
<script src='' type='text/javascript'></script>
And here’s how it was done:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim sCacheKey As String = "CACHE_ICanHasCheezburger"
        Dim oLolCat As clsLolCat
        Dim sHTML As String        

        oLolCat = CType(Cache(sCacheKey), clsLolCat)        

        If oLolCat Is Nothing Then
            oLolCat = PicAndCaptionGet()
            Cache.Insert(sCacheKey, oLolCat, Nothing, Now.AddHours(1), System.Web.Caching.Cache.NoSlidingExpiration)
        End If        

        sHTML = "<div><a href='" & oLolCat.sLinkURL & "'><img border='0' src='" & oLolCat.sPicURL & "'/></a>"
        sHTML = sHTML & "<div>More at LolCats at <a href=''>I Can Has Cheezburger</a></div></div>"        

        sHTML = "document.write(""" & sHTML & """);"

    End Sub

This first part just checks to see if we have the LolCat HTML in the cache. If we don’t then generate the HTML and put it in the cache again. Saves us hitting the site all the time (or in this case, feedburner).

    Private Function PicAndCaptionGet() As clsLolCat
        Dim Http As HttpWebRequest
        Dim sRequestURL As String
        Dim WebResponse As HttpWebResponse
        Dim responseStream As Stream
        Dim Reader As StreamReader
        Dim sText As String
        Dim oRSSDoc As New System.Xml.XmlDocument
        Dim oFirstNode As System.Xml.XmlNode
        Dim oLolCat As New clsLolCat        

        sRequestURL = ""
        Http = CType(WebRequest.Create(sRequestURL), HttpWebRequest)
        Http.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate")
        WebResponse = CType(Http.GetResponse(), HttpWebResponse)
        responseStream = WebResponse.GetResponseStream        

        If (WebResponse.ContentEncoding.ToLower().Contains("gzip")) Then
            responseStream = New GZipStream(responseStream, CompressionMode.Decompress)
        ElseIf (WebResponse.ContentEncoding.ToLower().Contains("deflate")) Then
            responseStream = New DeflateStream(responseStream, CompressionMode.Decompress)
        End If        

        Reader = New StreamReader(responseStream, Encoding.Default)
        sText = Reader.ReadToEnd()

        oFirstNode = oRSSDoc.SelectSingleNode("//item")
        oLolCat.sCaption = oFirstNode("title").InnerText
        oLolCat.sLinkURL = oFirstNode("link").InnerText
        oLolCat.sPicURL = oFirstNode("media:content").Attributes("url").Value        

        PicAndCaptionGet = oLolCat
    End Function        

End Class        

Public Class clsLolCat
    Public sPicURL As String
    Public sCaption As String
    Public sLinkURL As String
End Class

This is the code that visits the icanhascheezburger RSS feed and extracts the latest post details. This is all pretty simple stuff, with one cool bit that takes care of the gzip compression that is on the feed. Full credit must go to Rick Strahl for his post talking about gzip:

Convert MySQL to MS SQL Server Part 2

Following on from my last post on converting MySQL tables to MS SQL, here is the code to convert Insert SQL statements from MySQL to MS SQL. Try it out here: The code for this is really simple. Again, if you have any improvements just post the code here and I’ll update the original and give you credit.

        Dim ConvertedSQL As String = ""  

        ConvertedSQL = Me.txtMySQL.Text  

        ConvertedSQL = ConvertedSQL.Replace("rn", "")
        ConvertedSQL = ConvertedSQL.Replace("'", "''")
        ConvertedSQL = ConvertedSQL.Replace("\" & Chr(34), Chr(34))
        ConvertedSQL = ConvertedSQL.Replace("INTO " & Me.txtOldTableName.Text, "INTO " & Me.txtNewTableName.Text)
        Me.txtMSSQL.Text = ConvertedSQL  

Convert MySQL to MS Sql Server

I’ve been setting up some small database-driven sites lately and I needed to convert some MySQL tables to MS Sql Server. It’s not too hard convert them by hand, but it is oh so tedious…

So I wrote a small app to convert the MySQL tables to MS SQL, which you can try out here:

Now this was a quick & dirty app, so it really doesn’t do much else other than convert the datatypes and get the syntax right. It doesn’t convert keys/constraints/indexes or any of that stuff. It doesn’t even convert all the datatypes, but it has the main ones (ie - the ones I needed) covered. Note: If you add more datatypes or add support for indexes etc just email/post your changes and I will update this code as well as giving link credit.

Here is the code to do the conversion:

    Private Function ConvertTable(ByVal sMySQL As String, _
    ByRef sMSSQL As String) As String
        Dim sLine As String = ""
        Dim iC As Integer
        Dim sVarName As String
        Dim sDatatype As String
        Dim sLen As String
        Dim iLen As Integer
        Dim sNewDataType As String = ""
        Dim sOutput As String = ""
        Dim iLen2 As Integer

        For iC = 0 To sMySQL.Split(vbLf).GetUpperBound(0)
            sLine = sMySQL.Split(vbLf)(iC)
            sLine = Trim$(sLine)
            If sLine.StartsWith("CREATE TABLE") = True Then
                sMSSQL = sMSSQL & sLine & vbCrLf

            ElseIf sLine.StartsWith("KEY") = True Or sLine.StartsWith("PRIMARY KEY") = True Then
                'Ignore this
            ElseIf sLine.StartsWith(")") = True Then
                sMSSQL = Strings.Left$(sMSSQL, Len(sMSSQL) - 3)
                sMSSQL = sMSSQL & vbCrLf & ")"
                Exit For
                'sLine = sLine.Replace(",", " ")
                sVarName = sLine.Split(" ")(0)
                sDatatype = sLine.Split(" ")(1)
                If InStr(sDatatype, "(") > 0 Then
                    sLen = Mid$(sDatatype, InStr(sDatatype, "("))
                    sLen = sLen.Replace("(", "").Replace(")", "")
                    If InStr(sLen, ",") > 0 Then
                        iLen = Val(sLen.Split(",")(0))
                        iLen2 = Val(sLen.Split(",")(1))
                        iLen = Val(sLen)
                    End If
                    sDatatype = Strings.Left$(sDatatype, InStr(sDatatype, "(") - 1)
                End If
                If InStr(sDatatype, ",") > 0 Then
                    sDatatype = sDatatype.Split(",")(0)
                End If
                Select Case LCase(sDatatype)
                    Case "int", "smallint", "year", "tinyint"
                        sNewDataType = "int"
                    Case "blob", "text"
                        sNewDataType = "text"
                    Case "decimal"
                        sNewDataType = "decimal(" & iLen & "," & iLen2 & ")"
                    Case "double"
                        sNewDataType = "float(10)"
                    Case "date", "datetime"
                        sNewDataType = "datetime"
                    Case "timestamp"
                        sNewDataType = "bigint"
                    Case "varchar"
                        sNewDataType = "varchar(" & iLen & ")"
                    Case "char"
                        sNewDataType = "char(" & iLen & ")"
                    Case Else
                        sOutput = sOutput & "Unknown datatype = '" & sDatatype & "'"
                        sMSSQL = ""
                        Exit For
                End Select
                sMSSQL = sMSSQL & sVarName & " " & sNewDataType & "," & vbCrLf

            End If

        If sOutput = "" Then
            sOutput = "Conversion Complete"
        End If
        ConvertTable = sOutput

    End Function

Note: I have now made another post which shows how to Convert MySQL Inserts to MS SQL Server

Check 1000s of Images for duplicates quickly

I came up against a problem recently where I had over 4000 images and I needed to check to see if there were any duplicates and remove them. The images were all different sizes/resolutions and duplicate images could have the same picture, but have different sizes/resolutions.

I might also add that I’m not exactly ‘Dr Maths’ or have any clue about image transformations - but I needed to get rid of the dupes in a hurry.

The method I came up with in the end was pretty simple, and while not foolproof, I haven’t seen it make a mistake yet. It was also quick enough for my needs, removing all the duplicates in around 20 minutes.

The Screenshot

If you want to compare 2 directories, then fill out both directory boxes. Any duplicates you choose to delete will be removed from directory 2. If all the files are in one directory, then leave the directory 2 textbox empty.

The Downloads

CompareImages.exe - You can run this - Full code

The Solution:

1. build 50×50 copies of all images

Under the root directory of the images I add another directory called ’small’. I then make 50×50 copies of all the images and put them in this directory. I do this for 2 reasons.

  • It normalises the size of all the images - I couldn’t compare 200×200 to 300×300 images before, but now they are both 50×50.
  • Using pixel-by-pixel comparison, 50×50 is a lot less comparisons than 300×300 (2500 vs 90,000) and is still accurate enough to detect duplicates

2. Compare the 50×50 images with each other

Here is where the people that know something about images will most likely shake their heads (if they haven’t started already). For the rest;

For both images, I compare every pixel to see if they have ‘almos the same’ RGB value. If the RGB values are not similar, then I increment difference count. Once the number of differences reaches 50 these images are not the same, and I stop comparing (which saves a lot of time).

iDiff = 20

For iY = 0 To iHeight - 1
    For iX = 0 To iWidth - 1
	oOrigPixel = bmOrig.GetPixel(iX, iY)
	oNewPixel = bmNew.GetPixel(iX, iY)

	If Math.Abs(Int(oOrigPixel.R) - Int(oNewPixel.R)) > iDiff OrElse _
    	Math.Abs(Int(oOrigPixel.G) - Int(oNewPixel.G)) > iDiff OrElse _
   	Math.Abs(Int(oOrigPixel.B) - Int(oNewPixel.B)) > iDiff Then
    		iDiffCount = iDiffCount + 1
    		If iDiffCount > 50 Then
			'Images are not duplicates
			Exit Function
    		End If
	End If

'Images ARE duplicates

Draggable Marker Google Maps Demo

So you’ve been checking out my previous posts on Google Maps and Draggable Markers, and it would be nice to have a demo so you can see the draggable markers in action.

Check this out:

And the code as well? Here is the source for the Google Maps Demo

Add Draggable Markers and Events to your Google Maps

Following on from my last post on how to add Google Maps to your ASP.Net site, I’m now going to show how easy it is to add draggable markers to your map.

First, make sure you have the map working on your webform.

Having the map fire server-side events on user actions is pretty simple, and here is the code:

    Private Sub AddEventToMapDemo()
        Dim GeoCode As Subgurim.Controles.GeoCode
        Dim sMapKey As String = System.Configuration.ConfigurationManager.AppSettings("")

        GeoCode = GMap.geoCodeRequest("3052. VIC. australia", sMapKey)
        Dim gLatLng As New Subgurim.Controles.GLatLng(, GeoCode.Placemark.coordinates.lng)

        GMap.setCenter(gLatLng, 16, Subgurim.Controles.GMapType.GTypes.Normal)
        Dim oOption As New Subgurim.Controles.GMarkerOptions
        oOption.draggable = True
        oMarker = New Subgurim.Controles.GMarker(gLatLng, oOption)

        GMap.addListener(New Subgurim.Controles.GListener(oMarker.ID, Subgurim.Controles.GListener.Event.dragend, _
        "function(){{ var ev = new serverEvent('dragend', 0); ev.addArg(" & oMarker.ID & ".getPoint().lat()); ev.addArg(" & oMarker.ID & ".getPoint().lng()); ev.send(); }}"))

    End Sub

You then need to add code to handle the event:

    Protected Function GMap_ServerEvent(ByVal s As Object, ByVal e As Subgurim.Controles.GAjaxServerEventOtherArgs) As String

        If e.eventName = "dragend" Then
            Response.Write("New Latitude =" & e.eventArgs(0) & ", New Longitude = " & e.eventArgs(1))
        End If

    End Function

The server-side event will be fired every time the marker is dragged and dropped.

In my situation, I wanted to allow the user to drag & drop the marker as many times as they wanted - and only store the new Lat/Long values when the user pressed the Save button.

This is a little bit harder to code as the variables used to reference the marker cannot be accessed globally - so we can’t just read their values when the user presses the save button (to the gurus: I’m sure they can, but I couldn’t find an easy way to get at them) . However, we can store them in hidden fields when the DragEnd event is raised, and examine those fields when Save is pressed.

Add these fields to your webform:

<input type=hidden id="hidLat" name="hidLat" runat=server />
<input type=hidden id="hidLng" name="hidLng" runat=server />
<asp:Button ID="Button1" runat="server" Text="Save" />

And add this sub to your code-behind:

    Private Sub NewLatLongOnSaveMapDemo()
        Dim GeoCode As Subgurim.Controles.GeoCode
        Dim sMapKey As String = System.Configuration.ConfigurationManager.AppSettings("")

        GeoCode = GMap.geoCodeRequest("3052. VIC. australia", sMapKey)
        Dim gLatLng As New Subgurim.Controles.GLatLng(, GeoCode.Placemark.coordinates.lng)

        GMap.setCenter(gLatLng, 16, Subgurim.Controles.GMapType.GTypes.Normal)
        Dim oOption As New Subgurim.Controles.GMarkerOptions
        oOption.draggable = True
        oMarker = New Subgurim.Controles.GMarker(gLatLng, oOption)

            GMap.addListener(New Subgurim.Controles.GListener(oMarker.ID, Subgurim.Controles.GListener.Event.dragend, _
            "function(){ document.getElementById('hidLat').value=" & oMarker.ID & ".getPoint().lat();document.getElementById('hidLng').value=" & oMarker.ID & ".getPoint().lng() }"))

    End Sub

And here is the ‘Save’ button click event:

    Protected Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Response.Write("New Latitude =" & hidLat.Value & ", New Longitude = " & Me.hidLng.Value)
    End Sub

Code the perfect Exit Popup (exit console)

All popups are bad news, right? Nothing gets rid of visitors faster than a crappy ad for casinoviagraporn getting in their face.

But what about visitors that found your site through a search engine, spend 5 seconds on 1 page of your site & then press the back button?

They didn’t find what they want.
They aren’t coming back.
Don’t they deserve some popup love?

Seriously, you have (most likely) lost these visitors for good anyway, so showing them a popup won’t make much difference to your visitor retention.

So how do you do it?
The key is the javascript event onUnload. This fires when a page is exited, whether by navigating out via a link, pressing the back button or closing the browser. The problem is, it fires every time a page unloads - and we only want a popup when the visitor leaves your site (not every time they navigate to a new page on your site).

Over at they describe a solution which involves adding an onClick event to every internal link. The onClick event effectively blocks the popup from firing within the onUnload event.

Its a good solution, but finding every internal link within a decent sized site is a nightmare. So we need an automatic way of adding the onClick event to internal links, and it must not overwrite any existing onClick events we have already set up (unobtrusive javascript).

Check this out:

var Page_Enter;
var TimeLimit=20;
var Page_ShowPopOnExit=false;
var MySiteDomain='YOURSITE.COM';

function XBrowserAddHandlerPops(target,eventName,handlerName) {
  if ( target.addEventListener ) {
    target.addEventListener(eventName, function(e){target[handlerName](e);}, false);
  } else if ( target.attachEvent ) {
    target.attachEvent("on" + eventName, function(e){target[handlerName](e);});
  } else {
    var originalHandler = target["on" + eventName];
    if ( originalHandler ) {
      target["on" + eventName] = function(e){originalHandler(e);target[handlerName](e);};
    } else {
      target["on" + eventName] = target[handlerName];

function InternalLink() {
	Page_ShowPopOnExit = false;

function PageEnter() {
   Page_Enter=new Date();

function SiteExit() {
   var time_dif;
   var Page_Exit=new Date();
   if (time_dif<=TimeLimit && Page_ShowPopOnExit==true)
	alert('Here is your popup!');

function LinkConvert()
var href;
	var anchors = document.getElementsByTagName('a');

	for(var y=0; y<anchors.length; y++)
		href = anchors[y].href.toLowerCase();
		if (!(href.indexOf("http://")!=-1 && href.indexOf(MySiteDomain)==-1))


Save this as popup.js

The javascript does a few things.

  1. As soon as the page is finished loading a copy of the time is stored, so we can tell how long they have been on the page.
  2. All internal links have an onClick event handler added. An internal link is determined as one is missing ‘http://’ (internal relative links do not have the http:// ) and your domain name in the href. Note: If you are using javascript links for internal navigation then this method will not work. However, it should be easy to add the ‘Page_ShowPopOnExit = false;’ to your javascript link code.
  3. When the page unloads 2 checks are done; Has the person left the page within XX seconds? (if they stay 5 minutes then perhaps they liked your site, so no popup for them). Is the visitor following an internal link? If the answers are Yes & No respectively, then show them a pop.

Great, but if we just add this .js file to every page on our site then even people who directly type in our URL can be shown pops. These are the hardest of our hardcore fans, and should never get a pop. Also, I only want to show pops to people that hit my site from a search engine & immediately leave - if they visit more than 1 page then no pop for them.

So we need to inspect the Referrer, and check that they are coming from a search engine. I’m going to do this server side so I can cut down on my page size if the visitor is not pop-worthy.

In ASP.Net (put it in the page.load event):

Dim sPageReferrer As String = ""
If Not (Request.UrlReferrer Is Nothing) Then
    sPageReferrer = LCase(Request.UrlReferrer.ToString)
End If
If InStr(sPageReferrer, "") > 0 Or InStr(sPageReferrer, "") > 0 Or InStr(sPageReferrer, "") > 0 Then
    RegisterClientScriptBlock("PopUnder", "<script src='includes/popunder.js' type='text/javascript'></script>")
End If

If you wanted to do this in the .js file, then just change the last bit of popup.js to:

var href = document.referrer.toLowerCase();
if (href.indexOf("")!=-1 || href.indexOf("")!=-1 || href.indexOf("")!=-1)

Add Google Maps to your .Net site in 10 minutes

Ever wanted to add a Google Map to your site but only had 15 minutes to spare? Now you can add a map and still have time to brag to your mates and bask in the worship that (inevitably) comes afterward.

Basically, the guys over at have already done all the hard work in writing the .Net wrapper for Google Maps. Problem is, the examples on their site are mostly in spanish & its a bit difficult to find out exactly what is needed to get everything working.

But all this is cutting into your bragging time - so lets get started!

1. Get a Google Maps API key from here:

2. Download the SubGurim wrapper dll from here:

3. Unzip it, and put it in your \bin directory

4. Add it to your toolbox by
Tools -> Choose Toolbox Items -> Browse -> Select the .dll file -> OK
GMap will now be in the ‘Standard’ area of your Toolbox.

5. Add a new webpage.

6. Drag the GMap from the toolbox onto the page. A new instance of the GMap will appear on the page, with the name ‘GMap1′

7. Add the following lines to your web.config file:

    <add key="" value="YourGoogleMapsAPIKeyHere" />

8. Add the following code to your Page.Load sub

        Dim sStreetAddress As String
        Dim sMapKey As String = ConfigurationManager.AppSettings("")
        Dim GeoCode As Subgurim.Controles.GeoCode

        sStreetAddress = "100 Russell St. Melbourne. VIC. 3000. Australia"
        GeoCode = GMap1.geoCodeRequest(sStreetAddress, sMapKey)
        Dim gLatLng As New Subgurim.Controles.GLatLng(, GeoCode.Placemark.coordinates.lng)

        GMap1.setCenter(gLatLng, 16, Subgurim.Controles.GMapType.GTypes.Normal)
        Dim oMarker As New Subgurim.Controles.GMarker(gLatLng)

Press F5, and start basking in the glory!

Update: I’ve now posted the code to add draggable markers and events to your Google Maps