For daily doses of
geek stuff @joemaddalone

labs.insert-title.com

ASP.NET

Reading Various Files into Datatable


   '04a - EXCEL
    '-----------------------------------------------------------------------

    'Returns query against Excel file as datatable
    Function ReadExcel(ByVal sqlString As String, ByVal path As String) As System.Data.DataTable
        Dim strConn As String = _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & path & ";" & _
        "Extended Properties=""Excel 8.0;"""
        Dim recs As New Data.DataTable()
        Dim sql As New OleDbDataAdapter(sqlString, strConn)
        sql.Fill(recs)
        Return recs
    End Function

    '04b - ACCESS
    '-----------------------------------------------------------------------

    'Returns query against Access file database
    Function ReadAccess(ByVal sqlString As String, ByVal path As String) As System.Data.DataTable
        Dim strConn As String = _
        "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & path & ";"
        Dim recs As New Data.DataTable()
        Dim sql As New OleDbDataAdapter(sqlString, strConn)
        sql.Fill(recs)
        Return recs
    End Function

    '04c - CSV
    '-----------------------------------------------------------------------

    'Returns datatable from CSV File
    Function ReadCSV(ByVal path As String) As System.Data.DataTable
        Dim sr As New StreamReader(path)
        Dim fullFileStr As String = sr.ReadToEnd()
        sr.Close()
        sr.Dispose()
        Dim lines As String() = fullFileStr.Split(ControlChars.Lf)
        Dim recs As New DataTable()
        Dim sArr As String() = lines(0).Split(","c)
        For Each s As String In sArr
            recs.Columns.Add(New DataColumn())
        Next
        Dim row As DataRow
        Dim finalLine As String = ""
        For Each line As String In lines
            row = recs.NewRow()
            finalLine = line.Replace(Convert.ToString(ControlChars.Cr), "")
            row.ItemArray = finalLine.Split(","c)
            recs.Rows.Add(row)
        Next
        Return recs
    End Function

Handy ASP.NET Routines

Trace Output


Sub Trace(ByVal errorString As String, Optional ByVal x As String = "title not set")
    System.Web.HttpContext.Current.Trace.Write(x)
    System.Web.HttpContext.Current.Trace.Write(errorString)
End Sub

Quickly Access Page Elements from Codebehind


Function PG() As HttpContext
    'Ex:
    'PG.Response.Redirect("...")
    Return System.Web.HttpContext.Current
End Function

Quickly Access Application Settings


Function AP(ByVal x As String) As String
    'Ex:
    'MailMessage.To.Add(New MailAddress(AP("SupportAddress")))
    Return System.Configuration.ConfigurationManager.AppSettings(x)
End Function

PostBackUrl Equals Change the Friggin' Form Action


Dim btn As New Button
btn.PostBackUrl = "www.insert-title.com"
btn.OnClientClick = "if(!validate())return false;"
btn.Text = "Submit"

Curse you DBNull and/or Is Nothing!

that's right, just a title... we do that here. We also have no logo, or branding or consistent income... However, we DO have a hatred for redundant logic.

    Function Notta(ByVal x As Object) As String
        Dim ret As String
        If (x Is DBNull.Value) OrElse (x Is Nothing) OrElse (x Is String.Empty) Then
            ret = ""
        Else
            Try
                ret = CStr(x).Trim
            Catch
                ret = ""
            End Try
        End If
        Return ret
    End Function

Quick and Dirty URL Rewriting with VB.NET

As a preface, this is really only a solution for those of us who do not have a dedicated or VPs server. If you have access to the IIS Management console there are much better ways to accommodate the need for URL rewriting.

I am going to demonstrate a simple way to implement this, but there are a number of much more complex ways to utilize this code.

Basic Example

You have an ecommerce site and want to clean up your URLs a bit. A call to products.aspx?ID=123 is not quite as good as widgets.aspx.
No Problem.

The solution is a Global.asax file.

From MSDN:

The Global.asax file, also known as the ASP.NET application file, is an optional file that contains code for responding to application-level events raised by ASP.NET or by HTTP modules. The Global.asax file resides in the root directory of an ASP.NET application. At run time, Global.asax is parsed and compiled into a dynamically generated .NET Framework class derived from the HttpApplication base class. The Global.asax file itself is configured so that any direct URL request for it is automatically rejected; external users cannot download or view the code in it.

The Global.asax file is optional; if you do not define the file, the ASP.NET page framework assumes that you have not defined any application or session event handlers.

So this file goes into the root of your .NET application.

It starts like this


<script language="vbscript" runat="server"> 
Sub Application_BeginRequest(Sender As Object, E As EventArgs)
......

End Sub
</script>

The Application_BeginRequest is a lot like the page_load event in your standard .NET code except it starts with the application not the individual page.

And as an example if we popped this into our application and made it read


<script language="vbscript" runat="server"> 
Sub Application_BeginRequest(Sender As Object, E As EventArgs)
  response.write ("Hello world")
End Sub
</script>

Then from there on every page that loaded within this application would have the "Hello World" line at the top of the page.

Okay with me so far? Great!

Whats next... well we're talking about rewriting URLs so we need to know how to look at the URL itself.


<script language="vbscript" runat="server"> 
Sub Application_BeginRequest(Sender As Object, E As EventArgs)
  Dim httpContext As System.Web.HttpContext = HttpContext.Current
  Dim currentURL As String = CurrentURL.Request.Path.ToLower()
  response.write (currentURL)
End Sub
</script>

Done, now we are showing the URL in place of Hello World, it's really the path rather than the URL, so we don't have to worry about splitting out a bunch of /'s. We should be seeing the path of the current page relative to the global.asax file or the Application root.

I hope I am not losing you here - it doesn't matter, stick with this and you'll get it in the end.

So we've taken our URL and converted it into a string... so we have "products.aspx?ID=123" at the top of our page and it really isn't helping anybody yet...

All we need to do now is instead of calling "products.aspx?ID=123" let's call "widgets.aspx"... and then all we need to do is tell it that "widgets.aspx" = "products.aspx?ID=123"

Here goes.


<script language="vbscript" runat="server"> 
Sub Application_BeginRequest(Sender As Object, E As EventArgs)
  Dim httpContext As System.Web.HttpContext = HttpContext.Current
  Dim currentURL As String = CurrentURL.Request.Path.ToLower()
    If currentURL.IndexOf("widgets") > 0 Then
      objHttpContext.RewritePath("products.aspx?ID=123")
    else
      objHttpContext.RewritePath(httpContext)
    end if
End Sub
</script>

Thats it. One thing to mention here is that you can really, really expand on this.

clicky - widgets.aspx

Randomize YPN and Adsense

This is really very simple but I have been asked a number of times how I do this on some of my sites.

The Code


Public Shared Function placeAds(channel as integer,width as integer,height as integer,linkColor as string)	
Dim r as New Random
Dim x as integer
Dim adSTR as String	
x = r.Next(0, 100)
if x > 50
  adSTR = ("" & vbcrlf)
  adSTR  &= ("" & vbcrlf)

else		
  adSTR = ("" & vbcrlf)
  adSTR &= ("" & vbcrlf)
end if
	Return adSTR
End Function

Useage



placeAds(channelID,width,height,linkcolor)


Making VS.net 2003 Work for You

Summary:

This walk-thru will demonstrate how to create a web application project using the IDE, create a layout using frames with Microsoft FrontPage 2003, and configure the project for later being ran and debugged while not compiled with the Codebehind model (that by default relies on a compiled DLL.)

Bringing back the Codebehind model on a temporary basis when editing the project will also be demonstrated. This way some of the niceties that the IDE naturally provided by default can be once again made available like working with the pages in Design view and Code-Completion.

Download the sample project used in this demonstration

View the project conversion macros used in this example

Contents:

Why have I done this?

As ASP.net and the Microsoft Development Environment 2003 provide a means for developers to create object-oriented, content-separated code with an IDE that allows for rapid application development and writing server-side code that responds to client-side events easily, there have been some inherit problems with the approach. Obviously many developers would jump at making any transition needed to be able to develop this way and many have already done so.

However, there is a flip-side to this too as with anything new, the grass is sometimes greener on the other side. Many developers have avoided using this IDE due to obstacles that stood in their way. Often the HTML created by the design view of this IDE (not to mention others as well,) was not acceptable to developers and they've resorted to a "notepad" style of coding and have been doing so for quite some time now. Also, the nature of the classic ASP world tended to be inter-mingling server-side code with the HTML content on a web page causing many developers to be used to a raw development style as a result. Even though this particular IDE has offered a new coding style to be used, developers feel they are being forced down some pathways they have trouble accepting or getting around.

One of these pathways just mentioned, is compiling all of the class files for each of the web pages of the site into a DLL. While this has its benefits, it also has bothered many developers when they were used to being able to jump in and make a quick change on the fly using any text editor of their choosing and not having to re-compile a DLL. Although I am not personally against using a DLL all together, I like to know my options.

I hope this article will be informative and demonstrate some techniques that maximize the use of the IDE and that possibly may not be well known.

Creating the Web Application

I'll start by creating a Visual Basic Web Application project using Microsoft Development Environment 2003. This step will create a virtual directory with my solution's name and create all the needed project files to get up and running. These files include a global application file, a default .ASPX web page, and a .CSS stylesheet just to name a few. Matching .VB source code files have been created for the .AS?X file types being the Codebehind files in this project. Typically when the editing of these content and code files is done or at a good stopping point, the project is compiled,and each of these classes defined in the VB files gets compiled into one project-level DLL that supports the entire application at run-time. This DLL is saved to the Bin folder in the directory where the project files have been created. My demonstration in this article is not going to take that step and will not compile the code into a DLL.

I first began by launching the Microsoft Development Environment 2003. A couple of macros have been created to help facilitate my using the IDE for this demonstration. I will later discuss those macros in further detail.

First we shall create a new web application project (File - New - Project...)

I named this web application Base and clicked [OK].

Renaming WebForm1

Later in this demonstration I change the project properties to default the creation of web pages in FlowLayout mode instead of GridLayout. I also later changed the default client scripting language to VBScript. These settings are my personal preference; however, for the sake of this demonstration, you may want to make them in this particular project.

Now that the project and virtual directory have been created, I next renamed the webform to Default from the solution explorer. Then I right clicked on the page and selected View HTML Source. Inside the HTML source, I changed the reference for the Inherits attribute to:

Inherits="Base.DefaultClass"

The web page is now set to inherit from the class DefaultClass which in-turn inherits from System.Web.UI.Page. I still needed to open the VB code file and change its class name to DefautlClass.

Adding a needed import for later

I now had the base structure for the default web page created and ready for content. Considering how later these source files will not be ran using the Codebehind model, I needed to add 1 Import statement for the Global.asax.vb file right away. For the purposes of this demonstration using this project, no other Import statements will be needed.

Creating frames using Microsoft FrontPage 2003

Now I decided to use Microsoft FrontPage 2003 to create a frames page. Afterwards I copy some of the HTML it generates to my Default.aspx page.

(File - New...) and then I clicked More page templates... and then I selected Header, Footer and Contents.

The following frames page was created:

Next I opened the code view for this page, and changed some of the settings of the frames.

Now I copied the following HTML to the clipbboard so I could paste it into my Default.aspx page.

	

	
	
		
		
	
	
	
	<body>

	<p>This page uses frames, but your browser doesn't support them.</p>

	</body>
	

			

Here I pasted the HTML over the following text inside the Default.aspx page.

Next I changed the page title to Base.

Adding web forms to the project

Now I began creating the other .ASPX web pages in the project that will be loaded into these different frames. I right clicked the project from the solution explorer to add a web form to the project (Add - Add Web Form...)

At this point I determined that except for the default page, I'd name all web pages with the web prefix. So I opened the Default.aspx in HTML Source view again and changed these filenames to webHeader.aspx, webSidepanel.aspx, etc.

Before I continued adding the rest of the pages, I decided this would be a good point to stop and change a couple of project-level properties. (Project - Properties...) and then (Common Properties - Designer Defaults)

I changed the Page Layout and Client Script Language settings that will be used during the creation of every new web page created by the IDE in this project. Since the last web pages were created before these settings were changed, I will manually change them soon.

With these settings in place I proceeded to create the rest of the .ASPX pages that will be used for the frames.

For each of the frames I began typing some text into them so when viewing these frames later in Microsoft Internet Explorer I'd have a good idea of what I was looking at.

As I came to the webHeader.aspx file from the solution explorer, I saw this was one of the frames I needed to change manually and so I right clicked the page and selected Properties...

Here I changed the Page Layout and Default scripting language settings and clicked [OK]

Now I have all the pages created and saved and I'm ready to view them from Microsoft Internet Explorer.

Leaving the Codebehind model

I want to run this project without compiling the pages to a DLL so I shall NOT hit F5 at this point; instead I will use my macro to convert these files so they no longer use the Codebehind model. Even if F5 is accidentally pressed, no real harm will be done, but a DLL will be created. When the pages are changed from Codebehind to Src, the DLL will be ignored when ran anyways. This macro ToSrc will do the following:

1. Close all open files in the IDE (saving them.)

2. Find and replace in all .AS?X files the Codebehind attribute to Src.

3. Assume the project name involved has the same base name as the solution, and replace all of the Inherits attributes in these same files, removing the project name from the setting.

4. Afterwards, all the files will be saved.

Note: This macro and the other described later were created by me (not Microsoft) and is for use at your own risk. The general things to consider when using these macros is that they are intended for a solution having only 1 project that are each named the same and having source files not set with read-only attributes like is often the case when the files are under source control using Microsoft Sourcesafe. These macros have been created to give a general idea of the needed changes going to and from the Codebehind model while still making good use of the IDE.

So the ToSrc macro has now been executed. The web application can now run using IE and no compilation needs to occur.

Configuring the virtual directory for debugging

I next decided to modify some of the settings for the virtual directory from Internet Information Services (found under Administrative Tools) before continuing.

Here I typed the name Base for the application name, selected High (Isolated) for the Application Protection setting, and further continued some changes after clicking Configuration...

I changed the Debugging Flags to make them both enabled. Afterwards I clicked [OK] to both this dialog and the previous one. These settings allow for me to debug this application from a manual approach but are not needed for the virtual directory during production use. Afterwards, I still needed to change one more setting in Component Services (also found under Administrative Tools.) This last setting can only be applied to an application configured with High application protection and is to allow the user (security-wise) to attach to the running process from the Microsoft Development Environment 2003.

Here I located my application IIS--{Default Web Site//Root/Base} and selected Properties...

Under the Identity tab, I changed the account that the application would be run under. After clicking [OK] to this, I will be able to attach to the running process (when it is running from IE for example.) Now that I made these changes, I decided to run the project from IE.

Running the web application with no DLL

Going back to the Codebehind model

Now that the site has run without having compiled the DLL and the virtual directory is set to be debugged, I next made some changes to the content web page so I can further demonstrate the use of the IDE and debugging the application. Here I decided to run the other macro I created called ToCodebehind. The purpose for this macro is to change the files back to the Codebehind model so that the IDE will be friendlier with the pages, giving me back Design view, auto mapping to the events for the objects from the Design view, and Code-Completion in the code files. This macro ToCodebehind will do the following:

1. Close all open files in the IDE (saving them.)

2. Find and replace in all .AS?X files the Src attribute to Codebehind.

3. Assume the project name involved has the same base name as the solution, and replace all of the Inherits attributes in these same files, adding the project name to the setting.

4. A piece of self-cleaning code to ensure that if this macro has run several times, that the project name is not added multiples times in these attribute values.

5. Afterwards, all the files will be saved.

Note: This macro was created by me (not Microsoft) and is for use at your own risk. The general things to consider when using these macros is that they are intended for a solution having only 1 project that are each named the same and having source files not set with read-only attributes like is often the case when the files are under source control using Microsoft Sourcesafe. These macros have been created to give a general idea of the needed changes going to and from the Codebehind model while still making good use of the IDE.

Adding Content, Code, and Breakpoints

So the ToCodebehind macro has now been executed. The source files can now be opened in Design view, objects from the toolbar be added to the pages, and events for those objects be attached. The coding for these pages and the server-side events can be done with full Code-Completion and life is good. After opening my webContent.aspx file, I added a button and a text box from the toolbar to the page and I changed the bgColor of the document to aliceblue which in this case was transformed to a hex value in the Properties toolbar.

Now entering the code view after having double clicked the button from Design view. I'm ready to "code away."

Here I decided to add another Imports statement because it may come in handy later and added a line of code to run for the button's click event.

After source changes have been made, it's time to leave Codebehind again

Now edits have been made, and I run the ToSrc macro again. Going to and from the Codebehind model isn't necessary every time a change is to be made, but it will often be the desirable approach when several changes from Design view are desired and/or alot of code will be added or changed to the source files.

Now I refresh the page out of IE.

Attaching the debugger

Before I click the button and see the textbox updated with the date and time, I figure this is a good time to demonstrate debugging the page with the IDE attached.

I click Debug - Process... in the IDE and select the aspnet_wp.exe process that is handling my web application and then I click [Attach...] If debugging an ASP.net application, I will use the Common Language Runtime option and for classic ASP applications, I'll have the Script option checked. The process that runs the classic ASP apps, at least on Microsoft Windows XP, is the dllhost process. Anyways, I select these items, click [OK], and then am attached to the process for my application. Too bad I'm not seeing the page listed in the running documents like I'm used to with classic ASP sites.

Later I'll demonstrate adding these code files to the solution; however, at this point, I just open the code file I want to debug.

With this project open and being attached to the running process, this file opens in debug mode (read only) so I can now step trace, place breakpoints, and debug the code.

Now I click the button from the page and the breakpoint in the IDE is hit.

I added the text property of the textbox to the watch window and stepped into the code passing the statement that changed its value and see it changed in the watch window.

Now I hit F5 to resume running the page and finish the web request and IE gets refreshed and updated.

See all this and no DLL!

Additional Practices and Considerations

Remember if you try and open a file in Design view from the IDE that is linked to a code file using Src instead of Codebehind, you will generally see this following error. Afterwards, the page will still open only for HTML Source view while Design view will be disabled. These files need their page declarations changed and be saved and closed before being re-opened in Design view. The macros shown above help ease this process.

Here I add the VB files to the solution so they can be easily accessed when not using the Codebehind model.

Remember that when using the macros, it is important to have the main project selected and highlighted from the Solution Explorer, so the "replace in all files" (for the current project) happens correctly.

One additional remark is that if this approach for coding a web application is liked and source control will be used, one consideration would be to change the macros to not work at a project level but rather a file level, so pages could be checked out from source control, converted (via a macro,) edited, saved, tested, and then converted again (using another macro) before the file is checked back in.

I hope you have enjoyed this journey in the ASP.net world. Happy coding!

ASP to ASP.NET V

Making a ASP.NET Contact Form

Our original Contact Form was based on the standard ASP spaghetti code posting back to itself and using the ASPMail component.


<%
if request("send") <> "" then
Set Mailer = Server.CreateObject("SMTPsvg.Mailer")
Mailer.FromName   = Request.Form("contactName")
Mailer.FromAddress= "email@domain.com"
Mailer.RemoteHost = "our.smtp.server"
Mailer.AddRecipient "Insert Title", "email@domain.com"
Mailer.Subject   =  "IT CONTACT FORM"
Mailer.BodyText  = Request.Form("email")
Mailer.BodyText  = Request.Form("businessName")
Mailer.BodyText  = Request.Form("contactName")
Mailer.BodyText  = Request.Form("PhoneNumber")
Mailer.BodyText  = Request.Form("email")
Mailer.BodyText  = " "
Mailer.BodyText  = "This is what we need"
Mailer.BodyText  = Request.Form("checkbox")
Mailer.BodyText  = Request.Form("checkbox2")
Mailer.BodyText  = Request.Form("checkbox3")
Mailer.BodyText  = Request.Form("checkbox4")
Mailer.BodyText  = Request.Form("checkbox5")
Mailer.BodyText  = Request.Form("checkbox6")
Mailer.BodyText  = " "
Mailer.BodyText  = "This is what we have"
Mailer.BodyText  = Request.Form("checkbox7")
Mailer.BodyText  = Request.Form("checkbox8")
Mailer.BodyText  = Request.Form("checkbox9")
Mailer.BodyText  = Request.Form("checkbox10")
Mailer.BodyText  = Request.Form("checkbox11")
Mailer.BodyText  = " "
Mailer.BodyText  = "Time Frame: " & Request.Form("timeFrame")
Mailer.BodyText  = " "
Mailer.BodyText  = Request.Form("messageTxt")

if Mailer.SendMail then
Response.write "thank you - your information has been sent"

else
  Response.Write "Mail send failure. Error was " & Mailer.Response
end if
else
%>

<form method="post" action="contact.asp">

Your personal information will NOT be shared with any 3rd parties
<br /><br />
We'd love to hear from you:<br /><br />
Business Name:<br />
<input type="text" name="businessName" size="30" />
<br /><br />
Contact Name:<br />
<input type="text" name="contactName" size="30" />
<br /><br />
Email Address:<br />
<input type="text" name="email" size="30" />
<br /><br />
What type of time frame are you anticipating?<br>
<input type="text" name="timeFrame" size="30" />
<br /><br />
What type of project are you interested in? (check all
that apply)<br />
<input type="checkbox" name="checkbox" value="web_design" />
Website Design<br />
<input type="checkbox" name="checkbox2" value="logo_design" />
Logo Design<br />
<input type="checkbox" name="checkbox3"
value="flash_animation" />
Flash Animation<br />
<input type="checkbox" name="checkbox4" value="redesign" />
Website Redesign<br />
<input type="checkbox" name="checkbox5" value="SE_place" />
Search Engine Placement<br />
<input type="checkbox" name="checkbox6" value="ecommerce" />
Ecommerce Site<br>
<br /><br />
Do you already have any of the folloing: (check all that apply)<br />
<input type="checkbox" name="checkbox7"
value="Domain Name" />Domain Name<br />
<input type="checkbox" name="checkbox8" value="Hosting" />
Hosting<br />
<input type="checkbox" name="checkbox9" value="Printed Copy" />
Printed Copy<br />
<input type="checkbox" name="checkbox10" value="Digital Copy" />
Digital Copy<br />
<input type="checkbox" name="checkbox11"
value="Digital Images" />
Digital Images<br /><br />
Questions or comments:<br /><br />
<textarea name="messageTxt" cols="30" rows="5">
</textarea>
<br /><br />
<input type="hidden" name="send" value="notempty">
<input type="submit" value="Submit"
name="submit" />
<input type="reset" value="Clear" name="reset" />
</form>
<%end if%>

This was definitley one of those instances where I got tired of reading pretty quickly. It seems there are many, many options when creating forms, checkboxes, and emails with .NET

I read these two simple articles and sample files and went about rewriting this page pretty quickly, using some of the knowledge I had already picked up in the previous articles.

CheckBoxList Web Server Control

How to send an email in ASP.net

The second article there was simply this easy ASP.NET Email script


Dim mmMail As New System.Web.Mail.MailMessage()
Dim objSmtpServer As System.Web.Mail.SmtpMail
mmMail.From = "me@me.com"
mmMail.To = "you@you.com"
mmMail.Subject = "My subject"
mmMail.Body = "My body"
objSmtpServer.SmtpServer = "my smtp server"
objSmtpServer.Send(mmMail)

While this was useful, it didn't answer all my issues, just got me started. I also picked up that I didn't have to use the StringBuilder Class in order to build up a string as I had thought before. This time I simply used


"str +="

So in essense my previous example of how to build a string could now also be


<%@ Import Namespace="System.Net" %>
<script language="VB" runat="server">
Sub Page_Load(s as Object, e as EventArgs)

Dim str as String
str = ""
str += "abcdefgh"
str += "ijklmnopqrs"
str += "tuvwxyz"


myText.Text = str
End Sub
</script>
<asp:label id="myText" runat="server" />

This made a lot more sense to me

Not sure if i used all the proper techniques here, but I essentially put the entire form inside <asp:label ID=contactForm></asp:label>

Then a Thank You Message in another label tag.

the "If.IsPostBack" means "If the user has posted"... I think you'll get the rest

Anyways here's the code I ended up with


<Script runat="Server">
   Private Sub Page_Load(ByVal s As Object, ByVal e As EventArgs)
           If Page.IsPostBack Then
               contactForm.Visible = False
               thankYou.Visible = True
           Else
               contactForm.Visible = True
               thankYou.Visible = False
           End If

   End Sub



   Sub Button_Click( s As Object, e As EventArgs )
      Dim weHave as String = ""
      Dim weNeed as String = ""
      Dim strEmail as String = ""
      Dim iLoop as Integer
      Dim iLoop2 as Integer



      For iLoop = 0 To WeNeedList.Items.Count - 1
         If WeNeedList.Items(iLoop).Selected Then
            weNeed += WeNeedList.Items(iLoop).Value & ", "
         End If
      Next


      For iLoop2 = 0 To WeHaveList.Items.Count - 1
         If WeHaveList.Items(iLoop2).Selected Then
            weHave += WeHaveList.Items(iLoop2).Value & ", "
         End If
      Next



      strEmail += "Contact Name:" & contactName.Text & vbcrlf
      strEMail += "Company Name: " & businessName.Text & vbcrlf
      strEmail += "We need the following" & vbcrlf & weNeed
      strEmail += "We have the following" & vbcrlf & weHave
      strEmail += "Time Frame Expected:" & TimeFrame.Text & vbcrlf
      strEmail += message.Text

      Dim mmMail As New System.Web.Mail.MailMessage()
      Dim objSmtpServer As System.Web.Mail.SmtpMail
      mmMail.From = email.Text
      mmMail.To = "someone@insert-title.com"
      mmMail.Subject = "IT CONTACT FORM"
      mmMail.Body = strEMail
      objSmtpServer.SmtpServer = "our.smtp.server"
      objSmtpServer.Send(mmMail)

   End Sub
</Script>
<html>
<body bgcolor="#ffcc66">
<div align="left" id="content">

<asp:label ID="contactForm" runat="server">
<form runat="Server">
  Your personal information will NOT be shared with any 3rd parties
  <br /><br />
  We'd love to hear from you:<br /><br />
  Business Name:<br />
  <asp:TextBox ID="businessName" size="30" runat="server" />
  <br /><br />
  Contact Name:<br />
  <asp:TextBox ID="contactName" size="30" runat="server" />
  <br /><br />
  Email Address:<br />
  <asp:TextBox ID="email" size="30" runat="server" />
  <br /><br />
  What type of time frame are you anticipating?<br>
  <asp:TextBox ID="timeFrame" size="30" runat="server" />
  <br /><br />
  What type of project are you interested in? (check all
  that apply)<br />


  <asp:CheckBoxList ID=WeNeedList Runat=server>
  <asp:ListItem Value=Web Design>Web Design</asp:ListItem>
  <asp:ListItem Value=Logo Design>Logo Design</asp:ListItem>
  <asp:ListItem Value=Flash Animation>
  Flash Animation</asp:ListItem>
  <asp:ListItem Value=Redesign>Redesign</asp:ListItem>
  <asp:ListItem Value=SEO>
  Search Engine Placement</asp:ListItem>
  <asp:ListItem Value=Ecommerce>Ecommerce</asp:ListItem>
  </asp:CheckBoxList>
  <br /><br />
  Do you already have any of the following:
  (check all that apply)<br />

  <asp:CheckBoxList ID=WeHaveList Runat=server>
  <asp:ListItem Value=Domain>Domain Name</asp:ListItem>
  <asp:ListItem Value=Hosting>Hosting</asp:ListItem>
  <asp:ListItem Value=Printed Copy>Printed Copy</asp:ListItem>
  <asp:ListItem Value=Digital Copy>
  Digital Copy</asp:ListItem>
  <asp:ListItem Value=Digital Images>
  Digital Images</asp:ListItem>
  </asp:CheckBoxList>

  <br /><br />
  Questions or comments:<br /><br />
  <asp:textbox TextMode="Multiline" ID="message"
  cols="30" rows="5" runat="server" />
  <br /><br />
  <asp:Button
  Text="Send"
  OnClick="Button_Click"
  Runat="Server" />

</form>
</asp:label>
<asp:Label ID="thankYou"
runat="server">Thank You, Your Message Has Been Sent</asp:label>
</div>
</body>
</html>

And here's a cleaner copy of almost the same thing, but with less emphasis on design and fewer fields


<Script runat="Server">

'******************************************
'This Sub routine happens whent the page loads
'similar to an onLoad event you may have included
'in your body tag before
'It essentially says that if the form has NOT been submitted
'then the object called contactForm should be visible
'and the object called thankYou should not be visible
'The reverse is true if the form HAS been submitted
'******************************************

   Private Sub Page_Load(ByVal s As Object, ByVal e As EventArgs)
      If Page.IsPostBack Then
         contactForm.Visible = False
         thankYou.Visible = True
      Else
         contactForm.Visible = True
         thankYou.Visible = False
      End If

   End Sub



'******************************************
'This Sub wil be called when a button clicked that references
'this Sub in an OnClick event.
'Here we create our message by building up a string for email content
'based on the fields the visitor filled out.
'
'Basically if the field had an ID=ContactName then
'to reference this we call ContactName.Text
'this is similar to how we used to use request.form("ContactName")
'
'Once all that is in place we simply use Web.Mail.MailMessage()
'and System.Web.Mail.SmtpMail to send our email
'
'Now that our form has been submitted the Page Load event is called
'again and we are only displaying the contents of the thankYou Label
'******************************************


   Sub Button_Click( s As Object, e As EventArgs )
      Dim strEmail as String = ""


      strEmail += "Contact Name:" & contactName.Text & vbcrlf
      strEMail += "Company Name: " & businessName.Text & vbcrlf
      strEmail += message.Text

      Dim mmMail As New System.Web.Mail.MailMessage()
      Dim objSmtpServer As System.Web.Mail.SmtpMail
      mmMail.From = email.Text
      mmMail.To = "you@you.com"
      mmMail.Subject = "CONTACT FORM"
      mmMail.Body = strEMail
      objSmtpServer.SmtpServer = "our.smtp.server"
      objSmtpServer.Send(mmMail)

   End Sub

</Script>

<html>
<body>
 <asp:label ID="contactForm" runat="server">

<form runat="Server">


Business Name:<asp:TextBox ID="businessName" runat="server" />
<br />
Contact Name: <asp:TextBox ID="contactName"runat="server" />
<br />
Email Address:<asp:TextBox ID="email" runat="server" />
<br />

Questions or comments:<br />
<br />

<asp:Button Text="Send" OnClick="Button_Click" Runat="Server" />

</form>


 </asp:label>



 <asp:Label ID="thankYou" runat="server">

    Thank You, Your Message Has Been Sent


 </asp:label>

</body>
</html>

ASP to ASP.NET IV

The imageBOX (Our Print Portfolio)


<%
dim iStart
dim iStop

   if request.querystring("iStart") = "" then
      iStart = 0
   else
      iStart = request.querystring("iStart")
   end if

iStop = iStart + 2

with response
.write "<h1>Chicago Business Cards</h1>"

Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder("DIRECT PATH TO OUR PRINT IMAGES")
Set files = folder.Files

dim printARR()
   For Each file in Files
      redim preserve printARR(y)
      printARR(y) = file.name
      y = y + 1
   next


.write "<table border=""0"" width=""100%"">"
.write "<tr>"
.write "<td width=""25%"">"

   if iStart > 0 then
      response.write "<a href=""printport.asp"">First</a><br><br>"
   end if

.write "</td>"
.write "<td width=""25%"">"

   if iStart > 0 then
      response.write "<a href=""printport.asp?iStart=" & iStart - 3 & """>Previous</a><br><br>"
   end if

.write "</td>"
.write "<td width=""25%"">"

   if iStop < (ubound(printARR) * 1) then
      response.write "<a href=""printport.asp?iStart=" & iStop + 1 & """>Next</a><br><br>"
   end if

.write "</td>"
.write "<td width=""25%"">"

   if iStop < ubound(printARR) then
      response.write "<a href=""printport.asp?iStart=" & ubound(printARR) - 2 & """>Last</a><br><br>"
   end if

.write "</td>"
.write "</tr></table>"

   if ubound(printARR) < iStop then
      iStop = ubound(printARR)
   end if

   for i = iStart to iStop
      response.write "<img src=""printimages/" & printARR(i) & """><br /><br />"
   next

end with
Set files = folder.Files
Set file = Nothing
Set fso = Nothing

%>

So the issues at hand are how does ASP.NET handle Arrays and the File System Object of ASP Classic....

I sought out answers...

references so far:

After reading all this and some others I will list below, I have decided to use the ASP.NET datagrid instead of the Array I used in the original script. I did start off writing an ASP.NET script using the array which was more true to the original script, but never got a real grip on how to page through the DataList. The built in paging in the DataGrid is just awesome and too good to pass up.


<%@ Import Namespace="System.IO" %>

<script language="VB" runat="server">
  Sub Page_Load(sender as Object, e as EventArgs)
    BindData()
  End Sub


 Sub BindData()
    Dim dirInfo as New DirectoryInfo("PATH TO FILE")
    imageList.DataSource = dirInfo.GetFiles("*.jpg")
    imageList.DataBind()
  End Sub


 Sub NewPage (sender As Object, e As DataGridPageChangedEventArgs)
    imageList.CurrentPageIndex = e.NewPageIndex
    BindData()
  End Sub

</script>
<form runat="server">


<asp:DataGrid runat="server"
	id="imageList"
	AutoGenerateColumns="False"
	AllowPaging="True"
	OnPageIndexChanged="NewPage"
	PageSize = "3"
	showheader = "True"
	border="0"
	>
    <pagerstyle
         nextpagetext="Next" prevpagetext="Back"
         CssClass="a"
         position="top"
         pagebuttoncount=3
         horizontalalign="left" />

<Columns>
	<asp:TemplateColumn>
	<ItemTemplate>
	<asp:Image
	ImageUrl='<%# "printimages/" &  DataBinder.Eval(Container.DataItem, "Name") %>'
	runat="server"/>
	</ItemTemplate>
	</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
</form>

While this solution works for us I still want to rebuild the very customizable imageBOX as well as further develop the look and feel of the datagrid. Need "First" and "Last" links and the ability to add different image types.

Although, in my reading I am finding it is not that hard to build the First Page and Last Page links, I am somewhat disappointed that this functionality isn't already built in to the datagrid. It would seem so natural in conjunction with the functionality that is already there... maybe this was a rushed job? Is there some reason this wasn't added in ?

As a side note I talked extensively with Dan Kirkwood Jr., of Eagle Innovations, Inc., about this topic, as he is as far as I know the only ASP.NET guru I personally know. Here's a a bit of that Conversation

ASP to ASP.NET III

This article documents work done on Insert Title Web Designs

XML.ASP

At the heart of our website is this single file/script which calls all other pages and allows us to incorporate new pages into our site without a lot of revamping or reconfiguring.

This file was discussed in Part 1 of the article and here is what I did.

From the original code below:


<%
Set xml = Server.CreateObject("Microsoft.XMLHTTP")

	dim URL,page
	URL = "http://www.insert-title.com/web_design/"
	page = request.querystring("page")
		if page = "" then
			page = "dcontent"
		end if

	dim ext
	if left(page,9) = "articles/" then
		ext = ".html"
	else
		ext = ".asp"
	end if
Set fso = CreateObject("Scripting.FileSystemObject")
if fso.FileExists ("FULL PATH TO THE FILE" & replace(page,"/","\") & ext) then
	xml.Open "GET", URL & page & ext, False
	xml.Send
	Response.Write xml.responseText
else
	response.write "Page not found, sorry"
end if
Set xml = Nothing
%>

I created the following


<%@ Control Language="vb"%>
<%@ Import Namespace="System.Net" %>
<script language="VB" runat="server">
Sub Page_Load(sender as Object, e as EventArgs)
   Dim objWebClient as New WebClient()
   Dim page as String
   Dim ext as String
   Dim objStringBuild as StringBuilder
   page = Request.QueryString("page")
      if page = "" then
         page = "dcontent"
      end if


      if page.IndexOf( "articles/" ) > 0 then
         ext = ( ".html" )
      else
         ext = ( ".asp" )
      end if


   objStringBuild = New StringBuilder ("http://www.insert-title.com/web_design/")
   objStringBuild.Append (page)
   objStringBuild.Append (ext)

   Dim strURL as String
   strURL = objStringBuild.ToString()
   Dim objUTF8 as New UTF8Encoding()
   responsetext.Text = objUTF8.GetString(objWebClient.DownloadData(strURL))
End Sub
</script>
<asp:label id="responsetext" runat="server" />

I also updated the default.aspx file to include the new xml.ascx (formerly xml.asp) user control to read


<%@ Page Trace=False Language="vb" %>
<%@ Register TagPrefix="oo" TagName="Open" Src="open.ascx" %>
<%@ Register TagPrefix="xx" TagName="XML" Src="xml.ascx" %>
<%@ Register TagPrefix="cc" TagName="Close" Src="close.ascx" %>
<oo:Open id="Open" runat="server" <>/oo:Open>
<xx:XML id="XML" runat="server" <>/xx:XML>
<cc:Close id="close" runat="server" <>/cc:Close>

What I did

Based on two articles I read, one from 4guysfromrolla.com, ASP.NET Unleashed (c/o Dan Kirkwood Jr. of Eagle Innovations). I was able to develop the new code. One thing to note is that there doesn't seem to be a lot of support when it comes to String Manipulation in ASP.NET available on the web, so I did have to turn to the book for that, which I must say seems to be the best reference for this feature as of yet.

So, essentially, I removed the "XMLHTTPObject" and began working with the "WebClient()" class.

I used the "StringBuilder" class to add my desired extension to the "strURL" creating


http://www.insert-title.com/web_design/default.asp?page=articles/jtops.html

from


"?page=articles/jtops"

One thing I have not yet handled was the "File Not Found" issue, this was originall handled with ASP Classics FileSystem Objectr, I will have to find a solution to this before all is done.

At first this class for building up a string seemed a bit alien to me, but after using it a bit, it isn't really all that different from what you may have already done in classic ASP


str = "abcdefgh"
str = str + "ijklmnopqrs"
str = str + "tuvwxyz
response.write str

BECOMES


<%@ Import Namespace="System.Net" %>
<script language="VB" runat="server">
Sub Page_Load(s as Object, e as EventArgs)

    Dim str as StringBuilder

	str = New StringBuilder ("abcdefgh")
	str.Append ("ijklmnopqrs")
	str.Append ("tuvwxyz")

	Dim strText as String = str.ToString()
	myText.Text = strText
End Sub
</script>
<asp:label id="myText" runat="server" />

Another issue I ran across was the lack of support of the ASP Classic function "Instr"

Where this would have worked in Classic ASP


dim ext
if inStr(page,"articles/") > 0 then
	ext = ".html"
else
	ext = ".asp"
end if

I now had to use:


if page.IndexOf( "articles/" ) > 0 then
         ext = ( ".html" )
      else
         ext = ( ".asp" )
      end if

Not a huge difference, but we still seem to be lacking in documentation about these string manipulation features for .NET

Next Task: Converting some of the dynamic applications on the site from ASP Classic to ASP.NET

ASP to ASP.NET II

This article documents work done on Insert Title Web Designs

Getting the Fundamentals sorted out.

I started by readng a bit of this wonderful article: http://authors.aspalliance.com/anjum/ASPMigration.aspx

Based on the information in that article I've rewritten the default.asp page from


<!--#include file="open.asp" -->
<!--#include file="xml.asp" -->
<!--#include file="close.asp" -->

TO


<%@ Page Trace=False Language="vb" aspcompat="true" %>
<%@ Register TagPrefix="oo" TagName="Open" Src="open.ascx" %>
<%@ Register TagPrefix="cc" TagName="Close" Src="close.ascx" %>
<oo:Open id="Open" runat="server" ></oo:Open>
<cc:Close id="close" runat="server" ></cc:Close>

And renamed the file from default.asp to default.aspx.

One thing I noticed is that the inclusion of aspcompat="true" led me to believe that it would be needed in order to process some of the older ASP code in these pages, but even without everything is okay so far. (leaving it nonetheless)

I've skipped the xml.asp tranformation for now, attempting to get the easier solutions in hand, first.

At the top of the open.asp page which I renamed open.ascx making it a user control I added the following


<%@ Control Language="vb" %>
<%@ Register TagPrefix="lb" TagName="leftBar" Src="leftBar.ascx" %>

And where I used to have the leftBar.asp included I replaced


<!--#include file="leftBar.asp" -->

WITH


<lb:leftBar id="leftBar" runat="server" ></lb:leftBar>

A problem arises!

At the top of the open.asp (now open.ascx) I used to have the following


<%
Response.CacheControl = "no-cache"
Response.AddHeader "Pragma", "no-cache"
Response.Expires = -1
%>

This gave me the error

Server Error in '/' Application.

----------------------------------

Compilation Error

Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: BC30800: Method arguments must be enclosed in parentheses.

Upon removing the offending code, which turned out to be


Response.AddHeader "Pragma", "no-cache"

all was well, but this is something I will have to return to, in order to find out exactly what ramifications it has on the caching of the pages.

ASP to ASP.NET I

This article documents work done on Insert Title Web Designs

For The Record

For the record I am not a coding guru, like Scott Mitchell or Stephen Walther, or Jeffery Zeldman or any of those other guys. I am however a hands on master. I can get the job done "NOW"

I work everyday in an industry that is heavily saturated and still come out ahead every time. Because I deliver the goods one way or the other.

I've been guilty of writing spaghetti code, using too many session variables and not enough stored procedures.

Skillwise, I'm capable enough to read some documentation and get out of it what i need. CSS,ASP and server-side vbscript are my primary specialties, outside of that I am pretty good with a handful of graphics apps and development tools(Mostly MX)

I understand the bare minimum of javascript and use it only as a client-side form validation tool. I have no intention of writing any of this ASP.NET in any language outside of VB, so all you C# users out there, either need to get good at changing from VB to C# (which is generally , not too complicated) or read a different article.

I do not intend to rewrite this article over and over, so you'll see as I learn from my mistakes in real-time. If one method becomes more efficient that another you won't see me changing it on all previous sections of the article. This is an evolution of someone who knows very little about ASP.NET, but has a strong understanding of Classic ASP. If this sounds like you, you'll appreciate this article. If not, you'll think it's a waste of time.

Evaluating What Needs To Be Changed.

This site currently consists of a very simple file structure and few databases which is why I think it is a perfect project for learning ASP.NET step by step while attempting to achieve all the same results.

Currently almost every page is called from the default.asp page which looks like this:



<!--#include file="open.asp" -->
<!--#include file="xml.asp" -->
<!--#include file="close.asp" -->

open.asp

The open page consists of all the meta info, calling the style sheet and top half of the graphical layout.

The open page also has an include statement for the leftBAR.asp which constitutes all the navigation at the left hand side of the page.

xml.asp

The xml.asp page is really the heart of organizing this website. Using the XMLHTTP Object I develop page upon page without the need of going through a lot of trouble to add it to the site.

Here is the xml.asp code - -it may come in handy for you.


<%
Set xml = Server.CreateObject("Microsoft.XMLHTTP")

	dim URL,page
	URL = "http://www.insert-title.com/web_design/"
	page = request.querystring("page")
		if page = "" then
			page = "dcontent"
		end if

	dim ext
	if left(page,9) = "articles/" then
		ext = ".html"
	else
		ext = ".asp"
	end if

xml.Open "GET", URL & page & ext, False
xml.Send
	Response.Write xml.responseText
Set xml = Nothing
%>

In essence what this means is that

  • a call to "http://www.insert-title.com/web_design/?page=web"
  • becomes "http://www.insert-title.com/web_design/default.asp?page=web.asp
  • and a call to "http://www.insert-title.com/web_design/?page=articles/jtops"
  • becomes "http://www.insert-title.com/web_design/default.asp?page=articles/jtops.html"

The xml.asp file picks up the content of that page and returns it in between open.asp and close.asp.

Of course, a large concern is how ASP.NET will handle the current CSS that we apply to this site. This will need to be addressed as we move along

Methodology

Here's the gameplan -

Start with the big picture get the fundamentals of the site sorted out and drill down to each single page.

Also - I dont want to rely on any GUI/IDE (i.e., Dreamweaver, VS.NET, etc.) to make any changes, so all coding will happen in my favorite coding tool, Textpad