I had some free time during the holidays and saw at the MIX09 website that they have a contest entitled MIX09 10K Challenge where they ask participant to create a web application that is either using Microsoft® Silverlight™ or Windows Presentation Foundation, as a XAML Browser Application running in Partial Trust or as a ClickOnce application in 10 kilobytes or less. I decided to take a stab at it and this is what I've comed up with
SilverCalendar: A Silverlight Pregancy Calendar

You can see the app live here http://2009.visitmix.com/MIXtify/TenKDisplay.aspx?SubmissionID=0051
Dont forget to vote when you're there :P LOL
My primary motivation when I built the app is the idea of having something that is going to be useful and at the same time fun to build. My wife is currently 34 weeks pregnant and it made me think that a pregnancy calendar would be q great application to do since it relates to me and my current day to day life. I love pregnancy calendars because it gives you a good daily insight on the progress of your baby and what you might expected as you go along in your daily life as a soon to be parent.
The application that i built is using Microsoft Silverlight 2 with a backend WCF web service. You can find the pregnancy calendar web service here. I wasn't able to add any animations to the application because I decided to concentrate in adding functionality to app rather than the eye candy' With that said, I'll be posting the non-10K application this week.
Be sure to comeback on this blog in the coming weeks because I'll be publishing the source code to both project soon together with a 11 part tutorial and screencast walkthrough that i have prepared to show how to to build an application using .NET 3.5, WCF, WPF and Silverlight.
A week ago, I started a contest at DevPinoy.org about writing a Bible application and a few people have asked me if I tried my own challenge. I actually did took the challenge and built my own Bible application. I wasn't able to post it as soon as I wanted to do it due to time constrainst. What I built is a WPF Bible application but still needs some polishing to truely call it a "WPF app".
Now let's begin the tour of the WPF app that I built.
The screen below shows the main interface for the program. The first tab is the browsing tab that allows the user to select a Book and a Chapter they want and displays the contents of your selection on the list below the Comboxes

The bold letters on the upper right side of the list tells you what book and chapter you are currently reading

The second tab is the search tab. This tab has a textbox that allows you to enter your search parameters

It allows you to search by keyword\s

By book and chapter

or by specifying the Book, Chapter and Verse

There are a few more things that I wanted to add this app but wasn't able to do so like building a TreeView similar to CryptoKnight's implementation that allows you to see the Document Map and also a matching word highlighting on the search screen would be a great addition too. Another thing that could be improve is refactoring the code and making the service layer a little bit more generic. I wanted to refactor it a bit more after I finished it but never had a chance to do so. I'll leave it as is for now and hope to update it in the future.
There's a lot more improvements I could think of but I'll leave it for you guys to check and comment on what I could do with this app to improve it. Maybe we could make it an OpenSource application someday.
Anyhow, you can get the source code for this project here. KeithRull.NBible.zip (1.84 MB)
Thanks to everyone who tried the challenge. I promise to do more of these type of contest in the future.
Again, Thank you, God Bless and Mabuhay ka Filipino Developer!
In part 3 of this 5 part series I am going to show you how to make a Master-Detail View in ASP.NET. I you weren't able to see the two previous post you can check them out here:
This post is a continuation of what we started in the two previous post wherein i show you how to consume a webservice ins ASP.NET and present the values returned by the service to the user in a much more meaninful way.
To start off with this post lets look at how the application from our last article look-liked:

As you can see, we have a textbox that accepts a user-input asking for the symbol to lookup in our webservice, a button that triggers that query event and a DetailsView that displays the returned resultset. This works great.
But what if I have a list of symbols that I want the user to see information regarding them? The answer is to show them in a master-detail view so that the user can get a clearer view of the information on each symbol.
To start with this demo lets begin by deleting everything that we have on the page. Yup! we are starting from scratch so that we can get a clearer picture on how we can build a master-detail view screen. Once everything is cleared on the page let's begin by adding a DataList control on our page with a Label control inside its ItemTemplate: <html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Keith Rull's Consuming Web Services Sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DataList ID="stockDataList"
runat="server">
<ItemTemplate>
<asp:Label ID="quoteLabel"
runat="server"
Text='<%# Container.DataItem %>'>
</asp:Label>
</ItemTemplate>
<SeparatorTemplate>
<br />
</SeparatorTemplate>
</asp:DataList>
</div>
</form>
</body>
</html>
The first thing that you would notice on the code above is that we have assigned a value to the Text property of our Label control. This value signifies that we are binding the Container.DataItem value to the Text property. This DataItem will come from the value that we are going to set in the codebehind file for this page which in this case is just going to be a List<string>.
Next, lets go the codebehind file and create the Page_Load event for our page: public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//create a list of stock symbols
List<string> listOfSymbols = new List<string>();
//add some symbols to our list
listOfSymbols.Add("MSFT");
listOfSymbols.Add("GOOG");
listOfSymbols.Add("CSCO");
listOfSymbols.Add("MER");
listOfSymbols.Add("F");
//bind the list<string> to our datalist
stockDataList.DataSource = listOfSymbols;
stockDataList.DataBind();
}
}
}
All i did in the code above is create a list of strings, add some values to it and assign and bind that colletion of strings to our DataList. Running the application now would give us this result:

Nothing really impressive yet. Now let's add the cool part wherein we call a web service and show the information for each stock symbol.
To do that we need to add another DataList inside the ItemTemplate of our first DataList. The second DataList will serve as the list that shows the imformation about the specified execution symbol. We also need to add an event that is triggered each time a ListItem is binded to a data. Below is our modified HTML page: <html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Keith Rull's Consuming Web Services Sample</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DataList ID="stockDataList"
runat="server"
OnItemDataBound="stockDataList_ItemDataBound">
<ItemTemplate>
<asp:Label ID="quoteLabel"
runat="server"
Text='<%# Container.DataItem %>'>
</asp:Label>
<asp:DataList ID="stockInformationDataList"
runat="server">
<ItemTemplate>
<table cellpadding="1"
cellspacing="1"
border="0"
width="600px">
<tr>
<td><b>Last:</b> <%# Eval("Last") %></td>
<td><b>Date:</b> <%# Eval("Date") %></td>
<td><b>Time:</b> <%# Eval("Time") %></td>
<td><b>Change:</b> <%# Eval("Change") %></td>
</tr>
<tr>
<td><b>Open:</b> <%# Eval("Open") %></td>
<td><b>Low:</b> <%# Eval("Low") %></td>
<td><b>High:</b> <%# Eval("High") %></td>
<td><b>Volume:</b> <%# Eval("Volume") %></td>
</tr>
<tr>
<td><b>MktCap:</b> <%# Eval("MktCap") %></td>
<td><b>PrvClose:</b> <%# Eval("PreviousClose") %></td>
<td><b>PerChange:</b> <%# Eval("PercentageChange") %></td>
<td><b>AnnRange:</b> <%# Eval("AnnRange") %></td>
</tr>
<tr>
<td><b>Earns:</b> <%# Eval("Earns") %></td>
<td><b>P-E:</b> <%# Eval("P-E") %></td>
<td> </td>
<td> </td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
</ItemTemplate>
<SeparatorTemplate>
<br />
</SeparatorTemplate>
</asp:DataList>
</div>
</form>
</body>
</html>
I modified the ItemTemplate of our second DataList () and added an html table to hold the values that the web service returns. This way the view that we are presenting is much more readable.
Next stop is looking at the code behind where all these magic is going to be wired. All the work for the detail view will happen on the stockDataList_ItemDataBound event and no further modification to our Page_Load event is needed. Let me show you the code for that event before I start explaining every bits and pieces of that code: protected void stockDataList_ItemDataBound(object sender, DataListItemEventArgs e)
{
//check whether the current listitem is an acceptable ListItemType
if (e.Item.ItemType == ListItemType.Item
|| e.Item.ItemType == ListItemType.AlternatingItem)
{
//get the binded symbol
string symbol = e.Item.DataItem.ToString();
//find the datalist in our itemtemplate
Control foundControl = e.Item.FindControl("stockInformationDataList");
//cast the control to a DataList
DataList stockInformationDataList = (DataList)foundControl;
//get the stock information for the specified symbol
DataSet stockInformationDataSet = StockQuoteHelper.GetStockQuoteDataSet(symbol);
//bind the dataset to our datalist
stockInformationDataList.DataSource = stockInformationDataSet;
stockInformationDataList.DataBind();
}
}
What we are doing on this blog of code is we are checking if the ItemType of the current item being binded-to is either a ListItemType.Item or ListItemType.AlternatingItem. If it passes this criteria we then read the DataItem that was binded to this ListItem which in this case is our executionSymbol. The next step is to find our stockInformationDataList control and assign the stockInformationDataSet to it. The stockInformationDataSet contains the values that is retrieved from our stock web service by passing the exection symbol to our StockQuoteHelper.GetStockQuoteDataSet method.
Running our completed application will result to this screen:

And that's it! We've accomplished a master-detail view in ASP.NET. Pretty easy right? I hope you learned something from this tutorial. Next up we'll update this project and implement some Asynchronous Web Service calls via ASP.NET AJAX and show you some fun ways to present a master-detail view in a much more interesting way.
As always, source code is available for download here: KeithRull.ConsumingWebServices.Part3.zip (6.9 KB)
As a side note, many thanks to John A. Miller from Trofholz Technologies, Inc. for reminding me about this series. I totally forgot about it already after being assigned to a large project the past few months. Thanks John!
Whew! It's been a long time since the last time that we had a cool contest here at DevPinoy and I think it's about time to start giving away cool stuff those developers who are willing to take the challenge. This time around I've decided to make the contest a little bit more interesting than the usual...
Ok, enough with the teaser and on with the contest!
Our challenge this months is to build a Windows-based Bible application in C#, VB.NET or Java. The idea is to build an application that reads from a Bible database and displays testaments, books, chapters and verses based on these simple requirements:
- The user should be able to search for books base on a selected Testament (Old and New).
- The user should be able to see the contents of each Book
- The user should be able to search the contents of the Bible based on different search criterias like "Luke", "Genesis 1", "John 3:16", "love", "Abraham" and the application should be able to return the matching results.
- The user should be able to jump from one book to another.
- The user should be able to jump from one chapter to another.
That is all that is required for the app and it's up to you to add additional functionalities if you like. You can find the database for this challenge here: http://devpinoy.org/media/p/30310.aspx
Simple right? Here's the caveat! You are not allowed to use any third-party library in your solution (Yup! No NHibernate or Hibernate for you buddy!). Everything should be straight up what your language of choice supports. The only acceptable third-party library is a testing and mocking framework as part of your test harness but this is not required.
So what's the prize? Glad you asked! We are going to chose 2 winners for this contest and they will be able to chose 1 of these lovely prizes courtesy of JetBrains: IntelliJ IDEA, ReSharper, Team City(one Build Agent), dotTrace and JetBrain's forthcoming Ruby IDE(they don't have a name for it yet).
So who is entitled to join this contest? This contest is open to all Filipino developers who are willing to take the challenge regardless of location and ofcourse you should be a member of the DevPinoy website.
So how can I participate? All you need to do is finish the application and send it to keith.rull@gmail.com together with the source code before October 26, 2008 PST. Please include "DevPinoy October 2008 Code Challenge" on the subject line of your email when submitting your code. Please also include a screenshot of your application and your fullname in your submission email.. All submissions would be posted on October 27, 2008 PST in my devpinoy blog so the community can view your work. The announcement of winners will take place on October 29, 2008 PST.
Ready for the challenge? Stop reading, start typing and send your solution as quick as you can!
In part 1 of this series i showed you how to specify the voice, gender, rate and volume of the our SpeechSynthesizer object. This time i'm going to show you how to use predefined Voices in your machine and utilize it as hints to your SpeechSynthesizer object.
The first thing that I did to our sample project is change the UI since we would not need the Gender and Age combo box in our form. The result is a UI like this:

Next, we need to figure out a way to extract the names of the installed voices in our machine. To this we need to use the SpeechSynthesizer.GetInstalledVoices() method. This method, when invoked returns a readonly collection of TTS(text-to-speech) voices also known as InstalledVoice objects that are readily available in your machine. The InstalledVoice object contains a property called VoiceInfo which represents the voice information about that TTS voice. To begin our project we need to get all the VoiceInfo objects on each and every InstalledVoice. Below is a code snippet showing how we can accomplish this task: //create a new speechsynthesizer object
static SpeechSynthesizer speechSynth = new SpeechSynthesizer(); /// <summary>
/// a method that returns all the currently installed voice
/// info objects in the machine
/// </summary>
/// <returns>a list of VoiceInfo objects</returns>
private static List<VoiceInfo> GetInstalledVoices()
{
//get the current cultureinfo
CultureInfo currentCulture = CultureInfo.CurrentCulture;
//use linq to select each voiceinfo object from the intalledvoices collection
var listOfVoiceInfo = from voice
in speechSynth.GetInstalledVoices(currentCulture)
select voice.VoiceInfo;
//return the selected voiceinfo objects
return listOfVoiceInfo.ToList<VoiceInfo>();
}
Next, we need to bind the resulting list to our voiceComboBox. private void MainForm_Load(object sender, EventArgs e)
{
BindData();
}
/// <summary>
/// Bind the voices to our combobox
/// </summary>
private void BindData()
{
//get the installed voices
List<VoiceInfo> listOfVoices = GetInstalledVoices();
//bind the list to our combobox
voicesComboBox.DataSource = listOfVoices;
voicesComboBox.DisplayMember = "Name";
}
And finally we need to create the logic inside our button click event to initiate our SpeechSynthesizer private void speakUpButton_Click(object sender, EventArgs e)
{
//get the values specified in our form
string messageToSay = wordsTextBox.Text;
int selectedVolume = volumeTrackBar.Value;
int selectedVoiceRate = voiceRateTrackBar.Value;
//get the selected voice info
VoiceInfo vi = voicesComboBox.SelectedItem as VoiceInfo;
//specify the volume for our SpeechSynthesizer object
speechSynth.Volume = selectedVolume;
//specify the rate for our SpeechSynthesizer object
speechSynth.Rate = selectedVoiceRate;
//specify the voice info specifying the voice to use
speechSynth.SelectVoice(vi.Name);
//say the message
speechSynth.SpeakAsync(messageToSay);
}
And we are done ;) Running the application would show as all the installed TTS voice in our machine. One thing to note is that this list is machine dependent and different machines might contain different voices.

Clicking the "Speak!" button should echo our selected voice.
Next time I'll show you how to export the resulting speech to a wave file. HTH
Ever wondered how google would look like if it was on terminal mode (a la *Nix shell)? Then checkout Goosh! Goosh is a project that Stefhan Grothkopp started. The application behaves similar to a unix-shell wherein you type commands and it returns results based on your request (which in this case is web search results). I personally love the idea and have been using the tool since i found it.

This reminds me of the days when terminals were hip and cool. I do wish that the background was black though and the fonts converted to green to give more terminal-like feel to it but either way its two thumbs up for me ;)
One of the cool things that came out with .NET 3.x is the addition of System.Speech library. This library is a collection of classes that enables you to do alot of speech related things like speech recognition and text-to-speech conversion. It's a handful to talk about so i suggest you read up MSDN to learn more about this library[1][2][3].
The app I'm going to show you today is a basic application that shows how to utilize the SpeechSynthesizer class that is located inside the System.Speech.Synthesis namespace.
To start this demo lets add a reference to the System.Speech namespace to our project. You can do this by doing a right-click on References > Add Reference and selecting System.Speech from the list.

Once added we can now beging utilizing this library by adding a using directive pointing to the specific System.Speech namepace that we want to utilize. For this demo we will use System.Speech.Synthesis

Next, we need to create a new SpeechSynthesizer object. SpeechSynthesizer is class that enables you to convert text-to-speech. The class also has several properties and methods that you can use customize the voice information on your speech synthesizer.

Next is the fun part which is making our application say some words. The cool thing about SpeechSynthersizer is that all you need to do to make your application speak is call the SpeechSynthesizer.Speak() method and your done ;)

Run our application and once started you should here the words "Hello, World" spoken by your machine. Pretty cool huh?!
What we did was a simple demonstration on how to make our apps speak with a few lines using SpeechSynthesizer. But what about customizing the voice? Fear not! I created a sample application that will show you how you can customize the synthesizer by specifying the rate, volume, gender and age of the emitted sound. Below is the screenshot showing the UI for the application

And here is the code snippet with comments detailing how to customize our SpeechSynthesizer object. using System;
using System.Windows.Forms;
using System.Speech.Synthesis;
namespace KeithRull.TalkToMeGoose
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
//create a new speechsynthesizer object
SpeechSynthesizer speechSynth = new SpeechSynthesizer();
private void speakUpButton_Click(object sender, EventArgs e)
{
//get the values specified in our form
string messageToSay = wordsTextBox.Text;
int selectedVolume = volumeTrackBar.Value;
int selectedVoiceRate = voiceRateTrackBar.Value;
string selectedGender = genderComboBox.SelectedItem.ToString();
string selectedAge = ageComboBox.SelectedValue.ToString();
Type voiceGenderType = typeof(VoiceGender);
Type voiceAgeType = typeof(VoiceAge);
//convert the selectedGender value to a VoiceGender
VoiceGender gender = (VoiceGender)Enum.Parse(voiceGenderType, selectedGender);
//convert the selectedAge value to a VoiceAge
VoiceAge age = (VoiceAge)Enum.Parse(voiceAgeType, selectedAge);
//specify the volume for our SpeechSynthesizer object
speechSynth.Volume = selectedVolume;
//specify the rate for our SpeechSynthesizer object
speechSynth.Rate = selectedVoiceRate;
//specify the voice info by using hints regarding the gender and age
speechSynth.SelectVoiceByHints(gender, age);
//say the message
speechSynth.SpeakAsync(messageToSay);
}
private void MainForm_Load(object sender, EventArgs e)
{
speechSynth.Speak("Hello, World!");
}
/// <summary>
/// Bind the enums to our combobox
/// </summary>
private void BindData()
{
BindAgeToComboBox();
BindGenderToComboBox();
}
/// <summary>
/// bind the VoiceGender enum to our combobox
/// </summary>
private void BindGenderToComboBox()
{
//convert the enumeration to a string array
Array voiceGenderArray = Enum.GetValues(typeof(VoiceGender));
//bind the array to the datasource of our combobox
genderComboBox.DataSource = voiceGenderArray;
}
/// <summary>
/// Bind the VoiceAge enum to our combobox
/// </summary>
private void BindAgeToComboBox()
{
//convert the enumeration to a string array
Array voiceAgeArray = Enum.GetValues(typeof(VoiceAge));
//bind the array to the datasource of our combobox
ageComboBox.DataSource = voiceAgeArray;
}
}
};
As always, you can download the source code for this project here: KeithRull.TalkToMeGoose1.zip (27.46 KB)
I hope I was able to show you how simple it is to add text to speech functionality to your .NET application. Next time I'll show you how to use predefined voices. Till next time ;)

Would you agree? ;)
In part 3 of our series "Ten Questions - Filipino Developer Edition", I was able to talk to Melvin Dave Vivas, founder of PinoyJUG, developer, technopreneur and part-time fashion photojounalist(Heheh! I bet he wants me to include this on his intro :P).
Read more about this interview here.
It's funny, just after posting this post in response to an article that N@rds posted that I realized that I have been preaching about extension methods and his problem was a great example on when to make use of this excellent feature.
I wrote an article about this topic a few months ago but I wanted to explain it a little further in this article by showing real-world scenarios on when and how to use this feature.
So what does Extension Method mean? According to MSDN:
"Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type."
Now that we have that settled lets look at a good scenario that depicts a great time when to use an Extension Method.

Me and my wife will be at the Code Camp in Fullerton tommorow and we are excited. Code Camp is a great time to get together, learn new things about technology and network with people with the same mindset about technology and that is passion for learning and enriching knowledged. We are driving tonight to Fullerton so that we can be early tommorow.
There are already a few sessions that I am eyeing to go to. One of them is the session of John Bowen regarding WPF DataBinding and WPF controls. I met John Bowen 3 years ago in the .NET Rocks roadshow bus. I think this session is going to be awesome. I've been playing with alot of WPF lately and I'm interested in seeing and learning cool things about this technology.
Another session I'd love to see is the topic "Branching and Merging Guidance for VSTS 2008 and Team Foundation Server" presented by Mickey Williams. I haven't done anything with VSTS before but I know its going to be a great primer for me because merging and branching is one of the things that happens alot when you are in a team development environment.
Oh boy! This is going to be a great Code Camp. Time to go home and get ready for this event. See you there!
I encountered a problem today with one of my projects. The problem was about a third-party application choking when it encounters files greater than 20MB. I have a Windows Service that creates PDFs of KPIs for around 150 users and each of the file that I generate is around 25MB each. I can compress the PDF file to lower resolution format but the management decided that we shouldn't trade quality over speed so I was stuck thinking of a different solution.
Then it came to me that I can zip the files so that I get a smaller file.
I started evaluating C# zip libraries and ended up choosing #ZipLib from the creators of SharpDevelop because of it's simplicity and robustness. The only thing I didn't like was the fact that I wasn't find a great documentation about the library. I ended up fiddling with it. It wasn't hard but you need to play with it alot to understand whats happening in the background.
Ok, now lets start by identifying what we need to create a zip file with SharpZipLib. The first thing that you need to do is download the binaries from the #ZipLib website and reference that DLL in your project.

Now that is done you need to add the ICSharpCode.SharpZipLib namespace in you source file to be able to start creating zip files using the #ZipLib library.

To start creating a zip file, all you need to do is to initialize a ZipFile object.
//initialize the file so that it can accept updates
ZipFile z = ZipFile.Create(filename);
The code above creates a new zip file with the specified filename. Next we need to call the BeginUpdate method of the ZipFile object to tell it that we are going to do some modifications to that file.
//initialize the file so that it can accept updates
z.BeginUpdate();
At this stage we can now add files to our zip file.
//add your file e.g "c:\reports\gummywhammyyummy.pdf"
z.Add(<Your file to add including it's path>);
Once you are done you need to commit your changes and close the file.
//commit the update once we are done
z.CommitUpdate();
//close the file
z.Close();
Done. Now you have created your first zip file using #ZipLib. Neat! Below is the complete code listing of what we did above
/// <summary>
/// A method that creates a zip file
/// </summary>
/// <param name="zipFileStoragePath">the storage location</param>
/// <param name="zipFileName">the zip file name</param>
/// <param name="fileToCompress">the file to compress</param>
private void CreateZipFile(string zipFileStoragePath
, string zipFileName
, string fileToCompress)
{
//create our zip file
ZipFile z = ZipFile.Create(zipFileStoragePath + zipFileName);
//initialize the file so that it can accept updates
z.BeginUpdate();
//add the file to the zip file
z.Add(fileToCompress);
//commit the update once we are done
z.CommitUpdate();
//close the file
z.Close();
}
But what if you want to add a directory to your zip file? The ZipFile object provides a method called AddDirectory() that accepts a parameter directoryName. The problem with this method is that it doesn't add the files inside the specified directory but instead just creates a directory inside the zip file. To make this work, you need to get the files inside that directory by looping thru all objects in that directory and adding them one at a time. I was able to accomplish this task by creating a recursive function that drills through the whole directory structure of the folder you want to zip. Below is a snippet of the function.
/// <summary>
/// Creates a zip file
/// </summary>
/// <param name="zipFileStoragePath">where to store the zip file</param>
/// <param name="zipFileName">the zip file filename</param>
/// <param name="fileToZip">the file to zip</param>
/// <returns>indicates whether the file was created successfully</returns>
private bool CreateZipFile(string zipFileStoragePath
, string zipFileName
, FileInfo fileToZip)
{
return CreateZipFile( zipFileStoragePath
, zipFileName
, (FileSystemInfo)fileToZip);
}
/// <summary>
/// Creates a zip file
/// </summary>
/// <param name="zipFileStoragePath">where to store the zip file</param>
/// <param name="zipFileName">the zip file filename</param>
/// <param name="directoryToZip">the directory to zip</param>
/// <returns>indicates whether the file was created successfully</returns>
private bool CreateZipFile(string zipFileStoragePath
, string zipFileName
, DirectoryInfo directoryToZip)
{
return CreateZipFile( zipFileStoragePath
, zipFileName
, (FileSystemInfo)directoryToZip);
}
/// <summary>
/// Creates a zip file
/// </summary>
/// <param name="zipFileStoragePath">where to store the zip file</param>
/// <param name="zipFileName">the zip file filename</param>
/// <param name="fileSystemInfoToZip">the directory/file to zip</param>
/// <returns>indicates whether the file was created successfully</returns>
private bool CreateZipFile(string zipFileStoragePath
, string zipFileName
, FileSystemInfo fileSystemInfoToZip)
{
return CreateZipFile( zipFileStoragePath
, zipFileName
, new FileSystemInfo[]
{
fileSystemInfoToZip
});
}
/// <summary>
/// A function that creates a zip file
/// </summary>
/// <param name="zipFileStoragePath">location where the file should be created</param>
/// <param name="zipFileName">the filename of the zip file</param>
/// <param name="fileSystemInfosToZip">an array of filesysteminfos that needs to be added to the file</param>
/// <returns>a bool value that indicates whether the file was created</returns>
private bool CreateZipFile(string zipFileStoragePath
, string zipFileName
, FileSystemInfo[] fileSystemInfosToZip)
{
// a bool variable that says whether or not the file was created
bool isCreated = false;
try
{
//create our zip file
ZipFile z = ZipFile.Create(zipFileStoragePath + zipFileName);
//initialize the file so that it can accept updates
z.BeginUpdate();
//get all the files and directory to zip
GetFilesToZip(fileSystemInfosToZip, z);
//commit the update once we are done
z.CommitUpdate();
//close the file
z.Close();
//success!
isCreated = true;
}
catch (Exception ex)
{
//failed
isCreated = false;
//lets throw our error
throw ex;
}
//return the creation status
return isCreated;
}
/// <summary>
/// Iterate thru all the filesysteminfo objects and add it to our zip file
/// </summary>
/// <param name="fileSystemInfosToZip">a collection of files/directores</param>
/// <param name="z">our existing ZipFile object</param>
private void GetFilesToZip(FileSystemInfo[] fileSystemInfosToZip, ZipFile z)
{
//check whether the objects are null
if (fileSystemInfosToZip != null && z != null)
{
//iterate thru all the filesystem info objects
foreach (FileSystemInfo fi in fileSystemInfosToZip)
{
//check if it is a directory
if (fi is DirectoryInfo)
{
DirectoryInfo di = (DirectoryInfo)fi;
//add the directory
z.AddDirectory(di.FullName);
//drill thru the directory to get all
//the files and folders inside it.
GetFilesToZip(di.GetFileSystemInfos(), z);
}
else
{
//add it
z.Add(fi.FullName);
}
}
}
}
A sample usage of this function would be like this:
//sample usage for zipping a file
private void zipItButton_Click(object sender, EventArgs e)
{
string fileToZip = fileToZipTextBox.Text;
string zipFilename = Guid.NewGuid() + ".zip";
//zip a file
bool isCreated = CreateZipFile(
CONST_ZIP_FILE_STORAGE
, zipFilename
, new FileInfo(fileToZip) );
if (isCreated) {
MessageBox.Show(zipFilename);
}
else {
MessageBox.Show("Failed");
}
}
//sample usage for zipping a directory
private void zipFolderButton_Click(object sender, EventArgs e)
{
string directoryToZip = whereToZipTextBox.Text;
string zipFilename = Guid.NewGuid() + ".zip";
//zip a directory
bool isCreated = CreateZipFile(
CONST_ZIP_FILE_STORAGE
, zipFilename
, new DirectoryInfo(directoryToZip) );
if (isCreated){
MessageBox.Show("Created " + zipFilename);
}
else{
MessageBox.Show("Failed");
}
}
And that's it. I hope i was able to shed light on you can create zip files in few easy steps with C#. If you are interested you can checkout this sample application that I built to demonstrate how to create zip files with C# and SharpZipLib.

Download the source code here. KeithRull.CreatingZipFiles.zip (19.15 KB)
Yesterday I wrote an article explaning what var means in .NET 3.x. Today lets talk about Anonymous Types.
Anonymous Types as describe by the C# 3.0 specification are tuple types automatically inferred and created from object initializers. Anonymous Types allows the new operator to be used with an anonymous object initializer to create an object at compile time. The format for an anonymous type declaration is a follows
var v = new { p1 = e1 , p2 = e2 , ... px = ex }
where v is the var variable, px denotes the property name and ex is equaivalent value.
Enough with the theory and lets look at some actual code. Lets assume that I have a class called Person with the following properties:
public class Person
{
private string _name;
private int _age;
private bool _believesInJesus;
public string Name
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
public bool BelievesInJesus
{
get { return _believesInJesus; }
set { _believesInJesus = value; }
}
}
Let's say that I want to create an Anonymous Type that has a similar structure from what we have above, all I need to do is make this call:
var human = new { Name = "Keith", Age = 25, BelievesInJesus = true };
What happens in compile time is that the .NET compiler generates a class that represents the structure of your Anonymous Type.
public class __Anonymous1
{
private string _name;
private int _age;
private bool _believesInJesus;
public string Name { get { return _name; } set { _name = value; } }
public int Age { get { return _age; } set { _age = value; } }
public bool BelievesInJesus { get { return _believesInJesus; } set { _believesInJesus = value; } }
}
It's an "Anonymous Type" because it a nameless class, it's generated by the compiler for you and it directly inherits from object.
To prove this let's look at this example:
class Program
{
static void Main(string[] args)
{
var person = new { Name = "Keith", Age = 25, BelievesInJesus = true };
Console.WriteLine(person.Name);
Console.WriteLine(person.GetType());
Console.ReadLine();
}
}
Hovering at the person variable would give us some information about it's type:

The code above will have this output:

As you can see, the compiler created an Anonymous Type Called <>f__AnonymousType0`3. One thing to note about Anonymous Types is that the compiler is smart enough to figure out if an Anonynous Type has already been declared that meets the schema requirement of your new Anonymous Type. class Program
{
static void Main(string[] args)
{
var person1 = new { Name = "Keith", Age = 25, BelievesInJesus = true };
var person2 = new { Name = "Charissa", Age = 23, BelievesInJesus = true };
var person3 = new { Name = "Peter", Age = 23};
Console.WriteLine(person1.Name);
Console.WriteLine(person1.GetType());
Console.WriteLine(person2.Name);
Console.WriteLine(person2.GetType());
Console.WriteLine(person3.Name);
Console.WriteLine(person3.GetType());
Console.ReadLine();
}
}
The result would be:

I hope I was able to show you what Anonymous Types are in C#. Next up is Extension Methods.
Finally i'm back after a month of crazyness due to my webhost not performing up to its promise of 99.9% uptime.
Enough with the rant and on with the article, today i'm going to talk about how to list databases in a SQL Server by just using T-SQL and then showing you how to truncate the logs on those databases in different ways.
First, let's look at the 5 different approaches that you can use to list down databases in SQL Server by just using plain old T-SQL.
The stored procedure approach ( sp_databases, sp_helpdb ) :
USE master;
-- Lists databases that either reside in an instance of the SQL Server
-- 2005 Database Engine or are accessible through a database gateway.
EXEC sp_databases
-- Reports information about a specified database or all databases.
EXEC sp_helpdb
The sys tables approach ( sys.databases, sys.sysdatabases ):
USE master;
-- [SQL Server 2000/2005] Contains one row for each database in an instance of
-- Microsoft SQL Server 2005. When SQL Server is first installed, sysdatabases
-- contains entries for the master, model, msdb, and tempdb databases.
SELECT NAME FROM sysdatabases
-- [SQL Server 2005] Contains one row per database in the instance of Microsoft SQL Server.
SELECT NAME FROM sys.sysdatabases
The using the undocumented stored procedure sp_MsForEachDatabase approach
USE master;
-- Undocumented SQL Server stored procedure
EXEC sp_msForEachDB 'PRINT ''?''';
Simple huh? Now that we know how to list databases let's go back to the problem of truncating all of them in one query (in fact it's just one line!). Some people would suggest writing cursors that would loop thru all the rows returned by our sysdatabases query to do this task. Their solution might be similar to the one listed below:
[SOLUTION 1]
USE master;
DECLARE
DBNames CURSOR
FOR
SELECT
NAME
FROM sysdatabases
OPEN DBNames
DECLARE @Name varchar(50)
FETCH NEXT FROM DBNames
INTO @Name
WHILE (@@FETCH_STATUS <> -1)
BEGIN
DBCC SHRINKDATABASE( @Name , 0)
FETCH NEXT FROM DBNames
INTO @Name
END
CLOSE DBNames
DEALLOCATE DBNames
Others would suggest a more primitive approach which is building a simple query first that would list the names of the database appended with the DBCC SHRINKDATABASE command:
[SOLUTION 2]
USE master;
SELECT
'DBCC SHRINKDATABASE(' + NAME + ', 0)'
FROM sysdatabases
Then they would change the output option of the query into "Results to Text", copy the result to a new query window and execute the query from there. Pretty primitive. Alot of steps. Same results.
My suggested solution is using the sp_MSForEachDatabase procedure in conjunction with the DBCC SHRINKDATABASE function. This would result into a 1 line query. Less code with less steps to do that creates the same results.
[MY RECOMMENDED SOLUTION]
USE master;
-- truncates all the logs of all database in the server
EXEC sp_msForEachDB 'DBCC SHRINKDATABASE( ''?'', 0)'
Simple and straight to the point.
I hope you learned something from our article today. You can also do this programmatically by using C# and VB.NET. I wrote two articles about that topic here and here. Interested in truncating tables using sp_MsForEachTable? You can checkout this post.
Thanks!
I was working on a .NET application that integrates with Gravatar today because I needed a quickway to fetch someone's photo based on their email address. One requirement when doing this type of integration with Gravatar is that the email should be encrypted into an MD5 hash. Luckily, .NET already has a library that can do this for me by just calling a few methods:
[C# Version]
public static string ToMD5(string stringToConvert) { //create an instance of the MD5CryptoServiceProvider MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
//convert our string into byte array byte[] byteArray = Encoding.UTF8.GetBytes(stringToConvert);
//get the hashed values created by our MD5CryptoServiceProvider byte[] hashedByteArray = md5Provider.ComputeHash(byteArray);
//create a StringBuilder object StringBuilder stringBuilder = new StringBuilder();
//loop to each each byte foreach (byte b in hashedByteArray) { //append it to our StringBuilder stringBuilder.Append(b.ToString("x2").ToLower()); }
//return the hashed value return stringBuilder.ToString(); }
[VB.NET Version]
Public Shared Function ToMD5(ByVal stringToConvert As String) As String 'create an instance of the MD5CryptoServiceProvider Dim md5Provider As New MD5CryptoServiceProvider()
'convert our string into byte array Dim byteArray As Byte() = Encoding.UTF8.GetBytes(stringToConvert)
'get the hashed values created by our MD5CryptoServiceProvider Dim hashedByteArray As Byte() = md5Provider.ComputeHash(byteArray)
'create a StringBuilder object Dim stringBuilder As New StringBuilder()
'loop to each each byte For Each b As Byte In hashedByteArray 'append it to our StringBuilder stringBuilder.Append(b.ToString("x2").ToLower()) Next
'return the hashed value Return stringBuilder.ToString() End Function
Now all I need to do is get the result of my function and pass it to the avatar page in the Gravatar website and it should return me my Gravatar image.
[C# Version]
string gravatarUrl = "http://www.gravatar.com/avatar.php?gravatar_id"; string gravatarID = Utilities.Strings.ToMD5("keith.rull@gmail.com"); Image1.ImageUrl = String.Format("{0}={1}",gravatarUrl,gravatarID);
[VB.NET Version]
Dim gravatarUrl As String = "http://www.gravatar.com/avatar.php?gravatar_id" Dim gravatarID As String = Utilities.Strings.ToMD5("keith.rull@gmail.com") Image1.ImageUrl = [String].Format("{0}={1}", gravatarUrl, gravatarID)
http://www.gravatar.com/avatar.php?gravatar_id=d7ae6b890f16ad7541732e0f38adcbf2
Awesome!
I just saw this from my URL reffer list and it made me laugh.

Heheheh! How do you expect to get a result from this? Does the person expect to automatically get a list of all the people who attended the wedding?
I wrote an article a few years ago using SQL SMO and just realized today that I can also list SQL Severs without importing an additional assembly to my project(Microsoft.SqlServer.Management.Smo) by using the SqlDataSourceEnumerator class. SqlDataSourceEnumerator is a class that provides a mechanism for enumerating all intances of SQL Server in a given network. SqlDataSourceEnumerator exposes a method called GetDataSources() that returns a DataTable containing the list of SQL Servers and some basic information about the server
Somebody sent me an email today asking me about an article I wrote a few years ago detailing how to generate random strings and numbers in C# and VB.NET. He asked me if I could add function to the code that creates a random character set to be used as a base for the allowed characters in the random string. I went on and hammered the solution and this what I built for him. I don't have enough time to explain the whole thing but I hope the code comments I added would be good enough to understand what I did with the code.
[----------------- C# Version -----------------]
using System; using System.Collections.Generic; using System.Text;
namespace KeithRull.ConsoleCentral { class RandomStrings { //our default string size private const int CONST_MaxStringLenght = 10;
//our default character string set private const string CONST_AllowedCharacterLiterals = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
//our randomizer Random randomNumber = new Random();
/// <summary> /// Generate a random string using the default options /// </summary> /// <returns>the random string</returns> public string GenerateRandomString() { return GenerateRandomString(CONST_MaxStringLenght); }
/// <summary> /// Create a random string based on a specified lenght /// </summary> /// <param name="lenght">the lenght of the desired lenght of the random string</param> /// <returns>the randomized string</returns> public string GenerateRandomString(int lenght) { return GenerateRandomString(lenght, CreateRandomStringSet()); }
/// <summary> /// Creates a random string based on a specific lenght and character set /// </summary> /// <param name="lenght">the lenght of the desired lenght of the random string</param> /// <param name="charsToUse">character set to use</param> /// <param name="randomizeSourceSet">defines whether the source set should be scrambled</param> /// <returns>the random string</returns> public string GenerateRandomString(int lenght, string charsToUse, bool randomizeSourceSet) { string randomString = String.Empty;
if (randomizeSourceSet) { //scramble and jumble it randomString = GenerateRandomString(lenght, CreateRandomStringSet(charsToUse)); } else { //use the default charset randomString = GenerateRandomString(lenght, charsToUse); }
return randomString; }
/// <summary> /// Creates a random string based on a specific lenght and character set /// </summary> /// <param name="lenght">the lenght of the desired lenght of the random string</param> /// <param name="charsToUse">character set to use</param> /// <returns>the random string</returns> public string GenerateRandomString(int lenght, string charsToUse) { //Create a new StringBuilder that would hold the random string. StringBuilder randomString = new StringBuilder();
//Create a variable to hold the generated charater. char appendedChar;
//Create a loop that would iterate from 0 to the specified value of intLenghtOfString for (int i = 0; i <= lenght; ++i) { int characterIndex = Convert.ToInt32(randomNumber.Next(i, charsToUse.Length - i)); //Generate the char and assign it to appendedChar appendedChar = charsToUse[characterIndex]; //Append appendedChar to randomString randomString.Append(appendedChar); } //Convert randomString to String and return the result. return randomString.ToString(); }
/// <summary> /// Returns a random set of characters based on the default literal set /// </summary> /// <returns>the random string</returns> private string CreateRandomStringSet() { //just use the default character set return CreateRandomStringSet(CONST_AllowedCharacterLiterals); }
/// <summary> /// A function that returns a new set of characters based on an input set /// </summary> /// <param name="allowedCharacters">the source set</param> /// <returns>the new collection of characters</returns> private string CreateRandomStringSet(string allowedCharacters) { string randomizedString = String.Empty;
//get a random string set size int randomSetLenght = allowedCharacters.Length * randomNumber.Next(1, CONST_MaxStringLenght);
//while lenght of the random set is not the same as the source string lenght while (randomizedString.Length != randomSetLenght) { //add a new character randomizedString += GetRandomCharFromString(allowedCharacters); }
//return our random string return randomizedString; }
/// <summary> /// Gets a character from the the input string /// </summary> /// <param name="allowedCharacters">source string</param> /// <returns>a random character</returns> private char GetRandomCharFromString(string allowedCharacters) { return allowedCharacters[randomNumber.Next(allowedCharacters.Length - 1)]; } } }
[----------------- C# Usage -----------------]
using System; using System.Collections.Generic; using System.Text;
namespace KeithRull.ConsoleCentral { class Program { static void Main(string[] args) { RandomStrings r = new RandomStrings();
Console.WriteLine(r.GenerateRandomString()); Console.WriteLine(r.GenerateRandomString(10)); Console.WriteLine(r.GenerateRandomString(10, "qwerttyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM")); Console.WriteLine(r.GenerateRandomString(10, "[]{}<>!@#$%^&*()qwerttyuioplkjhgfdsazxcvbnm1234567890", true)); Console.WriteLine(r.GenerateRandomString(10, "qwerttyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM", false));
Console.ReadLine(); } } }
[----------------- VB.NET Version -----------------]
Imports System Imports System.Collections.Generic Imports System.Text
Namespace KeithRull.ConsoleCentral Class RandomStrings Private Const CONST_MaxStringLenght As Integer = 10 Private Const CONST_AllowedCharacterLiterals As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
Private randomNumber As New Random()
''' <summary> ''' Generate a random string using the default options ''' </summary> ''' <returns>the random string</returns> Public Function GenerateRandomString() As String Return GenerateRandomString(CONST_MaxStringLenght) End Function
''' <summary> ''' Create a random string based on a specified lenght ''' </summary> ''' <param name="lenght">the lenght of the desired lenght of the random string</param> ''' <returns>a random string</returns> Public Function GenerateRandomString(ByVal lenght As Integer) As String Return GenerateRandomString(lenght, CreateRandomStringSet()) End Function
''' <summary> ''' Creates a random string based on a specific lenght and character set ''' </summary> ''' <param name="lenght">the lenght of the desired lenght of the random string</param> ''' <param name="charsToUse">character set to use</param> ''' <param name="randomizeSourceSet">defines whether the source set should be scrambled</param> ''' <returns></returns> Public Function GenerateRandomString(ByVal lenght As Integer, ByVal charsToUse As String, ByVal randomizeSourceSet As Boolean) As String Dim randomString As String = [String].Empty
If randomizeSourceSet Then 'scramble and jumble it randomString = GenerateRandomString(lenght, CreateRandomStringSet(charsToUse)) Else 'use the default charset randomString = GenerateRandomString(lenght, charsToUse) End If
Return randomString End Function
Public Function GenerateRandomString(ByVal lenght As Integer, ByVal charsToUse As String) As String 'Create a new StringBuilder that would hold the random string. Dim randomString As New StringBuilder()
'Create a variable to hold the generated charater. Dim appendedChar As Char For i As Integer = 0 To lenght
'Create a loop that would iterate from 0 to the specified value of intLenghtOfString Dim characterIndex As Integer = Convert.ToInt32(randomNumber.[Next](i, charsToUse.Length - i)) 'Generate the char and assign it to appendedChar appendedChar = charsToUse(characterIndex) 'Append appendedChar to randomString randomString.Append(appendedChar) Next 'Convert randomString to String and return the result. Return randomString.ToString() End Function
''' <summary> ''' Returns a random set of characters based on the default literal set ''' </summary> ''' <returns></returns> Private Function CreateRandomStringSet() As String Return CreateRandomStringSet(CONST_AllowedCharacterLiterals) End Function
''' <summary> ''' A function that returns a new set of characters based on an input set ''' </summary> ''' <param name="allowedCharacters">the source set</param> ''' <returns>the new collection of characters</returns> Private Function CreateRandomStringSet(ByVal allowedCharacters As String) As String Dim randomizedString As String = [String].Empty
'get a random string set size Dim randomSetLenght As Integer = allowedCharacters.Length * randomNumber.[Next](1, CONST_MaxStringLenght)
'while lenght of the random set is not the same as the source string lenght While randomizedString.Length <> randomSetLenght 'add a new character randomizedString += GetRandomCharFromString(allowedCharacters) End While
'return our random string Return randomizedString End Function
''' <summary> ''' Gets a character from the the input string ''' </summary> ''' <param name="allowedCharacters">source string</param> ''' <returns>a random character</returns> Private Function GetRandomCharFromString(ByVal allowedCharacters As String) As Char Return allowedCharacters(randomNumber.[Next](allowedCharacters.Length - 1)) End Function End Class End Namespace
[----------------- VB.NET Usage -----------------]
Imports System Imports System.Collections.Generic Imports System.Text
Namespace KeithRull.ConsoleCentral Class Program Private Shared Sub Main(ByVal args As String()) Dim r As RandomStrings = New RandomStrings()
Console.WriteLine(r.GenerateRandomString()) Console.WriteLine(r.GenerateRandomString(10)) Console.WriteLine(r.GenerateRandomString(10, "qwerttyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM")) Console.WriteLine(r.GenerateRandomString(10, "[]{}<>!@#$%^&*()qwerttyuioplkjhgfdsazxcvbnm1234567890", True)) Console.WriteLine(r.GenerateRandomString(10, "qwerttyuioplkjhgfdsazxcvbnm1234567890QWERTYUIOPLKJHGFDSAZXCVBNM", False))
Console.ReadLine() End Sub End Class End Namespace
[----------------- Screenshot -----------------]

And that's how you create random strings in C# and VB.NET. Interested in the source code? You can download them here. RandomStrings.cs (4.61 KB) | RandomStrings.vb (5 KB)
Microsoft realeased Visual Studio 2008 yesterday and it made my fingers play with the latest bits and I wanted to exercise my hands on something that I could play with and at the same time learn the cool new features of the latest VS2008. With 'Play' being the keyword I have decided that the best application I could work with(and play at the same time) is this demo program from Vertigo.

Man, they did a great job on this app. The solution is in Visual Studio .NET 2003 (.NET 1.1) but can easily be ported to .NET 2.0 or .NET 3.5(which is what i'm trying right now). Here's some bits about the application taken from Vertigo's website:
In 1997, the computer gaming company id Software released a watershed first-person shooter game called QUAKE II, which went on to sell over one million copies and earn industry accolades as Game of the Year. Later, in December 2001, id Software generously made the QUAKE II 3-D engine available to the public under the GNU General Public License ("GPL").
Now, in July 2003, Vertigo Software, Inc. is releasing Quake II .NET, a port of the C-language based engine to Visual C++ with a .NET managed heads-up display. We did this to illustrate a point: one can easily port a large amount of C code to C++, and then run the whole application as a managed .NET application using the Microsoft Common Language Runtime (CLR) without noticeable performance delays. Once running as a .NET managed application, adding new features is easy and fun.
Quake II .NET Features:
- Demonstrates how to port C to native and managed C++
- Shows how to extend Quake II using .NET
- Whitepaper with tips on porting to native and managed C++
I haven't program in C++ in years but it think this is going to be a great refresher for my rusty C skills. I wonder if Scott Stansfield and his minions are brewing up something like this for .NET 3.5 and XNA? Hmmm... I have to wait and see but in the mean time if you guys are interested you can download this great application from Vertigo's website(complete with source code, demo tips and a developer white paper) here.
Hey Jeff! Maybe you can give me tips on how to beat the bad guys on level 4.
"FEATURE!"

Hehehe! I just saw this in my documents folder. I can't remember where I got it but it definetely made my developer flesh chuckle! Dedicated to all Software QA's out there(specially to my wonderful wife :*).
Later!

More than 2 years ago I wrote this article and submitted it in CodeProject detailing how you can build a FileSystem Browser in ASP.NET. The article talks about how newbie ASP developers moving to ASP.NET might code the solution and how somebody a little bit more familiar with ASP.NET would build the same application in lesser code.
Somebody emailed me about my article yesterday asking for some guidance. This lead me to inspect my old article. The first thing i said to myself after seeing my old code is 'Yikes! I did that?'. Yup, it was that horrible. The solution works, its functional based on the need but I knew i could clean it up and code it much better if i had the chance to do it a second time around. That chance happened today.
I haved changed the way i read folders(before it was using query strings). I have replaced that logic by placing the path inside my LinkButton CommandArgument property. How i pass the FileSystemInfo[] to the grid(it was using an intermediate datatable) and the type of control that displays the data(it was using a datagrid before now we are using a gridview). I've also added a breadcrumb like control to track the users location and made it a little bit prettier by adding icons instead of plain text descriptions.
I'll be updating this constantly based on the request I haved received from my original article. The most common request is sorting which I will add on the next release.
Hopefully this version is less crappier than the last.
*Update*
Thanks to Andreas Haydeck for pointing out a bug in the BuildNavigatorPath method that causes the navigator path not to show the proper folder location. This has been fixed and the code in this article has been updated.
Download the latest source here: KeithRull.FileSystemManagerRevisited.zip (6.57 KB)
My friend Mohammad Azam (Azamsharp) of GridViewGuy.com is looking for talented developers who also have extra-ordinary writing skills. He is looking for people who can contribute well-written articles to his website and in return he'll pay you $10/per article. So if you think you are up for the challenge and you have the skills and the motivation to write then send him a message at azamsharp@gmail.com.
A fried of mine IM'ed me today asking for help about an specific task that was assigned to him by his project manager. He is currently working on a project that has the client getting furious alot because the client discovered that most of the links on their site were broken (the vicious 404 erros) or are not pointing to the right pages (misplaced links). His PM wasn't happy at all so he was asked me to help him create a program that would parse a website and get all URLs accessible inside a page and dump the result into a text file.
I had a little bit of free time so i decided to help him by building this small application to show him how he can accomplish the task in C#.
using System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.IO; using System.Net;
namespace KeithRull.GiveMeUrls { class Program { static void Main(string[] args) { //the url to scrape Uri urlToScrape = new Uri("http://www.devpinoy.org"); //the list that would contain the urls recovered from the specified uri List<string> listOfUrls = GetAllUrlsFromUri(urlToScrape);
string fileName = SaveToFile(listOfUrls);
Console.WriteLine("Parsing completed! Urls saved to file: {0}", fileName);
Console.ReadLine(); }
public static List<string> GetAllUrlsFromUri(Uri urlToScrape) { //the list that would hold the urls List<string> listOfUrls = new List<string>(); //the search pattern that we are going to use for our regular expression string searchPattern = "href\\s*=\\s*(?:(?:\\\"(?<url>[^\\\"]*)\\\")|(?<url>[^\\s]* ))";
//get the contents of the page and put it to a string string pageContents = GetPageContents(urlToScrape);
//our regular expression should ignore case Regex regEx = new Regex(searchPattern, RegexOptions.IgnoreCase);
//get all the maching values generated by our regular expression Match match = regEx.Match(pageContents);
//loop thru all the matching strings while (match.Success) { //assign the match value to a temporary placeholder string urlFound = match.Value;
//check to see if the url does not include the full path(e.g: default.aspx) if (listOfUrls.IndexOf(urlFound) < 0) { string urlToAdd = urlFound; if (urlFound.StartsWith("href=\"javascript:")) { //do nothing, we need to display it as is. } else if (urlFound.StartsWith("href=\"/") || !urlFound.StartsWith("href=\"http://")) { //add the scrape url to the beginning of our found string urlToAdd = urlFound.Insert(6, urlToScrape.OriginalString); } //add the url to our list listOfUrls.Add(urlToAdd); } //move to the next match result match = match.NextMatch(); }
//return the list of urls that we have recovered from the site return listOfUrls; }
/// <summary> /// Reads a webpage and captures it html representation into a string /// </summary> /// <param name="urlToScrape">the website you want to read</param> /// <returns>the html representation of the site</returns> private static string GetPageContents(Uri urlToScrape) { HttpWebResponse httpWebResponse = null; StreamReader streamReader = null; string pageContents = String.Empty;
try { //create a webrequest object for the url WebRequest webRequest = WebRequest.Create(urlToScrape); //convert the webrequest to an httpwebrequest HttpWebRequest httpWebRequest = (HttpWebRequest)webRequest; //assign a timeout value for the process httpWebRequest.Timeout = 100000;
//create a webresponse object to hold the response generated for our request WebResponse webResponse = httpWebRequest.GetResponse(); //convert the webresponse to httpwebresponse httpWebResponse = (HttpWebResponse)webResponse;
//get the response stream and assign it to our streamreader streamReader = new StreamReader(httpWebResponse.GetResponseStream());
//read the contents of the stream pageContents = streamReader.ReadToEnd(); } catch (Exception ex) { //buble up the error throw ex; } finally { //close our webresponse object httpWebResponse.Close(); //close our streamreader object streamReader.Close(); }
//return the page contents return pageContents; }
/// <summary> /// Saves our list of urls to a text file /// </summary> /// <param name="listOfUrls">the list containing the urls</param> /// <returns>the filename created for the file</returns> public static string SaveToFile(List<string> listOfUrls) { //the file name string fileName = String.Format("{0}.{1}",Guid.NewGuid(), "txt");
//create a streamwriter for our file StreamWriter sw = File.CreateText(fileName);
//loop thru each string in our collection foreach (string url in listOfUrls) { //write the string to our file sw.WriteLine(url); }
//close oour streamwriter sw.Close();
//return our filename return fileName; } } }
Basically, the code does is it accepts a url and then parses that page using a regular expression to check all the strings that matches our search pattern. Once it finishes the processing of the page, it would then dump all those urls into a text file.
I sent the code to him and he was very happy with the result. Sweet!

Sounds strange but it's true. Just ask Mark Anders and he'll tell you the complete story. ;)
Anders: "... The original prototype was written in Java. I loved Java as a language and Scott(Guthrie) did too. So it was done in Java, and we took that around to lots of different groups. The first group that we took it to was the tools team. The VB and the InterDev teams were in a feud, and when they saw our demo they liked it. They said, 'If you build that, we will target it with our tools."
Thanks Dave for making me laugh today!

I was working on small project today and one of the requirements is to list down all the Mondays in a year and populate a dropdownlist with the values.
It's a funny requirement but still needs to be done since the client wants it that way(Oh well, customer is always right even if it would end up wrong). Below is my 5 minute function that accepts a 4 digit year value and DayOfWeek as its parameter(I added this feature to the function just incase they go kookoo again). The function would then return a generic list of DateTime objects that equals the specified DyOfWeek(eg. DayOfWeek.Monday, DayOfWeek.Tuesday and etc.).
private List<DateTime> GetDatesByDayOfWeek(int selectedYear, DayOfWeek dayOfWeek) { string firstDayOfTheYear = String.Format("January 1, {0}", selectedYear); string lastDayOfTheYear = String.Format("December 31, {0}", selectedYear);
DateTime firstDateTime = DateTime.Parse(firstDayOfTheYear); DateTime lastDateTime = DateTime.Parse(lastDayOfTheYear);
Int32 dayCount = lastDateTime.DayOfYear - 1;
List<DateTime> selectedDates = new List<DateTime>();
for (Int32 ctr = 0; ctr <= dayCount; ctr++) { DateTime processedDate = firstDateTime.AddDays(ctr); if (processedDate.DayOfWeek == dayOfWeek) { selectedDates.Add(processedDate); } }
return selectedDates; }
Pretty boring huh?
*update* Justice, the most Metrosexual developer in the face of North America posted a quick tweak to my code(Robert locke and Jokiz have the same comment too). Check his code below:
*update2* A bug was found by Robert Locke and Justice was kind enough to send the new code to fix the wrong block of code.
public static IList<DateTime> GetAllDaysOfWeekForYear(int year, DayOfWeek dw) { List<DateTime > listOfDates = new List<DateTime>();
DateTime firstDayOfWeekInYear = FindFirstDayOfWeekInYear(year, dw);
for (DateTime currentDateTime = firstDayOfWeekInYear; currentDateTime.Year == year; currentDateTime = currentDateTime.AddDays(7)) { listOfDates.Add(currentDateTime); } return listOfDates; }
public static DateTime FindFirstDayOfWeekInYear(int year, DayOfWeek dw) { for (int i = 1; i <= 7; ++i) { DateTime currentDate = new DateTime(year, 1, i); if (currentDate.DayOfWeek == dw) { return currentDate; } } throw new Exception("Impossible!"); }
I was browsing devpinoy today when I saw a post by one of the members about his "maintenance project" boredom. While I was reading his post I kinda had this "blast from the past" moment wherein memories of how i was back when i was starting my career as developer started vividly jumping into my head. I coudn't stop laughing for a couple of minutes because I just can't believe that some of the things that I did back when I was a little bit younger.
I used to get bored easily specially if the project that I am working on is boring, not challenging, repetitive or just something that doesn't even burn a braincell to accomplish. I would get so bored that i dread the idea of even going to work.
Yup. That was me back then.
I'ts funny how far I've reached eversince that days... I was so focused on new things, new technologies, new ideas that I forgot the reason why I was hired in the first place and that is to do work and do a good job on it. I think I was so engulfed in the idea that knowledge on every aspect of technology(even if its the most useless piece of code) would give me an edge over everybody.
It was a bad choice, a bad decision but i have learned to grow from it and now here I am, smarter than the developer I used to be. I guess I grew older and started to realize that knowledge is only important if you are using it in a positive and productive way. Any experience you learn from your daily life is a preparation for you in the future.
Through the years of working I was able to formulate a strategy on how to combat boredom... it has worked for me but believe me, it takes time to master. I can't say that I have mastered it completely but i do know that it has helped me little by little to establish myself as a better, smarter and a more patient individual. Below is the list of things i do to make work a little bit more fun than usual:
-
Try to learn as much as you could about the project. It doesnt matter if its a big task or not. Whats important to me is the idea that I might learn something new about project even if its the most boring project in the world. As I always say "You never know when you will find the next gem between the rocks."
-
See maintenance projects as a way for me to imporve the code. Whenever I'm assigned to maintenance project I see to it that I leave that project in a better shape than when I first got it. I usually pad my timeline with extra hours so that I could refactor the code. I always say to myself that any code that I touch is my property even if i didn't started it. You don't want to hear somebody saying something awful about your work(even if the code is not 99% yours) and perople usually blame the first developer or the last developer who touched a project. Always leave a mark of excellence on every work you do.
-
Take it as a challenge even if you hate the project. Don't dread the project because you wont be able to make good results. One of the things I learned in my career is that managers can easily spot if you don't like what you are doing and this can sometimes lead to bad impressions about your personality. What i usually do it code my heart out until my frustration(and burdens) are gone.
-
I'm paid to code and I should do it. Let's face it, even if you don't like a task but i's your job you need to do. It's the people who clean the drainage system.. they may not like cleaning, scrubbing and removing thrash in sewer but they need to do it because it's their job. We are not paid to like our job. We are paid to do the job and do a great job. Managers expect that from us thats why they assigned us to that task because the believe that we can accomplish it and think that we have the right skills to turn bad code into magic.
-
...and finally. Smile. No matter how hard the task, No matter how boring, No matter how repetitive. Always smile. I remember someone told me before that when you smile and feel good about yourself you always end up doing great things and you make people around you feel good. Stressing yourself about a small problem takes alot of brainpower and I would rather focus my energy on building solutions than drowning myself in the sea of problem.
I hope this helps you, I know it did wonders for me and it could do the same to you too! Practice this 5 things and reap the rewards of a happier work life.
***Want to comment?*** Comments are welcome but I suggest you post them in my DevPinoy blog. ;) Click here go there now.
I saw this while doing a research about .NET components and I find it really weird...
I think the guys in the .NET Framework team has this thing about vanity. Yeah! I call it code vanity. Not that its bad.. but its just funny how code has been getting beautiful. more beautiful and even more beautiful as the evolution of .NET goes forward. And it's a great thing too!
I was running a test on my Web Server today when a friend of mine IMed me about an interesting question about .NET. He was a new programmer for this company and the old developer that he replaced was running production(oh my) applications right of his desktop. The IT manager was getting worried because they dont have a list of applications that the old guy did because the old developer didnt do any turnover(he was fired =)) and alot of the apps that he did were essential to the business(the company was a small accounting firm). So my friend asked me if theres a way to figure out which applications are running using managed code so that they could check the application and move it to a more secure and dependable server.
In part 2 of our Back To The Basics Series, Keith discusses how to pass parameters to your inline SQL Statements, read a connection string from the web.config and the use of a static class for utilities. He also refactored(a little bit) our original solution to make the code more manageable.
|