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

Code Capers

The Ninja Coding Dojo
RSS Feed Twitter Email

Generating Structured Text with StringTemplate

clock February 7, 2010 by author Michael Ceranski


writing StringTemplate is a powerful tool that can be used to generate source code, web pages, emails, or any other formatted text output. Although StringTemplate was originally written in Java it has been ported to C#, Python and Ruby. My first encounter with StringTemplate was a few years ago when I needed to build a complex deployment script for setting up new SQL Server instances. The script needed to configure operators, alerts, SQL mail and also create a few basic jobs. The most important requirement was that the template could be easily changed without recompiling any code or needing any advanced knowledge of programming. Luckily, StringTemplate met all these requirements.

In order to get familiar with the functionality lets start by looking at a few sample templates. Here is a classic example which I found on the antlr website. This is a template for generating a simple SQL statement.

StringTemplate query = new StringTemplate("SELECT $column$ FROM $table$;");
query.SetAttribute("column", "name");
query.SetAttribute("table", "User");
In this example you probably immediately noticed the dollar signs. When we surround areas of our template with dollar signs we are telling StringTemplate that some work needs to be done. In particular when you execute this code you replace the variable $column$ with the value “name” and $table$ with “User”. The end result is the string “Select name from User”.

Now previously I mentioned that I was using StringTemplate to build a deployment script. In my environment I have many different versions of SQL Server. Since I did not want to write a special template for each SQL version I needed a way to put conditional logic in my template. Fortunately, this is easily accomplished with StringTemplate.

$if(supports_sql_mail)$
...
$endif$	
Finally, I also needed a section of my template which created all the various operators in the SQL Instance. Since there are 7 DBAs in my team I needed some sort of loop. Again, StringTemplate to the rescue:
$operators:{	
	IF EXISTS (SELECT name FROM msdb.dbo.sysoperators WHERE name = N'$it.name$') BEGIN  		
		EXECUTE msdb.dbo.sp_delete_operator @name = '$it.name$'	
	END
	
	print 'Creating operator: $it.name$';
	--create the operator
	EXECUTE msdb.dbo.sp_add_operator @name = '$it.name$', @enabled = 1, @email_address = '$it.emailaddress$', @netsend_address = '$it.netsendaddress$', @category_name = N'[Uncategorized]', @weekday_pager_start_time = 80000, @weekday_pager_end_time = 180000, @saturday_pager_start_time = 80000, @saturday_pager_end_time = 180000, @sunday_pager_start_time = 80000, @sunday_pager_end_time = 180000, @pager_days = 0	
	GO
		
	--notifications		
	EXECUTE msdb.dbo.sp_add_notification @alert_name = N'Full msdb log',  @operator_name = '$it.name$', @notification_method  = $notification_value$
	... YOU GET THE POINT!
	GO
}$
Breaking it down, we define a loop on Line 1. As we iterate over the array, the individual objects are referenced by the keyword it. The properties of each object are read by using dot notation. For example, when I want the operator’s name I use $it.name$.

So by now you have a basic understanding behind the power of StringTemplate. If you want to use StringTemplate in your application then here are the steps:

  1. Download the binaries (234 kb) from antlr.org.
  2. Add a reference in your project to the antl.runtime.dll and the StringTemplate.dll.
  3. Add a using statement for Antlr.StringTemplate.
  4. Write the code to load the template, and replace the variables.

 
Now it’s a simple matter of loading the template, substituting some variables and returning the output. Here is the code I used to build my deployment script:

if ((i.MajorVersion ?? 9 ) >= 9) {
	 template.SetAttribute("supports_sql_mail", true);
	 template.SetAttribute("notification_value", 5);
}
else {
	 template.SetAttribute("supports_sql_mail", true);
	 template.SetAttribute("notification_value", 4);
}

template.SetAttribute("smtp_server", smtpServer);

template.SetAttribute("mail_account_name", smtpServer + " Administrator");
template.SetAttribute("email_address", "dba@" + instanceName + ".com");
template.SetAttribute("delay_between_responses", delayBetweenResponses * 60);
template.SetAttribute("operators", operators);
return template.ToString();
To summarize, on line 1 we define a StringTemplate group. This is basically telling the StringTemplate engine where the templates are stored. Since I am using StringTemplate in web application I make a call to Server.MapPath to get the full directory path. On line 2, we tell StringTemplate that we are going to use the template named “SQLDeploymentScript”. Just to warn you, the filename on disk is actually named SQLDeploymentScript.st but we leave off the extension in our code. This is a convention that StringTemplate uses so just go along for ride. Next, on lines 4-18 we substitute the variables in the template. Finally we call template.ToString() to get the results.

So hopefully this article gave you a good idea of how powerful StringTemplate can be. You can use it to generate HTML, emails, code or whatever else you can dream up.



Required Reading – January 2010 Week 1

clock February 5, 2010 by author Michael Ceranski

I thought it may be helpful to others if I occasionally posted a list of must-read articles that I stumbled across during the week. Since, I am actively using twitter these days I see a lot of information float back and forth about MVC, jQuery, SQL Server and etcetera.  Enjoy!

Programming

Database

Other

Funny Tweets

  • @shanselman - I wonder if some people are *awesome* on Twitter, but when you speak to them in person, after that 141st char, you're like, "What a putz." 
  • @haacked @codinghorror besides. You know my immediate answer when someone asks me if MVC is successful. "http://stackoverflow.com bitch!"
  • @danecook - Its amazing how in this day & age u can tell how much a person truly cares about u by if they retweet your posts.
       - Retweeted by me and 100+ others :)
  • @SQLChicken Lmao! RT @SQLDumbass: Writing a DDL trigger. When anyone drops an index, I insert their name into the national sex offender database.


Making Your JavaScript Unobtrusive

clock February 3, 2010 by author Michael Ceranski

I was watching a video named "Mastering jQuery" on Tekpub a few days ago and I heard the term "Unobtrusive JavaScript". Basically unobtrusive JavaScript is a technique that emphasizes the separation of your functional layer from your presentation layer. In layman's terms this means that your JavaScript is NOT placed directly in your HTML. Instead it is placed in a separate external file. Hopefully, you are already doing this with your cascading style sheets. Why? So you can change the look and feel of your website without having to modify each page. The same principal applies to Unobtrusive JavaScript. Here is an example...

In the old days it was very common to add a control to your HTML and wire up the event directly on the controls. Although this works fine it does not give you flexibility in your design. If you have similar controls on other pages that call the same function you will have to modify each page if you change the method signature or rename the function.

<HTML>
   <HEAD>
	  <script type="text/javascript">
		function doTest() {
			alert( "Now that's obtrusive" );
		}
	  </script>
   </HEAD>
<BODY>
<input type="button" id="btnTest" onclick="doTest()" />
</BODY>
</HTML>
When adhering to the rules of unobtrusive JavaScript you would first and foremost take the script out of the head of the HTML page and place it in a separate file. This allows for code re-use and central management of your scripts. Secondly, you would not bind the onclick event directly from within the HTML. Instead, you bind the events programmatically. In jQuery this is done with the $(document).ready function
$(document).ready( function() {
	$("#btnTest").click( function() { 
		doTest() 
	});	
});	
Now that your JavaScript is isolated in a separate file and that your events are wired up from the script your HTML can be reduced to the bare minimum.
<HTML>
   <HEAD>
	  <script type="text/javascript" src="script.js"></script>
   </HEAD>
<BODY>
<input type="button" id="btnTest" />
</BODY>
</HTML>
This is just a simple example but it does a good job at illustrating the power behind adopting the unobtrusive JavaScript methodology. After all, with great tools like jQuery at our disposal there is really no reason why you should not kick your old school habits and start putting some separation between your functionality and presentation layer. 

If you are a .NET web developer, than you have probably witnessed change due to this methodology before. When we moved from classic ASP to ASP.NET we were all excited because it meant the end of spaghetti-code. The Web Form revolution was also supposed to allow teams to work better together. For example, a designer could work on the HTML while the developer independently wrote the code behind the controls. Although this was an improvement over classic ASP we still longed for a better paradigm. So along came MVC. We now have no excuses for not having a complete separation of our data layer, presentation layer and etcetera. So why not adhere to the same principals by making your JavaScript unobtrusive as well.



Adding a “Tweet This” Button To Your Blog Posts

clock February 2, 2010 by author Michael Ceranski

Twitter is a great tool for sharing information with others. As a blogger I will commonly send tweets to my followers when I post new content. The tweet message generally has a brief description along with the URL. However, not everyone who reads my blog, follows me on twitter. Therefore, I thought it would be nice to add a button to the bottom of each blog post which allows anyone to send a tweet about one of my articles. The format for updating a twitter status message by using the REST API is: http://twitter.com/home/?status=<message>

Simple enough! I can just add a button to my page and dynamically set the status variable in the query string with the article title and url, Right? Well not exactly, If you are familiar with twitter then you know that a tweet can not exceed 140 characters. Therefore a message containing the title and url of the article could easily go over the maximum length. The workaround for this is to shorten the url using bit.ly. If you are unfamiliar with bit.ly or the API then please see my previous post.

Since I am using BlogEngine.net, the main page of my site is customizable and allows me to modify the number of posts that are displayed. Typically I display between 5-10 posts at a time. For this reason, I immediately ruled out using an inline function to generate the shortened url on the fly. Mainly because each function call would require a separate round trip to the Bit.Ly server and it would drastically increase the load time for my website.

Therefore, I decided that I would create a new page named TweetIt.aspx which I would use as a redirect. So below each post I can add a new link to the TweetIt.aspx page which passes in a few variables. The variables are used to build the status message for the tweet. Here is an example of the formatted url:

http://www.somesite.com/TweetIt.aspx?url={0}&title={1}

In particular, if you are using BlogEngine.Net you add this button by modifying the PostView.ascx file in your theme directory to include the following HTML:

<a style="float:right" ref="nofollow" target="_blank" href="/TweetIt.aspx?url=<%=Server.UrlEncode(Post.AbsoluteLink.ToString()) %>&title=<%=Server.UrlEncode(Post.Title) %>">
<img src="/pics/tweet_this.png" alt="tweet this">
</a>

tweet_this (Here is the image I used, Right-click and "Save As...")

To break it down, when a request is made to the TweetIt.aspx page, The Page_Load event is fired. In the Page_Load event I verify the existence of the url and title request variables. If the variables are valid, then I do a simple security check to make sure that the url being shortened is from my domain. This prevents people from using my redirect page for other sites. Moving on, if the url is valid then I shorten it using the bit.ly service. The results from the bit.ly service are passed back as a JSON result so I parse them using regular expressions. Finally, I redirect the user to the twitter site with an updated status.

Below you will see the code for the TweetIt.aspx page. However, before using this code you will need to replace the constants at the top of the class:

<%@ Page Language="C#" %>

<script runat="server">	
	const string STATUS_SUFFIX = "by @your_twitter_name";
	const string BITLY_API_USERNAME = "<bit.ly username>";
	const string BITLY_API_KEY = "<bit.ly api key>";
	const string SITE_BASE_URL = "http://www.<your domain>.com";
	
	void Page_Load(object sender, EventArgs e) {
		string twitterUrlFormat = "http://twitter.com/home/?status={0}";

		//if you don't pass in the url then ignore the request
		if (String.IsNullOrEmpty(Request["url"])) {
			Response.Write("Please specify the url");
			Response.End();
		}

        if ( Server.HtmlEncode(Request["url"]).ToUpper().StartsWith( Server.HtmlEncode(SITE_BASE_URL).ToUpper() ) == false) {
            Response.Write("This service is for articles from " + SITE_BASE_URL + " only");
            Response.End();
        }

		string status = "";		
		
		try {
			string bitlyUrl = GetBitlyUrl(Request["url"]);			
			string title = Request["title"];			

            status = String.Format("{0}: {1} {2}", title, bitlyUrl, STATUS_SUFFIX);
			
			//if all the text will fit then show it all
			if( status.Length > 140 ) {
                //the title and url are over 140 so we will "shrink" the title down and exclude the suffix
                if ((title.Length + bitlyUrl.Length) > 140)
                {
                    //shrink the title
                    title = Request["title"].Substring(0, 140 - (bitlyUrl + "... ").Length);
                    status = title + bitlyUrl;
                }
                else
                {
                    //just set the title and author
                    status = title + bitlyUrl;
                }
			}
			
			string twitterUrl = String.Format(twitterUrlFormat, status);
			Response.Redirect( twitterUrl);
		}
		catch {
			//something went wrong!	
			Response.Write("Sorry, An Error Has Occured. Please Try Again Later");
		}		
	}
	
	private String GetBitlyUrl(String longUrl) {
		string apiUrl = String.Format("http://api.bit.ly/shorten?version=2.0.1&longUrl={0}&login={1}&apiKey={2}",
												  longUrl,
												  BITLY_API_USERNAME,
												  BITLY_API_KEY);
		string shortUrl = "";		
		System.Net.HttpWebRequest request = System.Net.WebRequest.Create(apiUrl) as System.Net.HttpWebRequest;		
		
		using (System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse) {
			System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());
			String jsonResults = reader.ReadToEnd();
			string pattern = "(?<shortUrl>http://bit.ly/[0-9a-zA-Z]*)";
			System.Text.RegularExpressions.Match m = 
				System.Text.RegularExpressions.Regex.Match(jsonResults, pattern, RegexOptions.IgnoreCase);
			if (m.Success == true) {
				shortUrl = m.Groups["shortUrl"].Value;
			}
		}
		return shortUrl;
	}
</script>


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 shorten method 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!



About the author

My name is Michael Ceranski. I am an IT Professional from Buffalo NY. I have been writing code for over 10 years starting with Borland Delphi and later migrating to the .NET stack. 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