Blog of a Filipino Developer about C#, VB.NET, ASP.NET, Java, PHP, SQL Server, MySql and Oracle RSS 2.0
 Thursday, November 08, 2007

I know, i missed alot after i didn't go to MIX07. I told Jon that i'll be coming to MIX07 but something happened with my project and i was asked to tend the wounds. This time I won't let the chance to party with Miguel, Jeff, Phil and Scott pass me by!

MIX08 here I come!

Thursday, November 08, 2007 9:40:22 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
Tech News and Issues
 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

Thanks Dave for making me laugh today!

Monday, October 29, 2007 11:34:52 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
All about Keith | Fun Stuff | SQL

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

I didn't know that I could do this inside SQL Server

EXEC master..xp_fixeddrives

Executing the procedure onmy server gave me this result set:

drive  MB free
C       5897
E       33334

Man, I think it's about time I upgrade and brush up my SQL skills. I don't know why you would do it inside SQL Server. But then again it's pretty cool to know that something like this exist. You never know, you might need it someday.

Friday, September 07, 2007 6:36:46 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
SQL

I've been working on alot of SQL Server lately due to the current project i'm assigned to and I found myself this morning needing a query that would truncate all the tables in one of my staging database. My initial thought is that I can do this using a cursor that would hold all truncate statements and execute each one of them one at a time so within 5 minutes i was able to build a query that looks like this:

--declare a variable that would hold the query to be executed
DECLARE @TruncateQuery varchar(4000)

-- create a cursor that would hold our truncate statements
DECLARE TruncateQuerries CURSOR LOCAL FAST_FORWARD
FOR SELECT
    N'TRUNCATE TABLE ' +
    QUOTENAME(TABLE_SCHEMA) +
    N'.' + QUOTENAME(TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE
        TABLE_TYPE = 'BASE TABLE'
    AND    OBJECTPROPERTY    (
                            OBJECT_ID(QUOTENAME(TABLE_SCHEMA) +
                            N'.' + QUOTENAME(TABLE_NAME)
                        ), 'IsMSShipped') = 0

-- read our truncate statements
OPEN TruncateQuerries
-- loop thru each statement in our truncate statement cursor
FETCH NEXT FROM TruncateQuerries INTO @TruncateQuery
WHILE @@FETCH_STATUS = 0
BEGIN
    --execute the statement
    EXEC(@TruncateQuery)
    --assign the current truncate statement to our @TruncateStatement variable
    FETCH NEXT FROM TruncateQuerries INTO @TruncateQuery 

END
-- close our cursor
CLOSE TruncateQuerries
-- and free up the resources
DEALLOCATE TruncateQuerries

Looks great right? Then I realized what my good friend Jon Galloway told me once that there are hidden stored procedures in SQL Server and 1 of those stored proc is sp_MSforeachtable. It's an undocumented sp so you won't find anything about it in the SQL Books Online. What this stored procedure basically does is that it lets you execute a command or a set of commands against all tables inside a database. Before we go into further detail lets look at the parameters that sp_MSforeachtable expects.

exec @RETURN_VALUE=sp_MSforeachtable @command1, @replacechar, @command2,
@command3, @whereand, @precommand, @postcommand

Where:(description taken from [LINK])

  • @RETURN_VALUE - is the return value which will be set by "sp_MSforeachtable"
  • @command1 - is the first command to be executed by "sp_MSforeachtable" and is defined as a nvarchar(2000)
  • @replacechar - is a character in the command string that will be replaced with the table name being processed (default replacechar is a "?")
  • @command2 and @command3 are two additional commands that can be run for each table, where @command2 runs after @command1, and @command3 will be run after @command2
  • @whereand - this parameter can be used to add additional constraints to help identify the rows in the sysobjects table that will be selected, this parameter is also a nvarchar(2000)
  • @precommand - is a nvarchar(2000) parameter that specifies a command to be run prior to processing any table
  • @postcommand - is also a nvarchar(2000) field used to identify a command to be run after all commands have been processed against all tables

All other parameters are optional except for @command1 which is first statement that would be executed.

Now, lets rewrite our truncate table query from above to use the sp_MSForeachtable procedure:

EXEC [sp_MSforeachtable] @command1="TRUNCATE TABLE ?"

What??? Tha't it? 1 line? Crazy huh? I didn't realized that it was that easy until i tried it. Man, If i knew this when I started writing my query above I could have not wasted 5 minutes of my life in something that can be done in 10 seconds. Thanks for hiding feature this Micrsoft!

But wait! There's more, now i've truncated my tables i need a way to reseed all the identity columns on my database:

EXEC [sp_MSforeachtable] @command1="DBCC CHECKIDENT (?, RESEED, 100)"

What??? Another 1 liner? Whats even better is that I could also REINDEX all the tables in my DB with one line of beautiful SQL code:

EXEC [sp_MSforeachtable] @command1="DBCC DBREINDEX('?')"

Wanna show progress message on each execution? Try this version:

EXEC [sp_MSforeachtable] @command1="RAISERROR('DBCC DBREINDEX(''?'') ...',10,1) WITH NOWAIT DBCC DBREINDEX('?')"

Oh, Ma! I can't believe being a programmer could be this easy. ;) I hope i could save someone's precious time by proving this example because i know it would save mine in the future.

Friday, September 07, 2007 6:07:58 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
SQL

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 4:58:37 PM (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | Tech News and Issues
Archive
<November 2007>
SunMonTueWedThuFriSat
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678