Blog of a Filipino Developer about C#, VB.NET, ASP.NET, Java, PHP, SQL Server, MySql and Oracle RSS 2.0
# Monday, March 09, 2009

Tooltips are great additions to any interface and in this article I'm going to show you how to attach a tooltip to control in Silverlight 2.

To start, let's assume that we have a button that we want to add a tooltip to:

[XAML]

<UserControl x:Class="KeithRull.Silverlight.CreatingTooltips.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="#FF1E238E">
        <Button Content="Hover over me!" 
                Height="20" 
                Width="100" Margin="30 40" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left">
                
        </Button>
    </Grid>
</UserControl>

[Rendered UI]

In order or us to attach a tooltip to our button we need to create a reference to the TooltipService.Tooltip inside the our button's XAML declaration. We also need to setup the Tooltip.Content to tell the compiler what to show when the user hover's to our button.

[XAML]

<UserControl x:Class="KeithRull.Silverlight.CreatingTooltips.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="#FF1E238E">
        <Button Content="Hover over me!" 
                Height="20" 
                Width="100" Margin="30 40" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left">
            <ToolTipService.ToolTip>
                <ToolTip>
                    <ToolTip.Content>
                        <TextBlock TextWrapping="Wrap">
                            Hooray! I'm alive!.
                        </TextBlock>
                    </ToolTip.Content>
                </ToolTip>
            </ToolTipService.ToolTip>
        </Button>
    </Grid>
</UserControl>

[Rendered UI (at runtime)]

The message "Hooray! I'm alive!" appeared when the user hovers over our button. We can also cutomize how our tooltip appears by adding more XAML elements in the Tooltip.Content property.

[XAML]

<UserControl x:Class="KeithRull.Silverlight.CreatingTooltips.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="#FF1E238E">
        <Button Content="Hover over me!" 
                Height="20" 
                Width="100" Margin="30 40" 
                VerticalAlignment="Top" 
                HorizontalAlignment="Left">
            <ToolTipService.ToolTip>
                <ToolTip Background="#FFFFFF" Width="150">
                    <ToolTip.Content>
                        <StackPanel>
                            <Image Source="images/silverlight.png" />
                            <TextBlock HorizontalAlignment="Right">
                                It rocks like a champ!
                            </TextBlock>
                        </StackPanel>    
                    </ToolTip.Content>
                </ToolTip>
            </ToolTipService.ToolTip>
        </Button>
    </Grid>
</UserControl>

[Rendered UI (at runtime)]

Another customization that you might want to do is specifying the HorizontalOffset and the VerticalOffset. This allows you to specify where the tooltip will appear in reference to your target control.

Monday, March 09, 2009 10:49:38 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Silverlight | Tutorial
# Wednesday, March 04, 2009

I just saw this twitter...

Sweeeeet!

Time to start polishing my ASP.NET MVC skills. I've played with ASP.NET MVC before but never had the chance to use it other than building small samples. I might be rusty but I know I'll have a great companion book in learning ASP.NET MVC 1.0 once Rob, Scott, Scott and Phil's upcoming book comes out.

Wednesday, March 04, 2009 1:00:26 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | ASP.NET | Tech News and Issues | MVC
# Wednesday, February 25, 2009

A user a devpinoy.org posted a question on the forum section asking if there's a way to restrict files from being saved in a directory. I know you can do this via the FileSystemWatcher class so I quickly whipped my Visual Studio 2008 IDE and started building a prototype application to demonstrate the solution.

The first thing that you need to do is to set-up some key details on what we want to watch/monitor

private const string ALLOWED_FILE_EXTENSION = ".doc";
private const string DEFAULT_WATCH_FOLDER = @"E:\Test Folder\";

Next, the FileSystemWatcher specify what directory you want to monitor.

FileSystemWatcher watcher = new FileSystemWatcher(DEFAULT_WATCH_FOLDER);

After that you need to setup the notification filters on what type of filesystem changes you want to watch;

watcher.NotifyFilter = NotifyFilters.LastAccess |
                                    NotifyFilters.LastWrite |
                                    NotifyFilters.FileName |
                                    NotifyFilters.DirectoryName |
                                    NotifyFilters.CreationTime;

And finally, we need to set-up the FileSystem events you want our FileSystem. In this case, we only want to monitor Created and Renamed events.

watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);

Now, let's start coding our event handlers.

For our event handler, I decided to use one method that would handle both the Created and Rename event. Ideally you want to seperate this to into two different methods because you might want to handle the tow events differently but since all I want to do is to block files\folders that doesn't match my criteria i decided to handle them both using a single method called FileSystemHandler.

void watcher_Renamed(object sender, RenamedEventArgs e)
{
    FileSystemHandler(e.Name, e.FullPath);
}

void watcher_Created(object sender, FileSystemEventArgs e)
{
    FileSystemHandler(e.Name, e.FullPath);    
}

Below is the implementation detail for our FileSystemHandler method.

void FileSystemHandler(string name, string fullpath)
{
    try
    {
        //read the contents of our directory
        DirectoryInfo di = new DirectoryInfo(DEFAULT_WATCH_FOLDER);
        //get the filesysteminfo[] objects
        FileSystemInfo[] fileSystemInfoArray = di.GetFileSystemInfos();

        //there's always going to be one object matching this criteria all the time
        FileSystemInfo found = fileSystemInfoArray.Single(f => f.FullName.Equals(fullpath));

        //if it finds something
        if (found != null)
        {
            //cast the found object to directoryinfo
            DirectoryInfo d = found as DirectoryInfo;

            //if it's null it means it's a FileInfo object
            if (d == null)
            {
                //cast found to a fileinfo object
                FileInfo f = found as FileInfo;

                //delete the file if the extension doesn't match our desired/allowed extension
                if (!f.Extension.Equals(ALLOWED_FILE_EXTENSION))
                {
                    f.Delete();
                }
            }
            else
            {
                //directories are not allowed on this folder too!
                d.Delete(true);
            }
        }
    }
    catch
    {
        //let it sleep for 30 seconds
        Thread.Sleep(30000);

        //it failed so we need to try again recussively
        /*
            note: it's a good idea to set a retry limit here because if we don't 
            then the app will retry to infinity but i'll leave that up to you.
         */
        FileSystemHandler(name, fullpath);
    }
}

What the function above is doing is that it checks to see if the filesystem object that was created on the directory is either a file or a directory. If it is a directory, automatically delete it since we dont want any directory to be saved on our folder. If it is a file we need to check if it's extension matches the allowed file extension. If it matches the allowed extension we let it thru. If it doesn't we call the the Delete method on the FileInfo object to delete the file.

All we need to do now is to tell the watcher to start monitor our folder

watcher.EnableRaisingEvents = true;

Setting EnableRaisingEvents to true triggers our watcher to start monitoring the folder. Setting it to false will stop the watcher.

And we are done! Now we have an application that blocks saving or renaming of files in a folder that doesn't match the allowed file extension.

Below is the full listing of the code for the demo project I built for this article:

using System;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace KeithRull.FolderSpy
{
    public partial class MainForm : Form
    {
        private bool IsCurrentlyWatching = false;
        private const string ALLOWED_FILE_EXTENSION = ".doc";
        private const string DEFAULT_WATCH_FOLDER = @"E:\Test Folder\";
        FileSystemWatcher watcher;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            SetUpWatcher();
        }

        private void watchButton_Click(object sender, EventArgs e)
        {
            if (!IsCurrentlyWatching)
            {
                watchButton.Text = "Stop watching";
                IsCurrentlyWatching = true;

                //start the watcher
                watcher.EnableRaisingEvents = true;
            }
            else
            {
                watchButton.Text = "Start watching";
                IsCurrentlyWatching = false;

                //stop the watcher
                watcher.EnableRaisingEvents = false;
            }
        }

        void watcher_Renamed(object sender, RenamedEventArgs e)
        {
            FileSystemHandler(e.Name, e.FullPath);
        }

        void watcher_Created(object sender, FileSystemEventArgs e)
        {
            FileSystemHandler(e.Name, e.FullPath);    
        }

        void FileSystemHandler(string name, string fullpath)
        {
            try
            {
                //read the contents of our directory
                DirectoryInfo di = new DirectoryInfo(DEFAULT_WATCH_FOLDER);
                //get the filesysteminfo[] objects
                FileSystemInfo[] fileSystemInfoArray = di.GetFileSystemInfos();

                //there's always going to be one object matching this criteria all the time
                FileSystemInfo found = fileSystemInfoArray.Single(f => f.FullName.Equals(fullpath));

                //if it finds something
                if (found != null)
                {
                    //cast the found object to directoryinfo
                    DirectoryInfo d = found as DirectoryInfo;

                    //if it's null it means it's a FileInfo object
                    if (d == null)
                    {
                        //cast found to a fileinfo object
                        FileInfo f = found as FileInfo;

                        //delete the file if the extension doesn't match our desired/allowed extension
                        if (!f.Extension.Equals(ALLOWED_FILE_EXTENSION))
                        {
                            f.Delete();
                        }
                    }
                    else
                    {
                        //directories are not allowed on this folder too!
                        d.Delete(true);
                    }
                }
            }
            catch
            {
                //let it sleep for 30 seconds
                Thread.Sleep(30000);

                //it failed so we need to try again recussively
                /*
                    note: it's a good idea to set a retry limit here because if we don't 
                    then the app will retry to infinity but i'll leave that up to you.
                 */
                FileSystemHandler(name, fullpath);
            }
        }

        void SetUpWatcher()
        {
            watcher = new FileSystemWatcher(DEFAULT_WATCH_FOLDER);
            watcher.NotifyFilter = NotifyFilters.LastAccess |
                                    NotifyFilters.LastWrite |
                                    NotifyFilters.FileName |
                                    NotifyFilters.DirectoryName |
                                    NotifyFilters.CreationTime;
            watcher.Created += new FileSystemEventHandler(watcher_Created);
            watcher.Renamed += new RenamedEventHandler(watcher_Renamed);

        }
    }
}

As always, you can download the code for the complete project here: KeithRull.FolderSpy.zip (40.38 KB)

Wednesday, February 25, 2009 7:48:40 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Thursday, January 08, 2009

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.

Thursday, January 08, 2009 7:47:35 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | All about Keith | Contest | Family | Fun Stuff | Tutorial | WPF | WCF | Silverlight | Pregnancy
# Thursday, October 30, 2008

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!

Thursday, October 30, 2008 11:35:52 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | All about Keith | Contest | Fun Stuff | My Faith | WPF
# Wednesday, October 22, 2008

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>&nbsp;<%# Eval("Last") %></td>
                                    <td><b>Date:</b>&nbsp;<%# Eval("Date") %></td>
                                    <td><b>Time:</b>&nbsp;<%# Eval("Time") %></td>
                                    <td><b>Change:</b>&nbsp;<%# Eval("Change") %></td>
                                </tr>
                                <tr>
                                    <td><b>Open:</b>&nbsp;<%# Eval("Open") %></td>
                                    <td><b>Low:</b>&nbsp;<%# Eval("Low") %></td>
                                    <td><b>High:</b>&nbsp;<%# Eval("High") %></td>
                                    <td><b>Volume:</b>&nbsp;<%# Eval("Volume") %></td>
                                </tr>
                                <tr>
                                    <td><b>MktCap:</b>&nbsp;<%# Eval("MktCap") %></td>
                                    <td><b>PrvClose:</b>&nbsp;<%# Eval("PreviousClose") %></td>
                                    <td><b>PerChange:</b>&nbsp;<%# Eval("PercentageChange") %></td>
                                    <td><b>AnnRange:</b>&nbsp;<%# Eval("AnnRange") %></td>
                                </tr>
                                <tr>
                                    <td><b>Earns:</b>&nbsp;<%# Eval("Earns") %></td>
                                    <td><b>P-E:</b>&nbsp;<%# Eval("P-E") %></td>
                                    <td>&nbsp</td>
                                    <td>&nbsp</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!

Wednesday, October 22, 2008 8:21:07 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | AJAX | ASP.NET | Fun Stuff | Tutorial
# Tuesday, October 21, 2008

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:

  1. The user should be able to search for books base on a selected Testament (Old and New).
  2. The user should be able to see the contents of each Book
  3. 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.
  4. The user should be able to jump from one book to another.
  5. 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!

Tuesday, October 21, 2008 9:36:18 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Contest | Fun Stuff | Java
# Tuesday, September 23, 2008

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

Tuesday, September 23, 2008 8:54:03 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Fun Stuff | Tutorial
# Thursday, September 18, 2008

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 ;)

Thursday, September 18, 2008 6:35:57 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Fun Stuff | Tutorial
# Wednesday, September 17, 2008

Below is a code snippet that allows you to determine what groups a Windows user is part of.

[C#]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;

namespace KeithRull.ActiveDirectory.IdentifyingUserGroups
{
    class Program
    {
        static void Main(string[] args)
        {
            //get the WindowsIdentity of the current user
            WindowsIdentity currentWindowsIdentity = WindowsIdentity.GetCurrent();
            //retrieve the groups that the user belongs to
            IdentityReferenceCollection currentWindowsIdentityGroups = currentWindowsIdentity.Groups;
            //iterate thru each group
            foreach (IdentityReference identity in currentWindowsIdentityGroups)
            {
                //translate the identity into an NTAccount identity
                IdentityReference ntAccountIdentityReference = identity.Translate(typeof(NTAccount));
                //get the value
                string groupName = ntAccountIdentityReference.ToString();
                //print to console
                Console.WriteLine(groupName);
            }
            //pause
            Console.ReadLine();
        }
    }
}

[VB.NET]

Imports System 
Imports System.Collections.Generic 
Imports System.Linq 
Imports System.Security.Principal 
Imports System.Text 

Namespace KeithRull.ActiveDirectory.IdentifyingUserGroups 
    Class Program 
        Private Shared Sub Main(ByVal args As String()) 
            'get the WindowsIdentity of the current user 
            Dim currentWindowsIdentity As WindowsIdentity = WindowsIdentity.GetCurrent() 
            'retrieve the groups that the user belongs to 
            Dim currentWindowsIdentityGroups As IdentityReferenceCollection = currentWindowsIdentity.Groups 
            'iterate thru each group 
            For Each identity As IdentityReference In currentWindowsIdentityGroups 
                'translate the identity into an NTAccount identity 
                Dim ntAccountIdentityReference As IdentityReference = identity.Translate(GetType(NTAccount)) 
                'get the value 
                Dim groupName As String = ntAccountIdentityReference.ToString() 
                'print to console 
                Console.WriteLine(groupName) 
            Next 
            'pause 
            Console.ReadLine() 
        End Sub 
    End Class 
End Namespace 

HTH

 

Wednesday, September 17, 2008 9:21:38 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ActiveDirectory
# Thursday, September 11, 2008

Speaking of free books... Below are the list of free ebooks that I recommend reading/downloading for this month. I personally love Karl Seguin's book and giving it 5 out 5 stars is actually an understatement if you ask me. :)

Karl Seguin's Foundation Of Programming: Building Better Software rocks so much I recommended it to everyone I know. This 79 page book is pack with a hearty bowl of software development knowledge that would teach you about the principles of development that you should have known way before you started coding that nightmarish system.

Red Gate's Dissecting SQL Server Execution Plan is a must read for anyone who deals with data on a daily basis. It talks about how to optimize your querries and understand whats causing your querries to sleep on you while being executed.

InfoQ's Domain Driven Design Quickly is a quickly-readable summary and introduction to the fundamentals of DDD that tries to summarizes Eric Evans' book as well as Jimmy Nilsson's Applying Domain Driven Design and various other sources. The book gives you hints and tips about DDD as well as ideas on how to start DDD in your own projects.

Minh T. Nguyen's Visual Studio.NET Tips & Tricks is a must read for all developers who use Visual Studio. Enuff said!

So what are you waiting for? Download and read 'em now!

Thursday, September 11, 2008 11:48:37 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | All about Keith | ASP.NET | Tech News and Issues | Your Career
# Friday, September 05, 2008

Ever heard of ColorTranslator? It's a really cool class that you can use to convert colors in .NET. One of the things that it can do is that enables you to convert HTML colors to Windows colors and vice versa. One particular scenario wherein you might want to use this class is when you want to use HTML colors on your WinForm.

Below are examples on how to use this calls:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace ColorTranslatorTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //convert a system.drawing.color to html
            Color c1 = Color.AntiqueWhite;
            button1.BackColor = c1;
            button1.Text = ColorTranslator.ToHtml(c1);

            //convert an html color to a gdi+ color
            string htmlColor = "#FFAD55";
            Color c2 = ColorTranslator.FromHtml(htmlColor);
            button2.BackColor = c2;
            button2.Text = ColorTranslator.ToHtml(c2);

            //convert a win32 color to gdi+ color
            int colorHexadecimalValue = 0xA267;
            Color c3 = ColorTranslator.FromWin32(colorHexadecimalValue);
            button3.BackColor = c3;
            button3.Text = ColorTranslator.ToWin32(c3).ToString("X");
        }
    }
}

HTH

Friday, September 05, 2008 5:59:10 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tutorial
# Tuesday, August 19, 2008

Ever thought of how to capitalize the first letter of every word in a string? Here's how:

[C#]

using System;
using System.Globalization;

namespace KeithRull.CapitalizingLetters
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string textToTransform = "keith, you need to post more blogs!";

            Console.WriteLine("Original text: " + textToTransform);

            //capitalizing the first letter of our text using the current culture
            Console.WriteLine("Capitalize using the current culture: "
                + CultureInfo.CurrentCulture.TextInfo.ToTitleCase(textToTransform));

            //capitalizing the first letter of our text using a defined culture
            CultureInfo newCultureInfo = new CultureInfo("zh-Hans", false);
            TextInfo textInfo = newCultureInfo.TextInfo;
            Console.WriteLine("Capitalize using a specified culture: " + textInfo.ToTitleCase(textToTransform));

            Console.Read();
        }
    }
}

[VB.NET]

Imports System
Imports System.Globalization
 
Namespace KeithRull.CapitalizingLetters
    Friend Class Program
        Shared  Sub Main(ByVal args() As String)
            Dim textToTransform As String =  "keith, you need to post more blogs!" 
 
            Console.WriteLine("Original text: " + textToTransform)
 
            'capitalizing the first letter of our text using the current culture
            Console.WriteLine("Capitalize using the current culture: "
                Dim CultureInfo.CurrentCulture.TextInfo.ToTitleCase(textToTransform)) As +
 
            'capitalizing the first letter of our text using a defined culture
            Dim NewCultureInfo As CultureInfo =  New CultureInfo("zh-Hans",False) 
            Dim textInfo As TextInfo =  NewCultureInfo.TextInfo 
            Console.WriteLine("Capitalize using a specified culture: " + textInfo.ToTitleCase(textToTransform))
 
            Console.Read()
        End Sub
    End Class
End Namespace

HTH

Tuesday, August 19, 2008 6:54:48 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tutorial
# Monday, August 11, 2008

Wooohooo!! Get 'em here!

Combined Visual Studio 2008 Service Pack 1 and .NET Framework 3.5 Service Pack 1

The update for Visual Studio 2008 SP1 and .NET Framework 3.5 Service Pack 1 in a single install.

.NET Framework 3.5 Service Pack 1

The update for just the .NET 3.5 Service Pack 1, it does not include updates for Visual Studio 2008.

Monday, August 11, 2008 6:37:23 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Saturday, July 26, 2008

Sorry for not being able to post anything interesting the past few months. Anyway, I saw this old thread at DevPinoy.org the other day and I realized that nobody has posted a complete sample solution that would solve and show how to accomplish dynamic input rows in a GridView. I was thinking of replying to it a few months back but i guess work caught up at me and I wasn't able to do so. I found some free time last week and decided to build an app to demonstrate how to solve this question.

Ok, lets start by analyzing the question:

Hi guys,

I have a problem here. How can i create a dynamic row in gridview the row will defend from the user input. For example the user enter a 4 then the gridview will generate 4 rows. Please site me an example.

Thanks,
D_Conqueror

From what I understood the user wants to be able to create dynamically rows of data in the GridView depending on the number he enters on a Textbox. We can accomplish this by creating a datasource with the same number of rows as the user specified and binding it to our GridView.

To demonstrate how to solve this problem i decided to create this sample.

To start off with our tiny project we need to create a page that would ask the user for the number of rows he wan'ts to display on the GridView. The page will contain a TextBox for input and a LinkButton that we will use for submitting the value to a seperate page. Below is the HTML code for our first page (Default.aspx):

dynamiggridview01.jpg

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Dynamic GridView Input Rows</title>
</head>
<body>
    <form id="form1" runat="server">
    <div style="width:330px;">
        Number of rows to create:&nbsp; 
        <asp:TextBox ID="numberOfRowsTextBox" runat="server"></asp:TextBox>
        <div style="text-align:right;">
            <asp:LinkButton ID="submitLinkButton" runat="server" 
                onclick="submitLinkButton_Click">Submit</asp:LinkButton>
        </div>
    </div>
    </form>
</body>
</html>

and below is the code listing for Default.aspx

using System;

public partial class _Default : System.Web.UI.Page 
{
    protected void submitLinkButton_Click(object sender, EventArgs e)
    {
        Response.Redirect(String.Format(
                            "DynamicGridViewPage.aspx?rows={0}"
                            , numberOfRowsTextBox.Text));
    }
}

As you can see, all we are doing is passing the value of our TextBox as a query string parameter to our second page. The true juice of our solution is on the next page. But before we go into detail to that we need to setup first what type of values needs to be shown on the page. For this example i've decided to display a simple Person class that has for fields. An ID, a Firstname, a Lastname, and a boolean field called IsChristian. Below is the code for our Person class:

using System;

/// <summary>
/// Summary description for Person
/// </summary>
public class Person : IPerson
{
    private int _ID;
    private string _firstname;
    private string _lastname;
    private bool _isChristian;

    public int ID
    {
        get { return _ID; }
        set { _ID = value; }
    }

    public string Firstname 
    {
        get { return _firstname; }
        set { _firstname = value; }
    }

    public string Lastname
    {
        get { return _lastname; }
        set { _lastname = value; }
    }

    public bool IsChristian
    {
        get { return _isChristian; }
        set { _isChristian = value; }
    }

    public Person()    {}

    public override string ToString()
    {
        string returnValue = @"ID: " + this.ID.ToString() + "<br />"
                            + "Firstname: " + this.Firstname + "<br />"
                            + "Lastname: " + this.Lastname + "<br />"
                            + "Is Christian: " + this.IsChristian.ToString();
        
        return returnValue;
    }
}

I also created a class Persons that is a generic list of type Person. In that class I created a contructor that accepts a integer value that we will use to create the dummy list of person. The code for our Persons class is listed below:

using System;
using System.Collections.Generic;

/// <summary>
/// Summary description for Persons
/// </summary>
public class Persons: List<Person>
{
    public Persons() {}

    public Persons(int rowCount) {
        this.Clear();
        for (int i = 1; i <= rowCount; i++)
        {
            Person p = new Person();
            p.ID = i;
            this.Add(p);
        }
    }
}

Now on our second page, DynamicGridViewPage.aspx, I decided to place 4 controls. A GridView that would contain our input boxes, a label to display messages, a button to submit the fields and another GridView to show the submit values. I've added these few quirks on the page to demonstrate how you can retrieve entered values in a GridView. Below is the HTML listing for the DynamicGridViewPage.aspx.

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="dynamicGridView" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="ID">
            <Columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:Label ID="idLabel" 
                            runat="server" 
                            Text='<%# Bind("ID") %>'>
                        </asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Firstname">
                    <ItemTemplate>
                        <asp:TextBox ID="firstnameTextBox" 
                            runat="server">
                        </asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Lastname">
                    <ItemTemplate>
                        <asp:TextBox ID="lastnameTextBox" 
                            runat="server">
                        </asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Christian">
                    <ItemTemplate>
                        <asp:CheckBox ID="isChristianCheckBox" 
                            runat="server" 
                            Enabled="true" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
        <asp:LinkButton ID="submitLinkButton" runat="server" 
            onclick="submitLinkButton_Click">Submit</asp:LinkButton>
        <br />
        <br />
        <asp:Label ID="messageLabel" runat="server"></asp:Label>
        <asp:GridView ID="submitedRecordsGridView"
            runat="server">
            <EmptyDataTemplate>
                <b>No record submitted!</b>
            </EmptyDataTemplate>
        </asp:GridView>
    </div>
    </form>
</body>
</html>

One of the things that you would quickly realize on our page is that the only thing I'm binding to our GridView is the ID property. The reason is because we don't really need to bind all the fields to our GridView because we are just creating rows. Next, lets look at the code behind for our page.

using System;
using System.Web.UI.WebControls;
using System.Text;

public partial class DynamicGridViewPage : System.Web.UI.Page
{
    public int RowCount
    {
        get
        {
            int returnValue = 0;

            if (Request.QueryString["rows"] != null)
            {
                try
                {
                    int.TryParse(Request.QueryString["rows"].ToString()
                                , out returnValue);
                }
                catch{
                    messageLabel.Text = @"Invalid row count! 
                                        Go back to the <a href=""Default.aspx"">home page</a> 
                                        to enter a value!";
                }
            }

            return returnValue;
        }
    }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Persons listOfPersons = new Persons(RowCount);

            dynamicGridView.DataSource = listOfPersons;
            dynamicGridView.DataBind();
        }
    }
    protected void submitLinkButton_Click(object sender, EventArgs e)
    {
        Persons listOfPerson = new Persons();
        StringBuilder messageBuilder = new StringBuilder();

        foreach (GridViewRow gr in dynamicGridView.Rows)
        {
            if (gr.RowType == DataControlRowType.DataRow)
            {
                Person p = new Person();

                if (gr.FindControl("idLabel") != null)
                {
                    p.ID = int.Parse((gr.FindControl("idLabel") as Label).Text);
                }

                if (gr.FindControl("firstnameTextBox") != null)
                {
                    p.Firstname = (gr.FindControl("firstnameTextBox") as TextBox).Text;
                }

                if (gr.FindControl("lastnameTextBox") != null)
                {
                    p.Lastname = (gr.FindControl("lastnameTextBox") as TextBox).Text;
                }

                if (gr.FindControl("isChristianCheckBox") != null)
                {
                    p.IsChristian = (gr.FindControl("isChristianCheckBox") as CheckBox).Checked;
                }

                if (!p.Firstname.Equals(String.Empty) 
                    && !p.Lastname.Equals(String.Empty))
                {
                    listOfPerson.Add(p);
                }
                else
                {
                    messageBuilder.Append(String.Format(
                                            @"Record on line number {0} 
                                              was not submitted because 
                                              it doesn''t have a 
                                              Firstname or Lastname!<br />"
                                            , p.ID));
                }
            }
        }

        if (messageBuilder.Length > 0)
        {
            messageLabel.Text = messageBuilder.ToString();
        }
        else
        {
            messageLabel.Text = String.Empty;
        }

        submitedRecordsGridView.DataSource = listOfPerson;
        submitedRecordsGridView.DataBind();
    }
}

What happens on the code-behind is pretty simple. When the page loads it checks to see if it is not a PostBack, if it's not then it tries to retrieve the rows to create using the RowCount property. Once retrieved, that value is then passed to the contructor of the Persons class to create a dummy list of items that would then be assigned to the DataSource property of our GridView.

dynamiggridview02.jpg

dynamiggridview03.jpg

I've added code to the submit button to simulate submissions to show how you can retrieve the values entered on our GridView.

dynamiggridview04.jpg

And that's it. Thats how you create a dynamic rows in a GridView and access the values. I hope i was to shed light on this issue. Thanks!

Want the source code? Download it here: KeithRull.DynamicGridViewRows.v2.zip (6.37 KB)

Saturday, July 26, 2008 10:21:24 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET
# Tuesday, June 24, 2008

This week we continue our quest to get to know well-known Filipino developers and this time I was able to catch Jojo Paderes, one of the founding board members of PinoyJUG, coder-extraordinaire at Viewlocity and father to two lovely twins.

Read more about this interview here http://devpinoy.org/blogs/keithrull/archive/2008/06/24/ten-questions-with-jojo-paderes.aspx

Tuesday, June 24, 2008 7:32:21 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Fun Stuff | Interviews
# Thursday, June 19, 2008

Just in case you are studying WCF.. You might want to check out the .NET StockTrader Sample Application.

The .NET StockTrader Sample Application is an end-to-end sample application illustrating Windows Communication Foundation and .NET Enterprise Technologies. It is a service-oriented application based on Windows Communication Foundation (.NET 3.0) and ASP.NET, and illustrates many of the .NET enterprise development technologies for building highly scalable, rich "enterprise-connected" applications. It is designed as a benchmark kit to illustrate alternative technologies within .NET and their relative performance.

The application offers full interoperability with J2EE and IBM WebSphere's Trade 6.1 sample application. As such, the application offers an excellent opportunity for developers to learn about .NET and building interoperable, service-oriented applications.

Read more here: http://msdn.microsoft.com/en-us/netframework/bb499684.aspx

I've been diving into WCF lately and I have found this sample application as a great blueprint on how to develop applications using WCF & ASP.NET. The sample includes a smart client and an ASP.NET application that you can jump on and play that showcases as huge list of technologies and approaches when developing an SOA app via WCF and .NET

Below is a list of technologies that's demonstrated in this sample application:

  • Service-oriented, n-tier design with ASP.NET and WCF
    • Clean separation of UI, business services and DB access
    • Design and tuning for performance
    • Horizontally scalable via dynamic clustering
    • Centralized configuration management of clustered service nodes
  • .NET 3.5 with Windows Communication Foundation
    • Interoperability with J2EE/WebSphere Trade 6.1
    • Incorporates alternative designs for performance comparisons
    • Loosely-coupled, message-oriented design with WCF and MSMQ
    • Achieving assured message delivery with transactions
    • Self-hosting WCF Services
    • Custom WCF Behaviors
    • Service host failure detection and automatic restarts
  • .NET Enterprise Application Server Technologies
    • ASP.NET 2.0
    • ADO.NET 2.0
    • .NET Transactions
    • MSMQ 3.5 (Windows XP/Windows Server 2003)
    • MSMQ 4.0 (Windows Vista/"Longhorn Server CTP")
    • Transaction batching with WCF and MSMQ

Try and see for yourself ;) I bet you will enjoy it too!

 

Thursday, June 19, 2008 11:08:05 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET
# Wednesday, June 11, 2008

Do you want to use LINQ but you are still stuck with .NET 2.0 and .NET 3.0? Are you still waiting for your company to upgrade to VS 2008 to get a hold of LINQ? Then wait no more because the good guys who wrote the book C# 3.0 In A Nutshell have created a .NET library that implements all the standard LINQ operators so that you can enjoy the goodness of LINQ in .NET 2.0 and 3.0.

LINQBridge is a reimplementation of all the standard query operators in Framework 3.5's Enumerable class. It's designed to work with the C# 3.0 compiler, as used by Visual Studio 2008. LINQBridge comprises a "LINQ to Objects" API for running local queries. (It doesn't include an implementation of LINQ to SQL, nor LINQ to XML; a good compromise can be to force Framework 3.5 out to just the server machines, allowing LINQ to SQL to be used where it's needed most).

LINQBridge also includes Framework 3.5's generic Func and Action delegates, as well as ExtensionAttribute, allowing you to use C# 3.0's extension methods in Framework 2.0.

In fact LINQBridge lets you use nearly all of the features in C# 3.0 with Framework 2.0—including extension methods, lambda functions and query comprehensions. The only feature it does not support is compiling lambdas to expression trees (i.e., Expression<TDelegate>).

Awesome huh?! Get this goodie here: http://www.albahari.com/nutshell/linqbridge.html

Wednesday, June 11, 2008 1:45:05 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Thursday, April 17, 2008

In my previous article I showed you how to add a web service reference in your ASP.NET application, call a webmethod and the display the values returned byt the web service to a Label. This time I'm going to show you how to transform that Xml string into a DataSet.

I suggest that you read the previous article before continuing in reading this post so you'll have a better insight on what we are trying to accomplish on this article.

Let's begin!

To start off this article let's look at how the application that we built for the previous article.

and the HTML code for the UI

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<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>
            <strong>Symbol</strong><br />
            <asp:TextBox ID="symbolTextBox" 
                         runat="server" />
            <asp:Button ID="executeButton" 
                        runat="server" 
                        Text="Execute"
                        OnClick="executeButton_Click" />
            <br />
            <br />
            <strong>Result</strong>
            <br />
            <asp:Label ID="xmlResultLabel" 
                        runat="server" />
        </div>
    </form>
</body>
</html>

and the underlying code for the click event of the "Execute" button

    protected void executeButton_Click(object sender, EventArgs e)
    {
        //get the execution symbol entered in the TextBox
        string executionSymbol = symbolTextBox.Text;

        //get the stock quote information
        string quoteInfo = GetStockQuoteInformation(executionSymbol);

        //HtmlEncode the string to properly render it on the page
        string htmlEncodedResult = System.Web.HttpUtility.HtmlEncode(quoteInfo);
       
        //assign the HtmlEncoded string to our Label control
        xmlResultLabel.Text = htmlEncodedResult;
    }

As you can see the code above does the job of displaying the retuned xml from the webservice. It works. We can understand that XML because we are techie enough but imagine a normal user seeing a xml values on his screen? Yup. Not good. The best way to present data to a user is to show values in tabular form. A lot more pleasing to the eyes and much easier to understand. With that said let's start by replacing the Label control in the form with a DetailsView control. The new aspx page for our form should look like this:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<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>
            <strong>Symbol</strong><br />
            <asp:TextBox ID="symbolTextBox" 
                         runat="server" />
            <asp:Button ID="executeButton" 
                        runat="server" 
                        Text="Execute"
                        OnClick="executeButton_Click" />
            <br />
            <br />
            <strong>Result</strong>&nbsp;<br />
            <asp:DetailsView ID="stockQuoteInfoDetailsView" runat="server" Height="50px" Width="125px">
            </asp:DetailsView>
        </div>
    </form>
</body>
</html>

As you can see in the old code for the Click event we are able to get the XML and display it on a Label. What we need to do now is to read that XML string and assign it to a our DetailsView but there is one problem... The XML string needs to be converted to an object that supports IList or IEnumerable first before it could be loaded to our DetailsView.

To solve this problem I've decided to create this method that accepts an XML string and converts it to a DataSet.

    /// <summary>
    /// A function that takes an XML string and converts it into a DataSet
    /// </summary>
    /// <param name="xmlString">The xml string to tranform into a DataSet</param>
    /// <returns>The DataSet representing the values and schema from our xml string</returns>
    private DataSet XmlString2DataSet(string xmlString)
    {
        //create a new DataSet that will hold our values
        DataSet quoteDataSet = null;

        //check if the xmlString is not blank
        if (String.IsNullOrEmpty(xmlString)) {
            //stop the processing
            return quoteDataSet;
        }

        try{
            //create a StringReader object to read our xml string
            using (StringReader stringReader = new StringReader(xmlString))
            {
                //initialize our DataSet
                quoteDataSet = new DataSet();

                //load the StringReader to our DataSet
                quoteDataSet.ReadXml(stringReader);
            }
        }
        catch{
            //return null
            quoteDataSet = null;
        }

        //return the DataSet containing the stock information
        return quoteDataSet;
    }

Now we can modify our our executeButton_Click event

    protected void executeButton_Click(object sender, EventArgs e)
    {
        //get the execution symbol entered in the TextBox
        string executionSymbol = symbolTextBox.Text;

        //get the stock quote information
        string quoteInfo = GetStockQuoteInformation(executionSymbol);

        //create our quote DataTable
        DataSet quoteDataSet = XmlString2DataSet(quoteInfo);

        //assign the quote information to our DetailsView
        stockQuoteInfoDetailsView.DataSource = quoteDataSet;
        stockQuoteInfoDetailsView.DataBind();
    }

All we did was pass the xml string to the XmlString2DataSet function to retrieve a DataSet containing the stock quote information and then assigning that DataSet object to our DetailsView for display. Below is how the final form looks-like after our modification

Now that is more presentable! I hope I was able to share with you something useful. Next stop, we'll be building Master-Detail pages in ASP.NET ;)

Care for the code? Grab it here: KeithRull.ConsumingWebServices.Part2.zip (5.76 KB)

Thursday, April 17, 2008 6:27:06 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET | Tutorial
# Tuesday, April 08, 2008

I've been meaning to write this tutorial for a month now and finally i found time to write it. As you may have noticed, I have been blogging about accessing files (here, here and here), reading XML, and loading XML data to a GridView lately. The reason behind this is that I am preping you guys up for a much larger article that would span to 5 articles with different demos for each post... something that needs to spend a little bit of time on the lower end of the grid to make the whole thing easier to explain once we start building the big picture... but I won't spill the details about the post yet ;) so better keep up with the site to learn what I've been brewing since early March.

In the meantime let's talk about how to consume XML Web Services in ASP.NET. I don't want to bore you with explanations on what an XML Web Service means so I'll just lead you to a document written by Roger Wolter in 2001 that explains the whole enselada about Web Services. Below is an excerpt from that document:

XML Web services are the fundamental building blocks in the move to distributed computing on the Internet. Open standards and the focus on communication and collaboration among people and applications have created an environment where XML Web services are becoming the platform for application integration. Applications are constructed using multiple XML Web services from various sources that work together regardless of where they reside or how they were implemented.

There are probably as many definitions of XML Web Service as there are companies building them, but almost all definitions have these things in common:

  • XML Web Services expose useful functionality to Web users through a standard Web protocol. In most cases, the protocol used is SOAP.
  • XML Web services provide a way to describe their interfaces in enough detail to allow a user to build a client application to talk to them. This description is usually provided in an XML document called a Web Services Description Language (WSDL) document.
  • XML Web services are registered so that potential users can find them easily. This is done with Universal Discovery Description and Integration (UDDI).

Now that we have nailed the basic definition let's build a simple application that consumes a publicly available web service. There are a lot of sites that list useful public web services and one of those sites is WebServiceX. WebServiceX's website contains 70+ freely available web service that you can use and utilize in your projects. For this demo I've decided to use the StockQuote service which is a web service that allows you to query stock information by using the symbol of the stock. Here's some information about the service taken from their website:

Summary: Get Stock quote for a company symbol by using this web service
Endpoint:
http://www.webservicex.net/stockquote.asmx
Disco: http://www.webservicex.net/stockquote.asmx?Disco
WSDL Location: http://www.webservicex.net/stockquote.asmx?wsdl

Let's begin building!

First, let's start by creating a new ASP.NET Website Project

Once that's done we need to add a Web Reference to our project that would point to the StockQuote service hosted on the WebServiceX website. We can do this by right-clicking on our solution and then selecting the Web Reference menu item.

A new screen will appear that will enable you to specify the URL of the web service. Input http://www.webservicex.net/stockquote.asmx on the URL dropdownlist to create reference to the StockQuote service.

Click "Add Reference" to add the reference to the project. You'll notice that the folder structure of your project has been updated and a new folder called "App_WebReferences" has been added to the project.

Ok, now let's build our UI. My idea for this sample application is to have a TextBox that allows users to enter the symbol, a Button control that will trigger the lookup to the web service via it's Click event and a Label control that will used to display the values returned by the web service. Below is how I envisioned our form to look-like:

And here's the accompanying HTML source for our form

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<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>
            <strong>Symbol</strong><br />
            <asp:TextBox ID="symbolTextBox" 
                         runat="server" />
            <asp:Button ID="executeButton" 
                        runat="server" 
                        Text="Execute"
                        OnClick="executeButton_Click" />
            <br />
            <br />
            <strong>Result</strong>
            <br />
            <asp:Label ID="xmlResultLabel" 
                        runat="server" />
        </div>
    </form>
</body>
</html>

Now that we have the infrastructure in place it's time to write some code. The first thing that we need to do on the code-behind level is to add the using declaration to include the web service class in our page.

This enables us to create objects from our web service. The class that we would be using in this exercise is the StockQuote object which has the StockQuote.GetQuote method that returns the XML data containing the information for a specified symbol. Below is the method I wrote to show you how to use this class:

    /// <summary>
    /// A function that retrieves the stock information
    /// from the StockQuote web service
    /// </summary>
    /// <param name="executionSymbol">the execution symbol to lookup</param>
    /// <returns>The string containing the XML information regarding the symbol</returns>
    private string GetStockQuoteInformation(string executionSymbol)
    {
        string quoteInfo = String.Empty;

        //check if the executionSymbol is not blank
        if (String.IsNullOrEmpty(executionSymbol)) {
            //stop the processing
            return quoteInfo;
        }

        try
        {
            //create a StockQuote object
            StockQuote quote = new StockQuote();

            //get the stock quote information for the specified symbol
            quoteInfo = quote.GetQuote(executionSymbol);
        }
        catch (Exception ex) {
            //raise the error
            string errorMessage = String.Format("Error while trying to connect to the Web Service. {0}", ex.Message);
            throw new Exception(errorMessage);
        }

        //return the quote information
        return quoteInfo;
    }

Now that we have the function that will call our web service it's time to hook up our method to the Click event of our button.

    protected void executeButton_Click(object sender, EventArgs e)
    {
        //get the execution symbol entered in the TextBox
        string executionSymbol = symbolTextBox.Text;

        //get the stock quote information
        string quoteInfo = GetStockQuoteInformation(executionSymbol);

        //HtmlEncode the string to properly render it on the page
        string htmlEncodedResult = System.Web.HttpUtility.HtmlEncode(quoteInfo);
        
        //assign the HtmlEncoded string to our Label control
        xmlResultLabel.Text = htmlEncodedResult;
    }

As you can see the whole process was built with little code. Run the application and see how the easy it is to connect to a web service, call a web service method and use it's returned value.

I hope you learned something from this tutorial. On our next article i'll show you howto display the XML returned by the web service to a GridView.

Later ;)

Tuesday, April 08, 2008 5:48:30 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Tuesday, April 01, 2008

Last week I showed you how to read an XML file, load it to a DataSet and assign those values into a GridView. Today I'll show you how you can read an XML file using the XmlDataSource object.

Let's assume that we have an XML file called Symbols.xml in our App_Data folder

that contains the following data

<?xml version="1.0" encoding="utf-8" ?>
<Symbols>
    <Symbol ExecutionSymbol="ATT" Name="AT&amp;T"></Symbol>
    <Symbol ExecutionSymbol="MSFT" Name="Microsoft"></Symbol>
    <Symbol ExecutionSymbol="GOOG" Name="Google"></Symbol>
    <Symbol ExecutionSymbol="CSCO" Name="Cisco"></Symbol>
    <Symbol ExecutionSymbol="IP" Name="International Paper Co."></Symbol>
    <Symbol ExecutionSymbol="MF" Name="MF Global"></Symbol>
    <Symbol ExecutionSymbol="Q" Name="Qwest Communications International Inc."></Symbol>
    <Symbol ExecutionSymbol="BMC" Name="BMC Software Inc."></Symbol>
    <Symbol ExecutionSymbol="WCI" Name="WCI Communities Inc."></Symbol>
    <Symbol ExecutionSymbol="SPY" Name="SDRs"></Symbol>
    <Symbol ExecutionSymbol="LEH" Name="Lehman Brothers Holdings Inc."></Symbol>
    <Symbol ExecutionSymbol="XLF" Name="Financial Select Sector SPDR"></Symbol>
    <Symbol ExecutionSymbol="QQQQ" Name="PowerShares QQQ TR 1"></Symbol>
    <Symbol ExecutionSymbol="IWM" Name="IShare Rus 2000 INDX"></Symbol>
    <Symbol ExecutionSymbol="GE" Name="General Electric Co."></Symbol>
    <Symbol ExecutionSymbol="MER" Name="Merrill Lynch Co., Inc."></Symbol>
    <Symbol ExecutionSymbol="BAC" Name="Bank of America Corporation"></Symbol>
    <Symbol ExecutionSymbol="INTC" Name="Intel Corp"></Symbol>
    <Symbol ExecutionSymbol="F" Name="Ford Motor Co."></Symbol>
    <Symbol ExecutionSymbol="QID" Name="UltraShort QQQ ProShares"></Symbol>
</Symbols>

and we want to load it to a GridView with no server-side code and a quick and easy way. The answer is to use the XmlDataSource object. The XmlDataSource control is an ASP.NET control that allows you to automatically read XML Data and make that data readily available to any ASP.NET control.

To start using this control, go to your Toolbox and drag the XmlDataSource control to your page.

Once the control is on the page it would popup a dialog that has configuration options for our XmlDataSource control. Click the "Configure Data Source" button to configure our XmlDataSource

A popup like below will come up that allows you to select the Xml file you want to your XmlDataSource object to read. It also gives you the option to select the XSL file. You can also specify an XPath expression to use to filter the data in our Xml.

Click the "Browse" button for the "Data File" option to select an XML file.

A new dialog will appear that will let you navigate the folder tree to select your desired XML file

Click "Ok" and you'll be taken back to the "Configure Data Source" screen. Click "Ok" again to finalize the XML data assignment.

Now that we have the file set in to our XmlDataSource control we need assign it to a control. We can do that by dragging a GridView control to our form.

Next, we need to assign the XmlDataSource control as the data source for our GridView. We can do this by selecting our XmlDataSource from the "Choose Data Source" dropdownlist.

Click "XmlDataSource1" and you will notice that our GridView was automatically updated and now shows the contents of our XML file.

Easy huh? Next up, Consuming Web Services in ASP.NET

 

Tuesday, April 01, 2008 12:15:13 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | ASP.NET | Tutorial
# Thursday, March 27, 2008

Last week I showed you ways on how to read text files. This time around we will be looking at how to load XML files into a DataSet.

Let's assume that we have a file called Symbols.xml which contains some XML data.

<?xml version="1.0" encoding="utf-8" ?>
<Symbols>
    <Symbol ExecutionSymbol="ATT" Name="AT&amp;T"></Symbol>
    <Symbol ExecutionSymbol="MSFT" Name="Microsoft"></Symbol>
    <Symbol ExecutionSymbol="GOOG" Name="Google"></Symbol>
    <Symbol ExecutionSymbol="CSCO" Name="Cisco"></Symbol>
    <Symbol ExecutionSymbol="IP" Name="International Paper Co."></Symbol>
    <Symbol ExecutionSymbol="MF" Name="MF Global"></Symbol>
    <Symbol ExecutionSymbol="Q" Name="Qwest Communications International Inc."></Symbol>
    <Symbol ExecutionSymbol="BMC" Name="BMC Software Inc."></Symbol>
    <Symbol ExecutionSymbol="WCI" Name="WCI Communities Inc."></Symbol>
    <Symbol ExecutionSymbol="SPY" Name="SDRs"></Symbol>
    <Symbol ExecutionSymbol="LEH" Name="Lehman Brothers Holdings Inc."></Symbol>
    <Symbol ExecutionSymbol="XLF" Name="Financial Select Sector SPDR"></Symbol>
    <Symbol ExecutionSymbol="QQQQ" Name="PowerShares QQQ TR 1"></Symbol>
    <Symbol ExecutionSymbol="IWM" Name="IShare Rus 2000 INDX"></Symbol>
    <Symbol ExecutionSymbol="GE" Name="General Electric Co."></Symbol>
    <Symbol ExecutionSymbol="MER" Name="Merrill Lynch Co., Inc."></Symbol>
    <Symbol ExecutionSymbol="BAC" Name="Bank of America Corporation"></Symbol>
    <Symbol ExecutionSymbol="INTC" Name="Intel Corp"></Symbol>
    <Symbol ExecutionSymbol="F" Name="Ford Motor Co."></Symbol>
    <Symbol ExecutionSymbol="QID" Name="UltraShort QQQ ProShares"></Symbol>
</Symbols>

And you want to load that data into a DataSet and display it to a GridView. How would you do it?

There are different ways you can load an XML file to a DataSet and i'm here to show you 4 of them. I don't have alot of time to explain the intrinsicts of each sample or performance comparisson of each technique because of time constraints so i'll leave that part for you to figure out the best among this examples. ;)

SAMPLE 1

//Sample 1
//the code below shows us how to load the XML document
//directly to our dataset by just specifying the file
//location to the DataSet.ReadXml method of the DataSet

using System;
using System.Data;
using System.Xml;
using System.IO;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string xmlFilePath = Server.MapPath(@"App_Data/Symbols.xml");

        if (File.Exists(xmlFilePath))
        {
            //create the Dataset object
            using (DataSet ds = new DataSet())
            {
                //load the xml data to the dataset
                ds.ReadXml(xmlFilePath);

                //bind the values to our GridView
                symbolGridView.Caption = "<h4>Loaded the data using Sample1</h4>";
                symbolGridView.DataSource = ds;
                symbolGridView.DataBind();
            }
        }
    }
}

SAMPLE 2

//Sample 2
//The code below is using the TextReader object to read
//the contents of the file and then assign those values
//to our dataset object

using System;
using System.Data;
using System.Xml;
using System.IO;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string xmlFilePath = Server.MapPath(@"App_Data/Symbols.xml");

        if (File.Exists(xmlFilePath))
        {
            //Create the TextReader object
            using (TextReader sReader = new StreamReader(xmlFilePath))
            {
                //create the Dataset object
                using (DataSet ds = new DataSet())
                {
                    //load the xml data from the TextReader to the Dataset
                    ds.ReadXml(sReader);

                    //bind the values to our GridView
                    symbolGridView.Caption = "<h4>Loaded the data using Sample2</h4>";
                    symbolGridView.DataSource = ds;
                    symbolGridView.DataBind();
                }
            }
        }
    }
}

SAMPLE 3

//Sample 3
//The code below is basically the same as the above code
//but this time we are using the XmlTextReader object
//instead of using the TextReader object. Please note that
//the XmlReader object calls the TextReader internally.

using System;
using System.Data;
using System.Xml;
using System.IO;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string xmlFilePath = Server.MapPath(@"App_Data/Symbols.xml");

        if (File.Exists(xmlFilePath))
        {
            //Create the XmlTextReader object
            using (XmlTextReader xTextReader = new XmlTextReader(xmlFilePath))
            {
                //create the Dataset object
                using (DataSet ds = new DataSet())
                {
                    //load the xml data to dataset
                    ds.ReadXml(xTextReader);

                    //bind the values to our GridView
                    symbolGridView.Caption = "<h4>Loaded the data using Sample3</h4>";
                    symbolGridView.DataSource = ds;
                    symbolGridView.DataBind();
                }
            }
        }
    }
}

SAMPLE 4

//Sample 4
//The code below uses an XmlDocument object and reads a file
//using the XmlDocument.LoadXml method. That data is then
//transfered to a DataSet by using the DataSet.ReadXml method
//and passing a XmlNodeReader object based on our XmlDocument

using System;
using System.Data;
using System.Xml;
using System.IO;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string xmlFilePath = Server.MapPath(@"App_Data/Symbols.xml");

        if (File.Exists(xmlFilePath))
        {
            //Create the Dataset object
            using (DataSet ds = new DataSet())
            {
                //create the XmlDocument object
                XmlDocument xDoc = new XmlDocument();

                //load the contents of the file to our XmlDocument object
                xDoc.LoadXml(File.ReadAllText(xmlFilePath));

                //load the xml data in the XmlDocument object to the Dataset
                ds.ReadXml(new XmlNodeReader(xDoc));

                //bind the values to our GridView
                symbolGridView4.Caption = "<h4>Loaded the data using Sample4</h4>";
                symbolGridView4.DataSource = ds;
                symbolGridView4.DataBind();
            }
        }
    }
}

And that's it. On my next post i'll show you how to load XML data directly to the GridView using the XMLDataSource object.

HTH.

Thursday, March 27, 2008 3:47:22 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tutorial
# Wednesday, March 19, 2008

Sample 3 is similar to Sample 1 and and Sample 2 but it uses the File.ReadAllText method which reads the content of the whole file instead of reading the data line by line or reading the data and putting the values into a string[].

[C# Version]

using System;
using System.IO;

namespace KeithRull.ReadMyFile
{
    class Program
    {
        static void Main(string[] args)
        {
            //the filename of the file to read
            string xmlFilename = "Symbols.xml";
          
            //validate if the file exist
            if (File.Exists(xmlFilename))
            {
                //read the contents of the file
                string fileContent = File.ReadAllText(xmlFilename);

                //display the output in the screen
                Console.WriteLine(fileContent);
            }
            else
            {
                //notify that the file was not found
                Console.WriteLine("File not found!");
            }

            //pause and wait for the user.
            Console.ReadLine();
        }
    }
}

[VB.NET Version]

Imports System 
Imports System.IO 

Namespace KeithRull.ReadMyFile 
    Class Program 
        Private Shared Sub Main(ByVal args As String()) 
            'the filename of the file to read 
            Dim xmlFilename As String = "Symbols.xml" 
            
            'validate if the file exist 
            If File.Exists(xmlFilename) Then 
                'read the contents of the file 
                Dim fileContent As String = File.ReadAllText(xmlFilename) 
                
                'display the output in the screen 
                Console.WriteLine(fileContent) 
            Else 
                'notify that the file was not found 
                Console.WriteLine("File not found!") 
            End If 
            
            'pause and wait for the user. 
            Console.ReadLine() 
        End Sub 
    End Class 
End Namespace 
Wednesday, March 19, 2008 7:18:14 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tutorial
Sample demonstrates how to use the File.ReadAllLines technique 

[C# Version]

using System;
using System.IO;

namespace KeithRull.ReadMyFile
{
    class Program
    {
        static void Main(string[] args)
        {
            //the filename of the file to read
            string xmlFilename = "Symbols.xml";
          
            //validate if the file exist
            if (File.Exists(xmlFilename))
            {
                //read the contents of the file
                string[] fileContent = File.ReadAllLines(xmlFilename);

                //iterate for each line item in our file
                foreach (string lineItem in fileContent)
                {
                    //display the output in the screen
                    Console.WriteLine(lineItem);
                }
            }
            else
            {
                //notify that the file was not found
                Console.WriteLine("File not found!");
            }

            //pause and wait for the user.
            Console.ReadLine();
        }
    }
}

[VB.NET Version]

Imports System
Imports System.IO

Namespace KeithRull.ReadMyFile
    Class Program
        Private Shared Sub Main(ByVal args As String())
            'the filename of the file to read
            Dim xmlFilename As String = "Symbols.xml"
           
            'validate if the file exist
            If File.Exists(xmlFilename) Then
                'read the contents of the file
                Dim fileContent As String() = File.ReadAllLines(xmlFilename)
               
                'iterate for each line item in our file
                For Each lineItem As String In fileContent
                    'display the output in the screen
                    Console.WriteLine(lineItem)
                Next
            Else
                'notify that the file was not found
                Console.WriteLine("File not found!")
            End If
           
            'pause and wait for the user.
            Console.ReadLine()
        End Sub
    End Class
End Namespace

Wednesday, March 19, 2008 7:04:44 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tutorial

Sample 1 demonstrates how to use the StreamReader technique when reading the contents of a file

[C# Version]

using System;
using System.IO;

namespace KeithRull.ReadMyFile
{
    class Program
    {
        static void Main(string[] args)
        {
            //the filename of the file to read
            string xmlFilename = "Symbols.xml";
          
            //validate if the file exist
            if (File.Exists(xmlFilename))
            {
                //create a new StreamReader object tha would read the file
                using (StreamReader sReader = new StreamReader(xmlFilename))
                {
                    //create a string object that would hold the
                    //value of each line in our file
                    string line = String.Empty;
                    
                    //iterate for each line item in our file
                    while ((line = sReader.ReadLine()) != null)
                    {
                        //display the output in the screen
                        Console.WriteLine(line);
                    }
                }
            }
            else
            {
                //notify that the file was not found
                Console.WriteLine("File not found!");
            }

            //pause and wait for the user.
            Console.ReadLine();
        }
    }
}

[VB.NET Version]

Imports System 
Imports System.IO 

Namespace KeithRull.ReadMyFile 
    Class Program 
        Private Shared Sub Main(ByVal args As String()) 
            'the filename of the file to read 
            Dim xmlFilename As String = "Symbols.xml" 
            
            'validate if the file exist 
            If File.Exists(xmlFilename) Then 
                'create a new StreamReader object tha would read the file 
                Using sReader As New StreamReader(xmlFilename) 
                    'create a string object that would hold the 
                    'value of each line in our file 
                    Dim line As String = [String].Empty 
                    
                    'iterate for each line item in our file 
                    While (line = sReader.ReadLine()) IsNot Nothing 
                        'display the output in the screen 
                        Console.WriteLine(line) 
                    End While 
                End Using 
            Else 
                'notify that the file was not found 
                Console.WriteLine("File not found!") 
            End If 
            
            'pause and wait for the user. 
            Console.ReadLine() 
        End Sub 
    End Class 
End Namespace 
Wednesday, March 19, 2008 6:52:53 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tutorial
# Tuesday, February 26, 2008

I've gotten this question 3 times in different flavors since last week and I've decided that it's time to post the solution in my blog. I've added comments on the code to explain what every line is doing.

The code below will demonstrate how you can read the assembly information in both C# and VB.NET.

[------------------ C# ------------------]

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;

namespace KeithRull.ReadingAssemblyInformation
{
    /// <summary>
    /// A sample program that demonstrates how to get the
    /// Assembly information. This is useful when you want
    /// to see the version of your class library.
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            //create a new assembly object that would signify
            //the current running assembly
            Assembly currentAssembly = Assembly.GetExecutingAssembly();

            //create the dictionary object that would contain
            //all the information about our assembly
            Dictionary<string, string> dictionaryOfProperties 
                        = GetAssemblyInfoDictionary(currentAssembly);

            //iterate thru each key in the dictionary
            foreach (string key in dictionaryOfProperties.Keys)
            {
                //print the key and its value
                Console.WriteLine("{0}: {1}", key, dictionaryOfProperties[key]);
            }

            //pause
            Console.ReadLine();

        }

        /// <summary>
        /// A method that returns a Dictionary of Assembly properties
        /// </summary>
        /// <param name="selectedAssembly">The assembly to inspect</param>
        /// <returns>The dictrionary containing the assembly information</returns>
        public static Dictionary<string, string> GetAssemblyInfoDictionary(Assembly selectedAssembly)
        {
            //Create the dictionary
            Dictionary<string, string> dictionaryOfProperties 
                                    = new Dictionary<string, string>();

            //get the location of the assembly
            string assemblyPath = selectedAssembly.Location;
            //add the assembly location to out dictionary
            dictionaryOfProperties.Add("AssemblyLocation", assemblyPath);

            //create the AssemblyName object based on our Assembly
            //this will enable us to get the version information
            //and other properties related to our assembly
            AssemblyName assemblyName = selectedAssembly.GetName();

            //add the FullName of out assembly
            dictionaryOfProperties.Add("AssemblyFullName", assemblyName.FullName);
            dictionaryOfProperties.Add("AssemblyName", assemblyName.FullName);

            //add the assembly version information
            dictionaryOfProperties.Add("Version", assemblyName.Version.ToString());
            dictionaryOfProperties.Add("Version.Major", assemblyName.Version.Major.ToString());
            dictionaryOfProperties.Add("Version.Minor", assemblyName.Version.Minor.ToString());
            dictionaryOfProperties.Add("Version.Build", assemblyName.Version.Build.ToString());
            dictionaryOfProperties.Add("Version.Revision", assemblyName.Version.Revision.ToString());
            
            //add the creation time
            DateTime creationTime = File.GetCreationTime(assemblyPath);
            dictionaryOfProperties.Add("CreationTime", creationTime.ToString());

            //add the last write time
            DateTime lastWriteTime = File.GetLastWriteTime(assemblyPath);
            dictionaryOfProperties.Add("LastWriteTime", creationTime.ToString());

            //return our dictionary obeject
            return dictionaryOfProperties;
        }
    }
}

[------------------ VB.NET ------------------]

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Reflection
Imports System.IO

Namespace KeithRull.ReadingAssemblyInformation
    ''' <summary> 
    ''' A sample program that demonstrates how to get the 
    ''' Assembly information. This is useful when you want 
    ''' to see the version of your class library. 
    ''' </summary> 
    Module Program
        Sub Main(ByVal args As String())
            'create a new assembly object that would signify 
            'the current running assembly 
            Dim currentAssembly As Assembly = Assembly.GetExecutingAssembly()

            'create the dictionary object that would contain 
            'all the information about our assembly 
            Dim dictionaryOfProperties As Dictionary(Of String, String) = GetAssemblyInfoDictionary(currentAssembly)

            'iterate thru each key in the dictionary 
            For Each key As String In dictionaryOfProperties.Keys
                'print the key and its value 
                Console.WriteLine("{0}: {1}", key, dictionaryOfProperties(key))
            Next

            'pause 
            Console.ReadLine()

        End Sub

        ''' <summary> 
        ''' A method that returns a Dictionary of Assembly properties 
        ''' </summary> 
        ''' <param name="selectedAssembly">The assembly to inspect</param> 
        ''' <returns>The dictrionary containing the assembly information</returns> 
        Public Function GetAssemblyInfoDictionary(ByVal selectedAssembly As Assembly) As Dictionary(Of String, String)
            'Create the dictionary 
            Dim dictionaryOfProperties As New Dictionary(Of String, String)()

            'get the location of the assembly 
            Dim assemblyPath As String = selectedAssembly.Location
            'add the assembly location to out dictionary 
            dictionaryOfProperties.Add("AssemblyLocation", assemblyPath)

            'create the AssemblyName object based on our Assembly 
            'this will enable us to get the version information 
            'and other properties related to our assembly 
            Dim assemblyName As AssemblyName = selectedAssembly.GetName()

            'add the FullName of our assembly 
            dictionaryOfProperties.Add("AssemblyFullName", assemblyName.FullName)
            'add the Name of the assembly
            dictionaryOfProperties.Add("AssemblyName", assemblyName.Name)

            'add the assembly version information 
            dictionaryOfProperties.Add("Version", assemblyName.Version.ToString())
            dictionaryOfProperties.Add("Version.Major", assemblyName.Version.Major.ToString())
            dictionaryOfProperties.Add("Version.Minor", assemblyName.Version.Minor.ToString())
            dictionaryOfProperties.Add("Version.Build", assemblyName.Version.Build.ToString())
            dictionaryOfProperties.Add("Version.Revision", assemblyName.Version.Revision.ToString())

            'add the creation time 
            Dim creationTime As DateTime = File.GetCreationTime(assemblyPath)
            dictionaryOfProperties.Add("CreationTime", creationTime.ToString())

            'add the last write time 
            Dim lastWriteTime As DateTime = File.GetLastWriteTime(assemblyPath)
            dictionaryOfProperties.Add("LastWriteTime", creationTime.ToString())

            'return our dictionary obeject 
            Return dictionaryOfProperties
        End Function
    End Module
End Namespace

HTH ;)

 

Tuesday, February 26, 2008 5:16:53 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tutorial
# Monday, February 25, 2008

I've been working on ASP.NET AJAX eversince it's beta days and the UpdateProgress and UpdatePanel has been my bestfriend since day one. I've learned a few tricks while using ASP.NET and today I'd like to share with you several ways to customize the look and feel of you UpdateProgress control with this sample solution. I have created a sample application that would demonstrate different ways to position your UpdateProgress control in the web browser. 

The samples included in the solution is as follows:

  • Sample 1

    The usual ASP.NET AJAX UpdateProgress control usage. This demonstrates the typical use of the UpdateProgress control in an application

  • Sample 2

    An ASP.NET AJAX UpdateProgress control positioned in the top right of the browser. (GMAIL like behavior)

  • Sample 3

    An ASP.NET AJAX UpdateProgress control positioned in the top right of the browser with a transparent gray background. (GMAIL like behavior)

  • Sample 4

    An ASP.NET AJAX UpdateProgress control positioned in the top right of the browser with a transparent gray background and the notification following the scrollbar position (fixed position).

  • Sample 5

    An ASP.NET AJAX UpdateProgress control positioned in the middle of the browser with a transparent gray background.

  • Sample 6

    An ASP.NET AJAX UpdateProgress control positioned in the middle of the browser with a transparent gray background and the notification following the scrollbar position (fixed position).

  • Sample 7

    An ASP.NET AJAX UpdateProgress control that uses the AlwaysVisibleControlExtender trick to place the progress notification at the top right of the browser.

  • Sample 8

    An ASP.NET AJAX UpdateProgress control that uses the AlwaysVisibleControlExtender trick to place the progress notification at the middle of the browser.

The project includes all aspx files, images and stylesheets that demonstrates effective UpdateProgress notifications. You can checkout the running sample of this ASP.NET AJAX project at the DevPinoy.org demo site

I hope what I shared with you can be useful in your daily life as a .NET developer. If you are interested you can download the source code for the whole project here: KeithRull.BuildingABetterAJAXLoadingNotification.zip (191.48 KB)

Monday, February 25, 2008 11:13:42 PM (GMT Standard Time, UTC+00:00)  #    Comments [4] -
.NET | AJAX | ASP.NET | Tutorial
# Thursday, February 07, 2008
Here's a small trick i use alot. Question: What's the easiest way to get the distict rows of data in a DataTable and DataView in .NET 2.0? Answer: The easiest way to get distinct DataRows in a DataTable or DataView is by using the DataView.ToTable() method. Here is a demonstration
Thursday, February 07, 2008 9:06:10 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Monday, February 04, 2008
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.
Monday, February 04, 2008 6:00:07 PM (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.NET | Fun Stuff | Tutorial
# Friday, February 01, 2008
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.
Friday, February 01, 2008 9:15:19 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | Tutorial
# Monday, January 28, 2008
Woohoo! That was a great Code Camp. Thanks to Woody and the gang for making this event happen. It was a fun and knowledge-filled event. I even got swags (a few books, a shirt, a small bag and a gym cup from Avanade)...
Monday, January 28, 2008 6:03:49 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | All about Keith | Life | Rant | Tech News and Issues | Code Camp
# Saturday, January 26, 2008

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!

Saturday, January 26, 2008 1:17:37 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | All about Keith | Fun Stuff | Life | Tech News and Issues | Your Career | Code Camp
# Friday, January 25, 2008

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)

Friday, January 25, 2008 8:59:16 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | Tutorial
# Wednesday, January 23, 2008

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.

Wednesday, January 23, 2008 7:58:09 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | Tutorial
# Tuesday, January 22, 2008

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!

 

Tuesday, January 22, 2008 7:58:26 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | Rant | SQL
# Saturday, January 05, 2008
One of the cool feature (if used correctly) added to .NET 3.x is Extension Methods which enables you to extend an specific type by adding your own methods to it. It's useful in cases where you want to extend a library that you dont have access to the source.
Saturday, January 05, 2008 12:42:16 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Friday, January 04, 2008

Just in case you are interested... Microsoft is giving away Free E-Books of 3 great books



Introducing Microsoft LINQ
by Paolo Pialorsi and Marco Russo

ISBN: 9780735623910

Introducing Microsoft ASP.NET AJAX
by Dino Esposito

ISBN: 9780735624139

Introducing Microsoft Silverlight 1.0
by Laurence Moroney

ISBN: 9780735625396

 

Get them here!

Friday, January 04, 2008 9:16:54 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET
# Wednesday, December 26, 2007

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!

Wednesday, December 26, 2007 7:26:04 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | Fun Stuff
# Monday, December 17, 2007

I've been banging .NET 3.5 lately and this rendezvouz with LINQ (Language Integrated Query) has been making my brain smile alot. I mean, how can you not like something so easy and well defined and makes your life as developer alot easier.

Anyhow, I just wanted to post my LINQ cheat sheet. It's not much and it's not even complete yet (I call this part 1.1). It consist of a few snippets that you might commonly do when doing LINQ processing. I'm planning to update this and hopefully I could find time this week to add some more piece of code that would demonstrate the other LINQ topics that I missed.

Anyway, here's some LINQ snippets:

//create our PersonService object
PersonService ps = new PersonService();

//get the list of person
PersonList listOfPerson = ps.GetPersonList();

//get a list of people with Gender set to Male
var maleOnlyList =
from l
in listOfPerson
where l.Gender == Gender.Male
select l;

//get a list of people with Gender set to female
//and declaring the returned fields
var femaleOnlyList =
from l
in listOfPerson
where l.Gender == Gender.Female
select new {
l.PersonID,
l.FirstName,
l.MiddleName,
l.LastName,
l.Email,
l.BirthDate,
l.Gender,
l.DateCreated };

//specify age
int selectedAge = 25;
//get a list of people with age greater than 25
var ageIsGreaterThan25 =
from l
in listOfPerson
where l.BirthDate >= DateTime.Now.AddYears(-selectedAge)
select l;

//get a list of people with a birthdate between a specified range
var birthdateBetweenRange =
from l
in listOfPerson
where
l.BirthDate >= DateTime.Parse("1/1/1980")
&& l.BirthDate <= DateTime.Parse("1/1/1981")
select l;


//order the result by lastname
var orderByLastNameSimple =
from l
in listOfPerson
orderby l.LastName
select l;

//order the list by birthdate and lastname
var orderByMultiple =
from l
in listOfPerson
orderby l.BirthDate descending, l.LastName ascending
select l;

//take three records
var takeThree = listOfPerson.Take(3);

//go to the 10th record and then take 3 records from there
var skipTenTakeThree = listOfPerson.Skip(10).Take(3);

//skip up until the Lastname is not equal to Thornton
var skipWhile = listOfPerson.SkipWhile(n => n.LastName != "Thornton");

P.S: There's more LINQ examples at the MSDN website.

 

Monday, December 17, 2007 8:36:31 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Wednesday, December 12, 2007

Wow, NBA.com is now joining the silverlight bandwagon.

NEW YORK — Dec. 10, 2007 — The National Basketball Association (NBA) will employ Microsoft Silverlight on NBA.com to further enhance the online video experience for NBA fans around the world. Microsoft Silverlight, a cross-browser, multiplatform plug-in for delivering the next generation of media experiences and rich interactive applications for the Web, will also be utilized on WNBA.com and NBADevelopmentLeague.com.

NBA.com will feature a full-screen NBA photo gallery, offer video highlights and deliver additional interactive applications throughout the site using Microsoft Silverlight. Through the use of Microsoft Corp.’s new application, the NBA will be able to provide further access to its extensive digital video library, integrate the video experience seamlessly into the site, and ultimately provide fans with access to more online video features.

Read the full article here...

I'm a big NBA fan and i frequently visit the site (atleast 4 times a day). Basketball is one of the most popular sports in the world and this partnership I think would greatly boost the adoption of Silverlight in the mainstream.

One more reason why i should kick my gears up another notch with silverlight.

Wednesday, December 12, 2007 10:36:34 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
# Tuesday, December 11, 2007
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
Tuesday, December 11, 2007 7:39:31 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | SQL
# Wednesday, November 28, 2007

I'm still a big fan of VB.NET even if I haven't touched a single VB.NET code in a year and one the biggest VB.NET fanboy I know has just started a website all about the good things you can do with VB.NET. Chris Williams (VB.NET MVP) has just started a website called ILoveVB.NET. The idea is to build a community that would champion the cause of VB.NET(which is to make the world known that VB.NET is a first class programming language and not a code kiddies toy anymore).

Here's the official message from Chris Williams:

This is the place where we show off all the amazingly cool stuff you can do with VB.NET.

If you're passionate about VB.NET, or you have an interesting project or maybe you're providing community support to a technology that doesn't currently have language parity, then you've come to the right place. We will gladly host your project and blog(s).

If you're looking for answers, you may find them here as well. If you're tired of looking everywhere for code samples and only finding C#, keep checking back here. We're making contact with the product teams and working towards getting the samples and SDKs you want.

Once again, thank you for stopping by. If you need anything, feel free to ask.

Chris Williams

Man, I bet you Paul, Carl, Bill and the VB.NET MVPs are going to be excited about this!

Wednesday, November 28, 2007 7:20:57 PM (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.NET | Tech News and Issues

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)

Wednesday, November 28, 2007 6:08:02 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | Fun Stuff

I've just finished downloading Microsoft Visual Studio 2008 bits last night and I think I'm about ready to install it on my VPC (yup, I don't want to install it yet on my real machine.).  I'm really excited about this new release since it looks really really promising. I've seen blogs giving it high praise and some not giving it a nod of acceptance(a few I should say) but for me it's the best Visual Studio to come out yet. I've been playing with the beta version since last year and really happy with this new release from the VS Team.

I know there are several things to consider before you install this version and I'm really glad that Jon made this list to keep as sane when installing/upgrading to Visual studio 2008. Great job Jon!

Now I'm ready to rock!

Wednesday, November 28, 2007 5:19:26 PM (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.NET | Tech News and Issues
# Tuesday, November 20, 2007

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.

Tuesday, November 20, 2007 6:57:58 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff
# Monday, November 19, 2007

Oh boy! Oh boy! Oh boy! Talk about geeky goodness! In case you miss the news, VS 2008 is ready for download for MSDN subscribers. Not an MSDN subscriber? Fear not! VS Express 2008 was also shipped today!

Want to learn whats on VS2008? Check out the video tutorials here or just read what ScottGu has to say.

Jeff also mentioned that Team Suite and TFS is also available and that the 90 day trial(in case you are not an MSDN subsriber) can be downloaded from the MSDN website.

Monday, November 19, 2007 8:19:50 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
# Saturday, November 17, 2007

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)

Saturday, November 17, 2007 12:02:24 AM (GMT Standard Time, UTC+00:00)  #    Comments [5] -
.NET | Fun Stuff
# Wednesday, November 07, 2007

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.

Wednesday, November 07, 2007 8:34:49 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | Tech News and Issues

Yesterday I wrote a post as about adding a mailto link to a GridViewColumn and was surprised with the amount of response i got via email regarding that topic. One person asked me a frequently asked question which i realized I haven't tackled on my blog yet. The question was:

Keith,

   Is it possible to add javascript code in a GridView Column? I'd like to attach a javascript function to a hyperlink that will show an alert that show's the selected Name whenever a user clicks that link.

Thanks,

XXXXX (Identity hidden)

The answer to the question is Yes you can add javascript code to a control inside your GridView and believe it or not there is two ways to do it. There's the easy way and there's the complicated but not hard to do way.

Let's start with the easy way. The easiest way to do this is by create a TemplateField in your GridView and add a HyperLink control inside the ItemTemplate of your TemplateField. Next, you need to modify the NavigateUrl property of the HyperLink control to something similar to this:

<asp:TemplateField>
   <ItemTemplate>
      <asp:HyperLink ID="selectionHyperLink" 
                     runat="server" 
                     NavigateUrl='<%# Eval("Name", "javascript:showMessage(&#039;{0}&#039;);") %>'
                     Text="Select" />
   </ItemTemplate>
</asp:TemplateField>

What the code on my NavigateUrl property does is that it attaches a javascript function called showMessage passing a parameter which in this case is a value from column taken from the binded datasource of the GridView. The javascript for the above code would like this:

<script language="javascript">
   function showMessage(personName)
   {
      alert("You clicked " + personName + "!");
   }
</script>

The second approach is adding a GridView_RowDataBound event to our GridView and add some control logic inside that event but first we need to modify our control attributes:

<asp:TemplateField>
   <ItemTemplate>
      <asp:HyperLink ID="selectionByCodeHyperLink" 
                     runat="server" 
                     Text="Select" />
   </ItemTemplate>
</asp:TemplateField>

As you can see i have removed the NavigateUrl attribute. The reason behind this is because i'll be feeding that information inside the GridViewDatabound event. To accomplish what we have accomplished on our first example we need to decide on two things: 1.) Do we want to use the same logic wherein we specify the javascript via the navigate url? or 2.) Do want to use the Control.Attribute.Add() method of the control to attach a onclick event to it.

Anyway, I'll leave that thinking to you and just show the code for both instead so that you can choose which approach is right for you:

Here's the code for the straight up NavigateUrl assignment of the javascript.

protected void peopleGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
   //determine if the row type is DataRow
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
      //find the hyperlink control in the GridView
      HyperLink hyperLink = (HyperLink)e.Row.FindControl("selectionByCodeHyperLink");

      //check whether the the hyperlink exist on our GridView
      if (hyperLink != null)
      {
         //get the dataitem assigned to the row.
         //assume that the dataitem is of type Person
         Person person = (Person)e.Row.DataItem;

         //assign our javascript code
         hyperLink.NavigateUrl = String.Format("javascript:showMessage('{0}');", person.Name);
      }
   }
}

As you can see, all we did was assign the same string that we assigned on our first example. Below is the add attribute version of the above code.

protected void peopleGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
   //determine if the row type is DataRow
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
      //find the hyperlink control in the GridView
      HyperLink hyperLink = (HyperLink)e.Row.FindControl("selectionByCodeHyperLink");

      //check whether the the hyperlink exist on our GridView
      if (hyperLink != null)
      {
         //get the dataitem assigned to the row.
         //assume that the dataitem is of type Person
         Person person = (Person)e.Row.DataItem;

         //add this code to make the text act as hyperlink
         hyperLink.NavigateUrl = "javascript:;";
         //add our javascript attribute
         hyperLink.Attributes.Add("onclick",String.Format("javascript:showMessage('{0}');", person.Name));
      }
   }
}

And that's it! That's how you add javascript code to controls inside a GridView. Hope that you learned something from this tutorial. 

Want to download the source for this project? Get it here: KeithRull.MappingLinksInGridViews.zip (3.28 KB)

Wednesday, November 07, 2007 7:41:23 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET

I was reading my site refferers today when I saw an interesting refferer query that came from Google. Three people got to my site after typing this phrase "hyperlink databind gridview mailto". I went to the the Google results page and immediately went to the page the was indexed by Google and upon futher review i found that my page wasn't really the answer to those persons question. Out of my curiousity i fired Visual Studio 2005 up and tried to add mailto link to a GridView using the HyperlinkField as my base.

<asp:HyperLinkField  DataNavigateUrlFields="Email" 
                     DataNavigateUrlFormatString="mailto:{0}"
                     DataTextField="Email" Text="Email me!" />

I ran the project thinking that this should work because this always works for me when i do same process for URLs. To my surprise, it didn't. For some unknown reason the column appears as plain text without any href attribute in sight. I went back to the HTML and checked it twice to see if maybe i missed something on the control attributes... hmmm, eveything looks ok. After a few minutes of playing around I resorted to the technique that never fails.. I converted the column to a TemplateField.

<asp:TemplateField HeaderText="Email">
   <ItemTemplate>
      <asp:HyperLink ID="emailHyperLink" 
                     runat="server" 
                     NavigateUrl='<%# Eval("Email", "mailto:{0}") %>'
                     Text='<%# Eval("Email") %>' />
   </ItemTemplate>
</asp:TemplateField>

Run the project again and sure enough, it worked. Huh! Weird! Anybody who knows what happened?

Wednesday, November 07, 2007 12:02:15 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Tuesday, November 06, 2007

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!

Tuesday, November 06, 2007 8:21:58 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff
# Friday, November 02, 2007
We are currently using Gemini here for our issue tracking and we love it eversince we had it installed in our server but this joy of Gemini has not stopped us from searching a better alternative because there are things that we don't like about it(specially that cost part of the software). That lead me to scour the web to find alternatives that we might consider in the future as a viable replacement for our long trusted Gemini. to my surprise I only found 4 open source ASP.NET bug tracking solution compared to the gargantuan list that I saw for PHP. Below are the 4 applications that I found and my comment about each project.
Friday, November 02, 2007 7:41:15 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
# Thursday, November 01, 2007

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."

Thursday, November 01, 2007 10:07:10 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff | Tech News and Issues | Java
A few days ago a forum question was posted in DevPinoy.org on how to read the values of a inside a GridViewRow and assigning them to a Label control(or TextBox) when that row is selected. I wasn't able to reply to that thread early due to time constraints with a project I had at that time but I told myself that I'm going to answer it as soon as my schedule frees up. This article is a bit late(about 3 days to be exact) but i still hope that this answers that persons question.
Thursday, November 01, 2007 9:33:42 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Wednesday, October 31, 2007
A colleague of mine asked me today about adding custom eventhandlers to a class. I explained the whole process to him and ended up doing a demo on how to accomplish this task. After a we were done talking it dawned to me that I haven't had the chance to blog code in weeks I think its a good time to show something that is pretty helpful when you understand how to use it.
Wednesday, October 31, 2007 8:39:22 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Monday, October 29, 2007

Modchip is going to love this!

ASP.NET: ASM to IL compiler

[Via Joe Stagnner]

Monday, October 29, 2007 11:14:01 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET
# Friday, September 07, 2007

New to C#? Need to know whats on C# 3.0? Then download this 500 page book coutersy of Microsoft. It's the most complete C# reference you can find and it is primarily written by the engineers of the C# language

Go download it here!

Thank you Charlie for the link!

Friday, September 07, 2007 5:58:37 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Monday, August 27, 2007

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!");
}

Monday, August 27, 2007 11:53:02 PM (GMT Daylight Time, UTC+01:00)  #    Comments [2] -
.NET | Fun Stuff
# Saturday, June 09, 2007
A few weeks ago I wrote an article about merging word documents in C# and got great response about the article. One of the readers, Abhi, had an interesting problem. The application he wrote was throwing this error: Word was unable to read this document. It may be corrupt. Try one or more of the following: * Open and Repair the file. * Open the file with the Text Recovery converter.
Saturday, June 09, 2007 6:20:55 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Saturday, May 26, 2007
A friend asked me for help today about a segment of code that was giving him a headache. After looking at the code I immediately told him the problem. Can you spot the problem too without compiling the VB code? Why is it happening?
Saturday, May 26, 2007 1:06:49 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Thursday, May 24, 2007
I had a pretty laidback today because one of my projects was halted due some requirements issue(we have just finished phase 1 and the client already wants to start phase 2 but they dont know what the want yet) so i was assigned to help one of my colleagues in a problem that they were having in their project. The problem was that they were trying to merge multiple Microsoft Word Documents into one file and for some reason the solution that they have implemented was not doing the job. They had this function that reads bits and bytes of the document and then combines those bytes into a single file. Yikes!
Thursday, May 24, 2007 12:24:11 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, May 16, 2007

This is weird but everytime I go to a conference and somebody speaks about Web Apps they always talk about why people should use custom errors instead of throwing the Yellow Page of Death. Just this morning I went to the ASP.NET website to check on the forums and this is what was displayed on my screen:

Huh? No custom errors? Hmmm.. seems like they are breaking their own rules.

Anyway, A friend of mine had this joke exception code that slipped to their production and one of the accountants called him and was very scared because she thought she made a huge mistake.

Yikes! It was mean. Even if its a joke it is really mean. Striking fear to your users is not a good thing at all. If they had a custom error page then this would not have happened.

This reminded me of the IKEA incident I saw from D'Arcy Lussier a few days ago.

Custom errors gives the easy feeling to the users. It doesn't scare them to death and it makes them more comfortable with your system knowing that it can recover from such a fatal crash.

Oh well, I'm just glad I got this baby showing up at devpinoy ;)

Wednesday, May 16, 2007 7:13:33 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | All about Keith | Tech News and Issues
# Tuesday, May 15, 2007
Man, oh Man, oh Man! Another timesaver to add in my development toolbox. Jerry Jarell has just released NStub which is a Unit Test Generator for .NET Assemblies and man it looks really promising.
Tuesday, May 15, 2007 7:15:10 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Unit Testing | TDD
# Thursday, May 10, 2007
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!
Thursday, May 10, 2007 1:57:28 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2] -
.NET | Fun Stuff
# Tuesday, April 24, 2007

I remember seeing this last year when i was trying to put my hands wet with WPF. It's a pretty good five day course courtesy of Karsten Januszewski which you can complete just by reading and applying the things that you can find out from his set of useful links. A pretty good primer to WPF if you ask me(although i think there are sveral new articles in the past few months that i believe should be added to the list).

Learn from Karsten Januszewski here.

Tuesday, April 24, 2007 6:45:24 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Friday, March 09, 2007
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.
Friday, March 09, 2007 11:54:03 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Fun Stuff
# Wednesday, February 28, 2007

This is the first part our series about ADO.NET which is part of our Back To The Basic Series which is a series designed to teach beginners about the benefits of ADO.NET and to show how easy it is to use the ADO.NET in a short 10 to 15 minute video using Tagalog as the medium.  Our idea is to start from small demo application and build from there by adding new functionalities and refactoring the sample application on each part of the series.

On this demo you'll learn the basics of creating a connection to SQL Server, using a Universal DataLink to automatically generate your connection string to a database server, populating a DataSet using a SqlDataAdapter and assigning a DataSet to our GridView control.

>> Click here to view the video <<

Comments and suggestions are welcome! :)

Wednesday, February 28, 2007 6:36:26 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues | Your Career | DevCast
# Friday, February 23, 2007
Don't you just love Generics? I mean, it helps you alot in so many ways that everytime you are asked about why you love Generics all you could say is "Uh, type safety?".. Err! We need to change that! There are alot more things to like about Generics than just type safety... Like code organization... more readable(if you ask me) code... and of course.. type safety(what? i thought you said there's more) :P
Friday, February 23, 2007 11:39:54 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Saturday, January 27, 2007

Hey guys! I'm here at code camp right now in CalState Fullerton and its been amazing. Kudos to the CodeCamp organizers!

Well.. i wast late abit.. so i wasnt able to listen to Woody and Michelle do their early morning speech(heheh, this is how one of the guys i met here in the camp described it). The registration was fast and really organized. I like how they have the parking directions posted everywhere because last year was a mess specially if you dont know the area(well, one can argue that if you can read parking lot signs then you wont have a problem since the SoCal codecamp website said that the parking for the event is on parking lot F).

One thing i noticed is that there is no schedule given to attendies. Last year they gave away papers containing schedules on where and when to find a specific talk. The good thing this year is that there is internet connectivity so you can check the posted schedule on the CodeCamp website which is non-existent last year.

I'll be updating this on every session i go to(hope i did this last year so that i could have warned people about not going to $%&*^* session(name encrypted to protect that persons ego) because he just reads slides and cant even give a good answer(sample response: "Uh, try searching that on the internet.. again i am just relaying to you what i have read online").

The notes below are from my scratchpad courtesy of Notepad++. This is a work in progress so dont bug me if theres typos on it. :D

9:00 - Mark Rosenberg's talk about Stored Procedure and below is the juice of his talk

[13 tips on  optimizing your stored procedures]
use stored procedures instead of heavy-duty querries
include set no count to on
call using fully qualified name
if you are returning a single integer user a return statement rather than returning one value as a record set
 Output value is for errors only, return value for values you want to be returned by the procedures.
SQL dot notations in 2005 helps in grouping objects in the database.
use the sp_executesql storedprocedure instead of execute
use the sp_executesql instead if temporary stored procedures
breakdown large stored procedures into smaller stored procedures
use @Table variables instead of #Table because #Table lives in tempdb and @table is created in memory.
avoid using ddl statements in your stored procedures
add with recompile option to create procedure statement if you know the query will change each time it id run
use the sql server profiler to determine which stored procedures have been recompiled to often
avoid using having clause
 << i think there are scenarios wherein a having clause is faster than a where clause.. so if you ask me i'll tell you that this suggestion is on a case to case basis.
use union all instead of union

#temp tables
dont use them
ok, sometimes bbut not often
 gettingresults from stored procedure(since you cant use recompile on them)
always create the taable then fill it(helps  with tempdb locking)can index (which can help performance)
dont use select into

@table variables
fster anf more efficient
not good for large datasets that would be saved to disk anyway
less table locking, logging
unfortunately no indexes, but you can have a primary key by using unique or primary key constraint.
much better during transactions
can only be used itn functions stored procedures and batches
when used in stored procedures there is less recompiling
cant apply alter table
cant use select into

dont use cursors if you can help it(use while clause instead)
filter as early in your stored procedure as possible
never select all the columns
sometimes a transaction can actually improve performance(but not often)

quote: "use print statements on querries too count performance" - i greatly disagree on this one.. i think its easier to look at it on the profiler plus adding print statements add clutter in your procedures.

10:15 - Robert Kozak's talk about Attribute Based Programming

He built a nice framework and demoed how to use the same set of classes to do different things. I love how he built his form by just mere UserControls and no code on the form itself. I agree with him when he said that seperation of concern is the way to go in builfing applications. I wasnt able to take down alot of notes because i was enamoured by the amount of cool stuff he was showcasing in his demo. i was able to take note of the third slide though.

 A properly designed framework will
    promote proper seperation between interface, implementation and user interface
    promote lose coupling and strong cohesion
    promote reusability of code(write once use everywhere)
    promotes RAD of production quality code
    wait theres more: automatic API for your application

1:00 - Bill Sheldon's ASP.NET Membership Customization << currently in progress  

Saturday, January 27, 2007 7:30:23 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | SQL | Tech News and Issues | Your Career
# Thursday, January 11, 2007
The guys from Asp.Net Resources created a compilation of code snippets that you can use as Cheat Sheets when working with the ASP.NET AJAX Library.
Thursday, January 11, 2007 6:38:08 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Wednesday, January 03, 2007

Seems like i learn something new everyday...

public string Name
{
   get
   {
      return name;
   }
   protected set
   {
      name = value;
   }
}

I never knew that i could put an accessibility level to the 'set' portion of my property. This technique is called Asymmetric Accessor Accessibility. Read more here.

Wednesday, January 03, 2007 12:53:38 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
We had a programming quiz couple of weeks back at Devpinoy.org.. there where 5 people who dared to take on the quiz but sadly nobody got the correct answer after two rounds of testing(i guess i was pretty strict with my test cases) in the end i decided to just give the prize to the person who got the most correct program(15 out of 17 test cases). All in all it was a fun event... anyway, i decided to post my answer to the quiz that i gave so that people could see how i solved the quiz(btw, this is not perfectly refactored so don't whine if you see some code smells in it...)
Wednesday, January 03, 2007 12:47:36 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Tuesday, December 26, 2006
A simple demo that shows how to create a Master-Detail View in ASP.NET.
Tuesday, December 26, 2006 10:52:18 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Wednesday, December 06, 2006
Anyway, I have been coding crazy as always when i found out that one of the Image Buttons in my project is missing a grayscale hover image. Whats crazy is that i didn't have Photoshop in my PC that time. The detail-oriented guy inside of me made the decision that i should have that image created because it is bothering me whenever i hover on an empty image placeholder. And so, I was of to the races...
Wednesday, December 06, 2006 12:50:41 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Thursday, October 19, 2006
I have always been a Sql junkie. Analyzing data was one of the things that I enjoy alot... Sometimes this task also involves writing gargantuan scripts.. and that is where the problem starts. Finding what stored procedure or view that uses a specific table could give you a hard time since SQL server doesn't have a feature that enables you to look at each and every stored procedure and view. usually when this problem arises we tend to open each and every script that we could think of(when this happens i usually script my database, open the generated .sql file in note pad and start using the Find function to search for the table/view name).
Thursday, October 19, 2006 10:20:51 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Friday, October 13, 2006
Joshua Flanagan has just released library he calls "ReadableRegEx"(I preffer calling it ReadEx) which is basically library that envisions itself to create a more readable(friendlier) RegularExpression code wrapper.
Friday, October 13, 2006 8:56:19 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Thursday, October 12, 2006
After creating this article, i realized that i can use a new utility in my toolbox. A Font Viewer. I don't want to download a new spyware so decided to code a simple one, something that i could use from time to time whenever i have the need to view a font before placing it on my Photoshop design(i do photoshop and flash on the side in my current job).
Thursday, October 12, 2006 12:49:16 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, October 11, 2006
This is a really basic stuff that alot of developers tend to forget(just like me :D)
Wednesday, October 11, 2006 9:28:28 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, September 27, 2006
After reviewing my first example.. i realized that doing reflection is not the easy way to do get the known color collection(thanks to Chris Vega who pointed to me the Enum called KnownColor which basically contains .NET known colors). Somebody also told me that the demo would be nicer if the colors are real images instead of just painting a panel(which makes really sense if you are thinking of saving the generated image in your desktop). With this suggestions i decided to create a revised version of our Color Chart Generator.
Wednesday, September 27, 2006 1:25:35 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Monday, September 25, 2006
I had a little downtime today so i decided to create something useful(ala coding4fun) and one of the things that i wish i have in my toolbox is an .NET color chart since most of the time i tend to look at what colors i could use when matching my controls with my UI's theme(stylesheets? nah, that only works for the web.. how about if its a windows app? see! 'nuf sed!). Plus, i'd like to play with alittle bit of Reflection today and some basic Generics(hmmm, seems like i'm already dead hooked with this one)
Monday, September 25, 2006 8:37:44 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Saturday, September 23, 2006
I'll be at the So Cal .Net Tech Summit tommorow at Irvine Hilton, Irvine CA.
Saturday, September 23, 2006 7:53:57 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
I created a demo today about WMI to demostrate to a friend how to read his machine's information. The resulting application is listed below. It's funny because i was just supposed to show him how WMI works but ended up discussing IEnumerators, Hashtables, Enums, Strategy and Command Pattern plus a hint of Generics. Which might make this sample application a little bit too much out of it's title.
Saturday, September 23, 2006 1:25:50 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Monday, September 11, 2006
I decided to create this demo after seeing a post on devpinoy.org today that is asking about how to pass a value from a gridview to another page using HyperLinks. I decided to extend it a little bit so that we could show alittle bit more functionality.
Monday, September 11, 2006 2:14:16 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET
# Friday, September 08, 2006
I didn't realize that this property exist up until today when i was playing with a custom control that i was building (don't ask what control it is! ofcourse its a button). At first i don't what to do with it since its something that was just injected in the .NET 2.0 framework but upon reading and understanding the method i realized that i could insert a javascript call inside this method call.. something similar to what i got used to doing which is adding attributes to the control at the page_init level.
Friday, September 08, 2006 7:13:04 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Saturday, September 02, 2006
I did a .NET Code Auditing demo today with my current company and it went out really well! It was great that even thought i should do this on UG meetings(uh, i think that's too much dreaming keith! :p).
Saturday, September 02, 2006 12:18:07 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, August 30, 2006
I was browsing dotnet.org.za today when i stumbled into an interesting problem that Derek Adkins posted on his blog. The problem was about redirecting users to a page to a new blank window(_blank) instead of using the same window to display the redirected page. I don't know the full detail about why you would like to do that approach but i was immediately intrigue on how to solve it since i found that alot of people already viewed the post and no one seems to bother answering it(perhaps nobody really knows how to do it.. just a wild guess :)).
Wednesday, August 30, 2006 7:55:31 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2] -
.NET
# Sunday, August 27, 2006
.NET 2.0 introduces to us the class known as DBProviderFactories which enables us to access available providers on a machine. the DBProviderFactories class has method called GetFactoryClasses() that returns a DataTable that contains any class that is registered on the GAC that implements the DBProviderFactory class.
Sunday, August 27, 2006 10:56:54 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, August 09, 2006
One of the most common things in data presentation is setting up a drill-down view or what is more commonly known as a Master-detail view. In this example we'll try to creat a simple and quick demonstration on how this can be down.
Wednesday, August 09, 2006 12:59:00 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Monday, June 19, 2006
HowTo: Use SqlParameters to pass parameters to querries and stored procedures
Monday, June 19, 2006 11:44:20 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Friday, June 09, 2006
On the other hand, there is SQL SMO (SQL Management Objects) the new set of classes designed to be the next generation of classes to serve as replacement to the old SQL-DMO. In this article, i'll show you how to programmatically retrieve a list of available SQL Servers on the network and then retrieve the underlying databases on that SQL Server.
Friday, June 09, 2006 5:45:49 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, June 07, 2006
There are alot of ways to accomplish this. The simplest one is to use the sp_databases procedure. Here's some example that uses this stored procedure in conjunction with ADO.NET to consume the returned data.
Wednesday, June 07, 2006 10:58:02 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Friday, May 19, 2006

using System;
using System.Collections.Generic;
using System.Text;

namespace KeithRull.CS.Windows.DevCenterConsole
{
   class TemperatureCalculation
   {
      static void Main(string[] args)
      {
         this.ShowCalculation();
      }

      public void ShowCalculation()
      {
         double celsius = 44.5;

         double fahrenheit = CelsiusToFahrenheit(celsius);

         Console.WriteLine(fahrenheit);

         celsius = FahrenheitToCelsius(fahrenheit);

         Console.WriteLine(celsius);
      }

      //formulas are taken from
      //http://vathena.arc.nasa.gov/curric/weather/fahrcels.html

      public static double CelsiusToFahrenheit(double celsius)
      {
         /*
            Tc=(5/9)*(Tf-32) 
            Tc=temperature in degrees Celsius 
            Tf=temperature in degrees Fahrenheit 
         * */

         return (((0.9 / 0.5) * celsius) + 32);
      }

      public static double FahrenheitToCelsius(double fahrenheit)
      {
         /*
            Tf=(9/5)*Tc+32 
            Tc=temperature in degrees Celsius 
            Tf=temperature in degrees Fahrenheit 
         */

         return ((0.5 / 0.9) * (fahrenheit + 32));
      }
   }
}

pretty boring stuff...

Friday, May 19, 2006 1:19:18 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Tuesday, May 16, 2006
The Repeater control is probably the most over used control in the company that i currently work for. Almost every grid and listing has been built using this and i has made me nuts when i first started using it since i consider myself a Datagrid or a DataList guy. One of the things I hate about it is that usually, people try to format everything in a way that the Visual Studio.NET IDE barks, squels and cry. Adding those pesky <%%> all over the code which makes the page resemble an old ASP page that any developer who has thrown those coding style into the trash bin have nightmares and gloom scapes all over their nightly pundit rest. And since I am a good employee who follows strict coding guidelines and comply with it with utmost care.... i decided to embrace it rather than to do a holy war against this control. But i need to do something to make my life easier. With that I built this control...
Tuesday, May 16, 2006 12:25:30 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Saturday, May 13, 2006
A quick and easy way to load files and directories contained in a specified folder into a DataTable.
Saturday, May 13, 2006 2:30:06 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Monday, April 03, 2006
Working in the financial industry is a tough job, specially if you are in the IT department. There are alot of factors that you need to consider whenever you build an application.. theres those State Laws that you need to follow.. corporate guidelines... And at the end of the day after you have followed all these mumbo jumbo they only boil down to one specific topic... SECURITY. In the financial industry, an application must be secure at all times... in fact it should be 110% percent secure since you are dealing with peoples information, money and ALOT MORE MONEY.
Monday, April 03, 2006 7:24:52 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Sunday, April 02, 2006
How To: Check if application is already running
Sunday, April 02, 2006 8:53:40 AM (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET
# Monday, March 13, 2006
So here I am again.. bored the whole weekend without anything to do.. i played like 6 hours already of NBA LIve 2K6... have read a couple of chapters of Pro ADO.NET 2.0 by Sahil Malik (which I higly recommend! read my review in Amazon).. and have gone to the mall to get a new shirt for the brokers visit in the company which i work for (we need to wear suit and tie on the 15th). and still i havent gotten enough from the weekend... i guess its just the geek inside me thats telling me that he is not yet satisfied with just plain poking around with books and websites... so i called my friend Bill to ask him if he has something in mind that he wants me to help him with.. gladly! he has a problem on .wav files. he has this application wherein he wants to play a sound using a file from a website instead of a local file located on their server. It's an interesting problem since the SoundPlayer object only accepts a string poiting to the path of the .wav file and a stream object.
Monday, March 13, 2006 6:46:18 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Saturday, March 11, 2006
A friend of mine asked me today about encoding a string Base64. The scenario was that he has some files that he wants to be allowed for download on their company website and that he doesn't want the people who are downloading the files from his website to see where the downloads are coming from. The files are located in a folder inside the webserver outside of the virtual directory. The decision that the came up with was just to Base64 encode all the paths, pass ito to a new page via querystring and then decode that value on the download page. I gave it a shot and this is the code i gave him to serve as a guide on how he can effectively implement this.
Saturday, March 11, 2006 12:34:20 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Sunday, February 12, 2006
Finally! After 30 minutes of coding and 5 hours of modification(I wasn't satisfied on how it looks so i ended up revising it a couple of times.. :P This also includes me watching UFC at the same time:D) I have finally released the first beta of the DevPinoy Visitor Locator. DPVL is an application that displays the geographical locations of visitors in the DevPinoy.org website and plots those visitors location to a Google Map control.
Sunday, February 12, 2006 10:44:08 AM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | Tech News and Issues
# Tuesday, February 07, 2006
Lets see if there are some architechture people around here :) Looking at code below... scrutinize this class and tell me whats wrong with its structure... what design pattern closely resembles it.. and how you can improve it? the code is provided in both C# and VB.NET so that it would be easier for those people who prefer {} and non-case sensitivity to look at it!
Tuesday, February 07, 2006 10:50:24 PM (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | Tech News and Issues | Your Career
Want to know which APIs are now obsolete in .NET 2.0?
Tuesday, February 07, 2006 9:06:24 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues | Your Career
# Saturday, February 04, 2006
In this example we will look on how to iterate thru controls inside a GridView. We will try to get and display the contols value on the screen. We'll also show two ways on how to accomplish this using two different methods. One using the multiple loop construct and the other using the FindControl method. The following approach is applicable on all types of controls as long as the control implements GetEnumerator property in order to iterate on it.
Saturday, February 04, 2006 9:47:34 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Wednesday, January 04, 2006
Finally! We haved decided who won the "Why should Keith give me the VS.NET and SQL Server 2005 Cds!" contest. It was a tough judgement that me and our judge Woody Pewitt, my local Microsoft Evangelist need to take. As with any contest, we were hoping that alot of people would be joining the promo since the prize is every .NET Developers dream.. A package containing both VS.NET 2005 and SQL Server 2005. But then again, only the boldess survive and succeeds in this goal driven world.
Wednesday, January 04, 2006 6:59:22 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues | Your Career
# Wednesday, December 28, 2005
Here's the rss feed of articles from people who have joined the "Why should Keith give me the VS.NET and SQL Server 2005 Cds!" contest. Read it! There's already a couple of interesting post and we are waiting for more! :)
Wednesday, December 28, 2005 5:59:12 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
# Wednesday, December 21, 2005
On the first episode of devTrain, a weekly video training blog about the .NET framework that i started. I have decided to talk about one of the newest feature of .NET 2.0 which is Multiple Language Support. Although not recommended for development its good to know that you can write an application using multiple languages because this would increase the effort on maintaining a project, particularly if the application would be maitained by someone who is not familiar with all the programming language use(just imagine an application written in C#, VB.NET amd J#! Gee! that would be a total pain in the ass!).
Wednesday, December 21, 2005 12:39:10 AM (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.NET | Tech News and Issues | Your Career
# Thursday, December 15, 2005
Have you ever wanted to search yahoo and google at the same using the same browser screen??? Now you can do that using this website called Gahooyoogle. Gahooyoogle aggregates search result from the two popular website and displays their result on two seperate frame. Kinda trippy huh?! This is good for those people who love to multi-task while browsing the web.
Thursday, December 15, 2005 6:34:36 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Wednesday, December 14, 2005
I got really bored today that i decided to create a demo application. There's nothing cheesy about this one since it is a simple implementation of the DateDiff function in calculating the difference of two Date values in years. I was thinking of writing something more interesting than this one but I didn't have the time to create a real braintwisting app. Anyway, enough with the crappy introduction. Here's the methods written in both C# and VB.NET:
Wednesday, December 14, 2005 1:27:35 AM (GMT Standard Time, UTC+00:00)  #    Comments [2] -
.NET
# Tuesday, December 13, 2005
Rasterbation!
Tuesday, December 13, 2005 7:33:36 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Tuesday, October 11, 2005
Ei,, I have been receiving alot of emails lately asking me to share some details about the Mark Miller talk at the San Diego .Net Developers group last week. I'm sorry guys if I havent had the time to post the thoughts that were shared on that session, i have been a bit busy lately but dont worry... i have all my notes... all i need to do right now is organize those accumulated knowledge that i got from that session (i havent been in me lethal shape lately after doing some PHP coding for a friend... arrrgh!) so just stay put,, i'll serve you those talk lines soon!
Tuesday, October 11, 2005 5:38:04 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Tuesday, October 04, 2005
Gee! I'll be having a blast tommorow! Finally i'll get to see one of the guys that i look up to in Application Development and Design! Mark Miller, author of (among many other things) CodeRush, a productivity add-in for VS.NET and Refactor! an add-in to Visual Studio .NET that parses your Source code as you move through it and delivers context specific refactorings that automate the process of reorganizing and shaping your source to make it easier to read and cheaper to maintain. Mark will be the guest speaker tommorow on the group meeting of SD .NET Developers Group. His topic for tommorow would be about "The Science of Great UI " which is expect to be a a great session since i know Mr. Miller is very well-versed when it comes to designing application UI. The meeting will be on Qualcom Incorporated's San Diego Design Center - Auditorium at 6:00-9:00pm. There would be free pizza for the attendees courtesy of SMS.ac plus there would be raffle for some authentic San Diego .NET Developer swag.
Tuesday, October 04, 2005 3:04:21 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2] -
.NET | Tech News and Issues
# Tuesday, September 13, 2005
"People say that your favorite piece of code tells tales about you.." I want to hear it from you guys, whats your favorite piece code? I work alot with flat files and databases using c# and most of the time the processing of data takes rigorous implementation of string handlers.This takes me to realize that my probable bestfriends right now are the string functions.
Tuesday, September 13, 2005 5:54:54 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Friday, September 02, 2005
Filipinos join celebration of global Software Freedom Day THE PHILIPPINES will join more than 50 countries in the worldwide celebration of Software Freedom Day on September 10, 2005. Software Freedom Day is a global grassroots effort to promote public awareness and use of free and open source software (FOSS), according to its website -- softwarefreedomday.org.
Friday, September 02, 2005 4:43:59 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Tuesday, August 23, 2005
I saw a post in DevPinoy today asking for a demonstration on the disconnected data paradigm in ADO.NET is. With that i decided to create a sample program to illustrate how this works in ADO.NET.
Tuesday, August 23, 2005 4:43:02 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Friday, August 19, 2005
A collection of Coding Guidelines and Standards in C# and VB.NET
Friday, August 19, 2005 6:08:16 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Friday, August 12, 2005
Here is a quick example on how to access the registry in .NET. This example just loops thru each entry in the selected folder in the registry and prints the gathered information to the console.
Friday, August 12, 2005 8:55:32 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Thursday, July 14, 2005
In Part 1 and Part 2 of this series, we have used column mappings and index mapping to generate our csv files. These approach requires us to loop thru each colum to create the header, the loop thru again to create the rows. The problem with this approach is the amount of time spent in coding such procedures, well, its not that long... but considere this, if you could do something in a short amount of time with shorter lines of code and changing from one approach to another approach would make your life as a programmer a little bit better.. wouldn't you consider using that approach?
Thursday, July 14, 2005 11:05:12 PM (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET
# Wednesday, July 13, 2005
One thing that i really really really really want to be included on the next release of dasBlog is the ability to ping more than one feed site inside dasBlog. Something like pingomatic.com where you just select which website you want to send a ping when a new post is created. This feature would be really useful specially if you want to generate traffic to your blog by adding your blog to blog directories all over the internet universe.
Wednesday, July 13, 2005 11:56:41 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Sunday, July 10, 2005
In part 1 of this series i have showed to you how to use a IDataReader in creating a function that would generate a CSV file. On part 2 of this series I'm going to show you how to accomplish the same task but this time using a different object. We will still implement the same concept that we used in part 1 but shortening code by using native properties of a DataTable in accessing rows and columns.
Sunday, July 10, 2005 12:14:03 AM (GMT Daylight Time, UTC+01:00)  #    Comments [2] -
.NET
# Friday, July 08, 2005
As always, Mike Gunderloy made my eyes go 'BIG' after reading his article regarding some of his recomendations on how to use and manipulate strings in .NET 2.0. This post also gives some highlights about some key changes on System.String namespace and other aspects of using strings including the dreaded localization.
Friday, July 08, 2005 12:55:31 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Monday, July 04, 2005
Part 1 shows us how to create CSV files in both C# and VB.NET using techniques that were used back on the old days of ADO and OLEDB but implementing them using native ADO.NET objects(IDataReader) instead of recordsets.
Monday, July 04, 2005 8:24:24 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Sunday, July 03, 2005
Grasshopper: Visual Studio .NET IDE for Linux!
Sunday, July 03, 2005 5:43:57 PM (GMT Daylight Time, UTC+01:00)  #    Comments [1] -
.NET | Tech News and Issues
# Friday, July 01, 2005
File System Browsing: New Approach vs. Old Approach. this demonstrates how to use the a datable combined with filesystem objects to browse for folders and files. This also deffirentiate the different techniques in doing this task, from the classic programmers point of view, to the asp.net point of view
Friday, July 01, 2005 11:10:46 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Thursday, June 23, 2005
A tool that automatically formats your sql statement in any language (C#, Java, VB and Delphi)
Thursday, June 23, 2005 4:56:15 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | SQL | Tech News and Issues
# Thursday, June 09, 2005
SharpChess is an Open-Source game wholely developed using C#. This application was developed by Peter Hughes.
Thursday, June 09, 2005 7:40:49 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Thursday, June 02, 2005
With the advent of Visual Studio 2005 being released at the end of this year, wouldn't it be suitable to think about whats the future Visual Studio would be like?
Thursday, June 02, 2005 8:05:52 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Tuesday, May 24, 2005
Online C# Compiler
Tuesday, May 24, 2005 9:01:40 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET | Tech News and Issues
# Thursday, April 07, 2005
A comparisson between C# and VB.NET coding techniques and standard.
Thursday, April 07, 2005 11:10:07 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0] -
.NET
# Wednesday, March 16, 2005
This sample demonstrate how to sort and filter a DataTable using a DataView.
Wednesday, March 16, 2005 1:47:53 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Tuesday, March 15, 2005
Left, Right and Mid functions in C#
Tuesday, March 15, 2005 6:55:35 PM (GMT Standard Time, UTC+00:00)  #    Comments [3] -
.NET
# Monday, March 14, 2005
FreeTextBox or FCKeditor?
Monday, March 14, 2005 5:04:06 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
# Friday, March 11, 2005
Are you kidding me? VB6 on VS.NET IDE? HELL NO!!!
Friday, March 11, 2005 11:52:06 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
# Thursday, March 10, 2005
How to Generate random strings and numbers in C# and VB.NET
Thursday, March 10, 2005 5:13:52 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
Update regarding the tutorial i am writing.
Thursday, March 10, 2005 4:50:28 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Sunday, March 06, 2005
my decision to create an online tutorial on .net framework
Sunday, March 06, 2005 9:13:48 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
# Tuesday, March 01, 2005
A port to C# of the C++ ATL Web Service.
Tuesday, March 01, 2005 6:01:01 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET
Archive
<March 2010>
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
Keith Rull
Sign In
Statistics
Total Posts: 271
This Year: 0
This Month: 0
This Week: 0
Comments: 182
Themes
Pick a theme:
All Content © 2010, Keith Rull
DasBlog theme 'Business' created by Christoph De Baene (delarou)