Thursday, July 10, 2008

Command Window in Visual Studio 2008

As we develop applications in a particular IDE, it becomes imperative that we come to terms with the technical details of the IDE itself. Features like shortcuts can prove big time saves when working in huge projects. In this post, I want to discover the command window feature in Visual Studio 2005 and 2008.

Command window allows working with the IDE using commands, instead of using the mouse and the IDE menu. Some times it is just quicker to pop open the command window and perform routine tasks, such as opening and saving files, creating aliases for other windows, reading and setting the value of a variable during debugging.

Once in a while my IDE would get messed up and I would lose my solution explorer. By having an alias for it, I simply open up the command window and get straight to any window that I need. Now, solution explorer does have its shortcut (Ctrl-Alt-L), but I am not very keen about these "3keyed shortcuts". For those of us that are used to the more traditional Dos Prompt Style, command window makes us feel right at home with its command features.

Command window can be accessed using the shortcut Ctrl-Alt-A.

Lets get down and dirty and see some useful features that have helped me. I am sure you would find them useful as well.

Creating Aliases

Aliases allow us to define a shorter name for a command. So, for example, we can define an alias to open up Server Explorer using the alias syntax like this:

alias se View.ServerExplorer

alias1

Now, lets have a look at our created alias. Simply type alias and press Enter to see a list of all aliases defined in the environment.

alias2

The alias command gives us a list as show in the image above. Notice our newly created alias highlighted.

To run this alias, simply type se on an empty line in the command window and the Server Explorer opens up for us.

To delete an alias, type in: alias se /delete as shown below.

alias3

Command window has other useful uses as well. I will leave those for another post.

Monday, July 7, 2008

FTPing with ASP .NET

The framework provides us with various techniques to connect with FTP servers and interact with them. In this post, I will go over some of the ways and we will see how to add functionality to a FTP client.

Here is a limited class for our FTP. It has three methods: listFiles, makeDirectory and deleteDirectory.

1 Imports Microsoft.VisualBasic
2 Imports System.IO
3 Imports System.Net
4
5
6 Public Class ftpclientcode
7 Protected myftprequest As FtpWebRequest
8 Protected myftpresponse As FtpWebResponse
9 Private _myserver As String
10 Private _myuser As String
11 Private _mypw As String
12
13 Public Sub New(ByVal myserver As String, ByVal myuser As String, ByVal mypw As String)
14 _myserver = myserver
15 _myuser = myuser
16 _mypw = mypw
17 myftprequest = WebRequest.Create(_myserver)
18 myftprequest.Credentials = New NetworkCredential(_myuser, _mypw)
19
20 End Sub
21
22
23 Public Function ListFiles() As Stream
24 myftprequest.Method = WebRequestMethods.Ftp.ListDirectory
25 myftpresponse = myftprequest.GetResponse()
26 Return myftpresponse.GetResponseStream()
27
28 End Function
29
30 Public Sub MakeDirectory(ByVal mydirname As String)
31
32 myftprequest.Method = WebRequestMethods.Ftp.MakeDirectory
33 myftpresponse = myftprequest.GetResponse()
34
35 End Sub
36
37 Public Shared Sub Close()
38 ' myftpresponse.Close()
39
40 End Sub
41
42 Public Sub DeleteDirectory(ByVal mydirname As String)
43 myftprequest.Method = WebRequestMethods.Ftp.RemoveDirectory
44 myftpresponse = myftprequest.GetResponse()
45
46 End Sub
47
48
49 End Class




And here is the Default.aspx page to work with our class


1 Imports System.Net
2 Imports System.IO
3
4 Partial Class _Default
5 Inherits System.Web.UI.Page
6
7 Private servername As String = "localhost"
8 Private myusername As String = "rafayali"
9 Private mypassword As String = "******"
10
11
12 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
13 Dim myftp As New ftpclientcode("ftp://" & servername, myusername, mypassword)
14 Label1.Text = ""
15 Dim datastream As Stream = myftp.ListFiles()
16 Dim reader As New StreamReader(datastream)
17 While Not reader.EndOfStream
18 'Response.Write(reader.ReadLine() & "<br/>")
19 Label1.Text = Label1.Text & "&nbsp;&nbsp;?&nbsp;&nbsp;&nbsp;" & reader.ReadLine() & "<br/>"
20 End While
21 'myftp.Close()
22 End Sub
23
24 Protected Sub createdir_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles createdir.Click
25 Panel1.Visible = False
26 Panel2.Visible = False
27 Panel3.Visible = True
28 TextBox1.Focus()
29 End Sub
30
31 Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles createbutton.Click
32 Panel3.Visible = False
33 Panel1.Visible = True
34 Panel2.Visible = True
35 Dim myftp As New ftpclientcode("ftp://" & servername & "/" & TextBox1.Text, myusername, mypassword)
36 Try
37 myftp.MakeDirectory(TextBox1.Text)
38 Page_Load(sender, e)
39 Catch ex As Exception
40 Response.Write(ex.Message.ToString())
41 Finally
42 'myftp.Close()
43 End Try
44 End Sub
45
46 Protected Sub cancelbutton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cancelbutton.Click, Button2.Click
47 Panel1.Visible = True
48 Panel2.Visible = True
49 Panel3.Visible = False
50 Panel4.Visible = False
51 End Sub
52
53 Protected Sub removedir_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles removedir.Click
54 Panel1.Visible = False
55 Panel2.Visible = False
56 Panel4.Visible = True
57 TextBox2.Focus()
58 End Sub
59
60 Protected Sub Button1_Click1(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
61 Panel4.Visible = False
62 Panel1.Visible = True
63 Panel2.Visible = True
64
65 Dim myftp As New ftpclientcode("ftp://" & servername & "/" & TextBox2.Text, myusername, mypassword)
66 Try
67 myftp.DeleteDirectory(TextBox2.Text)
68
69 Catch ex As Exception
70 Response.Write(ex.Message.ToString())
71
72 End Try
73 Page_Load(sender, e)
74 End Sub
75
76 Protected Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Unload
77
78
79 End Sub
80 End Class
81

Web.Config Code Snippets

I was going through some old projects yesterday and came across some interesting web.config settings that I thought would be a good read. So, without further ado, here are some useful code snippets.

 

Set The Upload File Size to 128KB for a Particular Page

1 <configuration>
2 <location path="myFileUploadPage.aspx">
3 <system.web>
4 <httpRuntime maxRequestLength="128"/>
5 </system.web>
6 </location>
7 </configuration>


Bringing an Application Offline


1 <configuration>
2 <system.web>
3 <httpRuntime enable="false" />
4 </system.web>
5 </configuration>

Encrypting Database Passwords using MD5

Today, I will show you a very basic technique to encrypt database passwords for storage using MD5 algorithm. MD5 is a one-way algorithm; decrypting is almost next to impossible. One very important characteristic of this algorithm is that a particular text value would always result in the same encrypted value. Therefore, even though the encrypted value cannot be decrypted directly, we do have a way to verify such passwords.

Let us get down straight to code and see for ourselves:

1 Dim connectionString As String = "Data Source=.\SQLEXPRESS;AttachDbFilename=D:\rafay\projects\certification\encrypt\App_Data\members.mdf;Integrated Security=True;User Instance=True"
2
3 Dim sqlStatement As String = "INSERT INTO users VALUES(@myuser,@mypassword)"
4 Using objConn As SqlConnection = New SqlConnection(connectionString)
5 Using objComm As SqlCommand = New SqlCommand(sqlStatement, objConn)
6 Dim userNameParameter As New SqlParameter("@myuser", Data.SqlDbType.NVarChar, 15)
7 userNameParameter.Value = "Test"
8
9 Dim passwordParameter As New SqlParameter("@mypassword", Data.SqlDbType.Binary, 16)
10 passwordParameter.Value = encryptPasswordWithMD5("TestAccountPassword")
11
12 Dim objCommParameterArray() As SqlParameter = {userNameParameter, passwordParameter}
13 objComm.Parameters.AddRange(objCommParameterArray)
14
15 objConn.Open()
16 Dim result As Integer = objComm.ExecuteNonQuery()
17 End Using
18 End Using
19


This is our very basic example of connecting to SQL Server Express database file called members.mdf. We set up a sql statement and two parameters for username and password. The important part to look at is that the password is first encrypted using our helper function called encryptPasswordWithMD5. Another thing to note is that the database field for password is defined as a binary type of length 16. Once the parameters are defined and their values set, a parameter array is formed and then added to the SQLCommand object. The record is finally inserted with a call to ExecuteNonQuery.


Let us now have a look at our encryptPasswordWithMD5 function.



1 Private Function encryptPasswordWithMD5(ByVal stringToEncrypt As String) As Byte()
2 Dim MD5Encrypter As New MD5CryptoServiceProvider()
3 Dim stringBytes() As Byte = convertStringToBytes(stringToEncrypt)
4 Dim bufferToHoldEncryptedData() As Byte = Nothing
5
6 bufferToHoldEncryptedData = MD5Encrypter.ComputeHash(stringBytes)
7
8 Return bufferToHoldEncryptedData
9 End Function
10
11 Private Function convertStringToBytes(ByVal stringToConvert As String) As Byte()
12 Return Text.Encoding.UTF8.GetBytes(stringToConvert)
13 End Function




Line 3 of the code above is of particular interest. Since the ComputeHash method of MD5CryptoServiceProvider class takes in a byte value, our very first task is to convert the password string into a byte. This is accomplished using our second helper function convertStringToBytes (also defined in the listing above). What convertStringToBytes does is to take a string value and return the bytes using GetBytes method of the Encoding class in System.Text namespace. Once this is done, we calculate the hash and store in a buffer and return this buffer.


So, how do we actually verify the credentials since there is no way to decrypt? Well, since MD5 always results in the same hash for the same text, we can encode the text again and compare this against the value in the database. Code sample follows:



1 Public Function checkPassword(ByVal userName As String, ByVal myPassword As String) As Boolean
2 Dim connectionString As String = "Data Source=.\SQLEXPRESS;AttachDbFilename=D:\rafay\projects\certification\encrypt\App_Data\members.mdf;Integrated Security=True;User Instance=True"
3 Dim result As Integer = 0
4 Dim sqlStatement As String = "SELECT count(*) from users Where myuser=@myuser AND mypassword=@mypassword"
5 Using objConn As SqlConnection = New SqlConnection(connectionString)
6 Using objComm As SqlCommand = New SqlCommand(sqlStatement, objConn)
7 Dim userNameParameter As New SqlParameter("@myuser", Data.SqlDbType.NVarChar, 15)
8 userNameParameter.Value = userName
9
10 Dim passwordParameter As New SqlParameter("@mypassword", Data.SqlDbType.Binary, 16)
11 passwordParameter.Value = encryptPasswordWithMD5(myPassword)
12
13 Dim objCommParameterArray() As SqlParameter = {userNameParameter, passwordParameter}
14 objComm.Parameters.AddRange(objCommParameterArray)
15
16 objConn.Open()
17 result = CInt(objComm.ExecuteScalar())
18 End Using
19 End Using
20 If result > 0 Then
21 Return True
22 Else
23 Return False
24 End If
25 End Function
26 End Class


In the first code above, I have hardcoded the username and password values. These would naturally need to be changed and the source of input would be probably be a CreateUserWizard or another composite control with various textboxes. The values were hardcoded for simplicity.

ASP .NET Cheat Sheets

Here I have collected various cheat sheets for download. I do not recall the exact sources from where they were downloaded. If you download a sheet and know the source, let me know and I will mention it in this post.

 

Regular Expressions Cheat Sheet (pdf)

Page Life Cycle (pdf)

ASP .NET 2.0 Life Cycle (png)

ASP .NET Tips and Tricks (ppt): Microsoft ASP .NET Team presentation

VS 2005 Code Snippets (pdf)

Health Monitoring Class Diagram (bmp): Scott Mitchell's article on Health Monitoring at 4GuysFromRolla

ASP .NET Membership Database Schema (png)

Visual Basic 2005 Default Key Bindings (pdf)

Visual Basic 2008 Default Key Bindings (pdf)

Health Monitoring Event Codes (png)

 

I will update these listings, if and, when I come across new sheets. If you know of any, please let me know and I will link them here.

This post is accessible from the sidebar in the future.

Friday, July 4, 2008

Compressing ViewState

Viewstate is a client-side "state management" method. Viewstate allows page and control data to be preserved between postbacks.

When client side HTML is generated for the page, the current state and data of the page is serialized into base64-encoded strings and stored as hidden field(s) in the page. Viewstate is page specific; that is, once you navigate away from the page, the viewstate is lost.

Hangman Game - An Exercise in Learning

With ample time on hand past Saturday, I decided to dig up some past tutorials just to refresh some material that may have slipped my mind. I have found that going through old stuff once in a while is a handy way to polish ASP .NET skills - or any programming environment for that matter. So, the first time that caught my eye was a Hangman tutorial by Scott Mitchell at 4GuysFromRolla. 4GuysFromRolla is a great place to learn about ASP .NET; I do a tutorial every night or every week (depending on the complexity and the series) to stay current with this ever changing dynamic platform.

I decided to use the Hangman tutorial and re-code it using different classes and logic. Here are parts and pieces of the changed code that I would like to share with the readers here. I have kept the method names same as the one found on 4GuysFromRolla for easy comparison.

1 Protected Sub generateLetterBoard()
2 'generates the letters from A-Z and creates linkbuttons
3 'called in page_PreInit()
4
5 Dim i As Integer = 0
6 Dim j As Integer = 65
7
8 For i = 0 To 25
9 If j < 92 Then
10 Dim myLinkButton As New LinkButton()
11 myLinkButton.ID = ChrW(j).ToString()
12 myLinkButton.Text = ChrW(j).ToString()
13 myLinkButton.CommandArgument = ChrW(j).ToString()
14 AddHandler myLinkButton.Command, AddressOf LetterGuessed
15 form1.Controls.Add(myLinkButton)
16 End If
17 j = j + 1
18 Next
19 End Sub





As you can see, instead of creating link buttons singularly in the source view, I took the approach of dynamically creating the link buttons. What the above snippet does is it declares a variable to loop 26 times for each alphabet in the English language. The inner loop then executes to display letters; letters are extracted from their ASCII values (65 represents an uppercase A, 90 represents an uppercase Z). The inner loop, then, create a link button, and assigns its Text, ID, and CommandArgument properties. It then adds an event handler to handle the Command event. Command event is raised each time that a link button is clicked. Finally, the link button is added to the form's controls collection.



Here is an ASCII chart for reference (taken from http://www.cdrummond.qc.ca/cegep/informat/Professeurs/Alain/files/ascii.htm).



ASCII1



 



The second piece of code that I changed was getRandomWordFromTextFile() method. Here's the implementation:




1 Protected Function getRandomWordFromTextFile(ByVal filePath As String) As String
2 'Dim myFileStream As New FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)
3 'Dim words As New ArrayList()
4 'Dim myStreamReader As New StreamReader(myFileStream)
5
6 'While myStreamReader.Peek > -1
7 ' words.Add(myStreamReader.ReadLine())
8 'End While
9
10 'myFileStream.Close()
11 'myStreamReader.Close()
12
13 'Dim randomNumberGenerator As New Random()
14 'Dim randomNumber As Integer = randomNumberGenerator.Next(words.Count)
15 'Dim chosenWord As String = words(randomNumber)
16 'Return chosenWord
17
18 'THE FOLLOWING USES OLEDBDATAADAPTER TO READ THE TEXT FILE AND RETURN RANDOM WORD
19
20 Dim ds As DataSet
21 Dim chosenWord As String = ""
22
23 If Not Page.IsPostBack Then
24 Dim objConn As New OleDbConnection("provider=microsoft.jet.oledb.4.0;data source=" & filePath & ";extended properties='text;hdr=yes;'")
25 Dim objAdapter As New OleDbDataAdapter("SELECT * FROM WORDS.txt", objConn)
26 ds = New DataSet()
27 objAdapter.Fill(ds)
28 Dim randomNumberGenerator As New Random()
29 Dim randomNumber As Integer = randomNumberGenerator.Next(ds.Tables(0).Rows.Count)
30 chosenWord = ds.Tables(0).Rows(randomNumber).Item(0).ToString()
31
32 End If
33
34 Return chosenWord
35
36
37
38 End Function






Instead of using a TextReader, I opted for an OleDBDataAdapter to perform the task of connecting to the text file. A random value is then extracted from the dataset; random row is selected and the value in the first column is set as the Hangman word.



The remainder of the code is similar.