Sie sind auf Seite 1von 67

Using PreviousPage with a Master Page

Using the PreviousPage scenario, with Master Pages presents its own particular problems, but they're not hard to overcome. As you may have noticed, using "PreviousPage" scenario isn't quite as simple as it looks in all the tutorials. In fact, using most of the tutorials/code samples on the web, doesn't work at all. That's specifically because they aren't taking into consideration, that, with a Master Page, you have a ContentPlaceholder, and you must first look there, to find the data from the previous page. For those who don't know, the base samples show a scenario in which the 'Submit' button on the first page has it's PostBackURL property assigned to the second page in the postback scenario. The code, then would look something like:
Dim Name As TextBox Name = Page.PreviousPage.FindControl("txtName") Label1.Text = Name.Text

As we stated earlier, if you're using a Master Page in your website (with a Master Page designated, specifically, in the submitting page), this doesn't work. In able to do this, you must look in the Content Placeholder of the submitting page, first. Therefore, the code would look more like this:
Dim ph As ContentPlaceHolder = CType(PreviousPage.Master.FindControl("YourContentPlaceholderID"), ContentPlaceHolder Dim tb As TextBox = CType(ph.FindControl(YourControlID), TextBox) Label1.Text = tb.Text

In this sample, we first look inside the submitting page, then we find the Contentplaceholder. Then, once we find the contentPlaceholder, we look inside it, to find the control, from which we need to retrieve the data. Here's a small function which does all this for us, to cut down on repetitive code:
Function GetData(ByVal CtrlID As String) As String Dim ph As ContentPlaceHolder = CType(PreviousPage.Master.FindControl("YourContentPlaceholderID"), ContentPlaceHolder) If Not ph Is Nothing Then Dim tb As TextBox = CType(ph.FindControl(CtrlID), TextBox) If Not tb Is Nothing Then Return tb.Text End If End If Return String.Empty End Function

Then, to use it, you merely do something like this:


lblName.Text = GetData("txtName")

Helper Functions
(How to handle Conditional Formatting on a page) One of the most common questions on the net about ASP.Net, when coming from a Classic ASP background, is how to handle situations in which conditional programming is necessary. For instance, in Classic ASP, if you had this code:
If recordset("fieldName") <> "" Then ' do this Else ' do this End if

Since, in ASP.Net, we do not have the sequential code, coming throught the page, like it did with Classic ASP, sometimes we'll have a label or textbox (or whatever), with the same field information which would have been previously contained in 'recordset("fieldName")'. To handle this, we would create a helper function, in our code section. So, in this case, let's call the Function 'CheckItem'. In the tag, we'd start with something like this:
<asp:Label ID="Label1" Text='<%# Container.DataItem("fieldName") %>' Runat="server" />

Next, we'll add the code for the function:

<asp:Label ID="Label1" Text='<%# CheckItem(Container.DataItem("fieldName")) %>' Runat="server" />

Then, in our code section, we'd create the 'CheckItem' function:

Public Function CheckItem(ByVal sItem as String) as String If sItem<>"" then Return sItem Else Return "n/a" End If

This is all there is to it. When it's time for the text in Label1 to be shown on the web page, first, the helper function, 'CheckItem' is run against the text which is designated. If that item does not equal an empty string, then that item is presented on the page. If not, 'n/a' is presented

A Beginners Guide to the Connection String


The Magic - de-Mystified! One of the most misunderstood items, using ASP.Net, and some of the most asked questions, are about Connection Strings - the way in which you connect to the database. Any time you connect to a database, a Connection String is required, so it's an integral part of .Net programming, whether it's ASP.Net or WinForms programming. Of course, here, we're addressing only ASP.Net programming, and mainly with SQL Server. Each Connection String has several 'sections' in it. The basic form of the Connection String consists of:
ConnectionString=""

Your string can reside in different locations, including a DataSource Control (ASP.Net 2.0), in code, on the fly, and in the Web.Config file. Most likely, if you are using a particular string in multiple locations throughout your website, it will probably be best to store it in the Web.Config file. Then, any time, in your application, you need the connection string, the setting in the Web.Config file is referenced instead of the exact connection string. This way, if the connection string ever changes (and believe me, after years of doing this, I'm here to attest that it most likely WILL change at some time), then you will only need to change it in one place. How this is done, will be addressed, later on in this tutorial, There are many sections of a connection string which are possible, but there are 3 basic sections which are absolutely required: The Server The Database Name The authentication The Server can be notated in the Connection String several different ways, however, the most common usages are:
Data Source=YourServerGoesHere Server=YourServerGoesHere

In the above section, instead of 'YourServerGoesHere', you would put the address to the Server itself, in either a domain type of construction (like:MyServer.Com), or an IP address (like: 198.12.1987). So, at this point, using the Basic form from above, this would look like:
ConnectionString="Data Source=YourServerGoesHere" or ConnectionString="Data Source=YourServerGoesHere"

Naturally, the above, as mentioned before, can use 'Server' instead of 'Data Source' Next comes the Database section. It may be in 2 different forms:
Database=Northwind Intial Catalog=Northwind

The different sections in the Connection String need to be separated, so in order to do this, we use a semi-colon in between the different sections ";". The entire connection string, then, will be surrounded by double-quotes At this point, using the Basic form from above, this would look like:
ConnectionString="Data Source=YourServerGoesHere;Initial Catalog=Northwind" or ConnectionString="Server=YourServerGoesHere;Database=Northwind"

And, lastly, we come to the Authentication method. The two types of authentication use either Windows Authentication, or a direct access to the database, using a User ID and a Password. For Windows Authentication, the Authentication section would look something like : Integrated Security=[true, false, yes, no, SSPI] Trusted Connection=[true, false, yes, no, SSPI] True, False, Yes, no and SSPI are different from each other, and your choice to make. SSPI is equivalent to 'true', and is the generally recommended when using Windows Authentication. When set to 'false', it is required that you use a User ID and Password in the connection string. Also, a point to make here, is that, if it is set to 'false', it's not really required that you put it in the connection string at all. Now, we come to the User ID and Password parts. These, of course, are the User ID and Password required, when logging into the Server. The form can either be 'User ID' or 'uid', and either 'Password' or 'pwd'. Case sensitivity does not matter here. At this point, using the Basic form from above, this would look like:
ConnectionString="Data Source=YourServerGoesHere;Initial Catalog=Northwind;User ID=YourUserNameGoesHere;Password=YourPasswordGoesHere" or ConnectionString="Server=YourServerGoesHere;Database=Northwind;uid= YourUserNameGoesHere;pwd= YourPasswordGoesHere"

One thing which is not necessary, but is commonly asked about on the Net is the Connection Timeout. Sometimes, with more resource intensive queries, it might be necessary to lengthen the time it takes to complete the query, before it stops and returns an error. To do this, add a Connection Timout section to the Connection String. It uses seconds as an argument, and can use either of the following forms:
Connection Timeout=120 Connect Timeout=120

Now, to store this Connection String in the Web.Config file, inside the configuration section, locate (if available) or create (if not available) a 'connectionStrings' section:
<connectionStrings> </connectionStrings>

Then, put a new line in this section, referencing your Connection String:
<add name=" ConnStringName" connectionString="server=YourServer;uid=YourUID;pwd=YourPassword;database=N orthwind" providerName="System.Data.SqlClient" />

Then, in your code, you would reference this, as in the following: 4

Dim myConnection As SqlConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("YourConnStringName"). ConnectionString)

In a DataSource Control, you would reference it like the following:


ConnectionString="<%$ ConnectionStrings:YourConnStringName %>">

There are many other things you can add in, and, if you would like to explore it further, you are invited to visit this MSDN link: MSDN Connection Strings As you can see, when you break it down, Connection Strings can be very easy to understand. I hope this tutorial has explained it in a way that it is not confusing and very helpful.

Membership/Roles with Remote DB


(Other than SQL Express) This will be a very short tutorial, actually. If you know how easy it is to create all the tables, and stored procedures with the ASP.Net Login controls, you know that it creates a database, by default, in the App_Data directory, called ASPNet.mdf. However, in the real world, that sometimes doesn't cut it - especially if you have a hosted web site. There are only two steps to get everything setup on any other SQL 2000 or SQL 2005 server. The first step is to use the ASPNet_regsql.exe application that comes with your installation. The hardest part about using this is that you will need to use the Command Prompt (Start/Run/cmd) and navigate to the correct directory/folder, which is:
C:\windows\Microsoft.net\Framework\

At the time of this writing, the version is v2.0.50727. When you get to the directory, type in:
aspnet_regsql -W

There are a lot of other registration options that are possible, but this will get you to the GUI to handle this, instead of having to learn what all the options might or might not mean to you. The rest is no more difficult than entering the IP address of your SQL Server, the user ID and the Password. Just follow the wizard all the way through this, and it will setup all the Tables and Stored Procedures you need to handle this. The last and second step is to create a ConnectionString entry in the ConnectionString section of your web.config for your application, using 'LocalSQLServer' as the name:
<connectionStrings> <remove name="LocalSqlServer" /> <add name="LocalSqlServer" connectionString="server=YourSrvr;uid=YourUID;pwd=YourPWD;database=YourDB" providerName="System.Data.SqlClient" /> </connectionStrings>

As you probably noticed, there is a line above the connectionString, with 'remove LocalSQLServer'. If you already have created a connection to the default server, this may be in the Machine.config file already. This makes sure the one you want is used. It removes it from memory, if it's there, and then adds your particular server back. Then, the last step is to add a Membership/Provider section to the Web.Config to tie it all together:
<membership defaultProvider="AspNetSqlMembershipProvider"> <providers> <remove name="AspNetSqlMembershipProvider" /> <add connectionStringName="LocalSqlServer" name="AspNetSqlMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"

passwordStrengthRegularExpression="" requiresQuestionAndAnswer="true" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> </providers> </membership>

Here, the default name, 'AspNetSqlMembershipProvider' is used, adding it as the defaultProvider in the Membership section and assigning (the name attribute) in the Provider section. Also notice here, that there are a lot of attributes you can use to tighten down the security in your application. Remember, at the first of this tutorial, when I said it would be very short and easy? Well, that's all there is to it.

Multiple DropdownLists with AppendDataBoundItems


(Using ASP.Net 2.0) With ASP.Net 2.0, using multiple DropdownLists is really simple. However, what happens when you want to add an extra item to the first DDL, like 'ALL'? Consider this scenario: You want all models (in this sample) returned, when the 'All' item is chosen. You can't put 2 SelectCommands in one DataSource control, but, when 'All' is selected, you still need the SQL statement (in this case, the DataSource Control's 'SelectCommand' property) to change. But, with just a little code, this is still fairly easy to accomplish. To do this, in this scenario, we'll need two DropDownLists - one for the 'Brands' of automobiles, and one for the 'Models' of the particular brands. First, you create a new sub (here, it's named 'doCheck', but you can call it anything you want), and add the following code:
Sub doCheck(Source as Object, E as EventArgs) if ddlBrand.SelectedItem.Value=99 then ds2.selectCommand="Select id, model from Models order by model" End If End Sub

Then, reference that subroutine in the DropDownList's tag:


<asp:DropDownList id="ddlBrand" DataTextField="Brand" DataValueField="id" DataSourceID="DS1" AppendDataBoundItems="True" Runat="server" AutoPostBack="True" OnSelectedIndexChanged="doCheck" <asp:ListItem Value="99">All</asp:ListItem> </asp:DropDownList>

The 'AppendDataBoundItems' property is added, along with the ListItem, containing a value, so that the 'All' entry gets added to the DDL along with all the items returned from the Database. Keep in mind, the 'All item was appended here, with a value of 99. There's nothing magical about that number. It simply must be a number higher than anything the DDL's databound value will return. Next, we'll create the second DropDownList (for the models table):
<asp:DropDownList id="ddlModels" DataTextField="Model" DataValueField="id" DataSourceID="DS2" Runat="server"> </asp:DropDownList>

Notice that each one of the DDLs reference it's own DataSource control (DS1, and DS2). So, let's create them here:

<asp:SQLDataSource ID="DS1" Runat="Server" SelectCommand = "SELECT id, Brand From Automobiles" ConnectionString="<%$ ConnectionStrings:YourConnStringGoesHere %>"> </asp:SQLDataSource> <asp:SQLDataSource ID="DS2" Runat="Server" ConnectionString="<%$ ConnectionStrings:YourConnStringGoesHere %>"> <SelectParameters> <asp:ControlParameter ControlID="ddlBrand" Name="ID" PropertyName="SelectedValue" />

</SelectParameters> </asp:SQLDataSource>

The 'SelectCommand' in the first DataSource control is straight-forward. It simply returns all the brands from the 'Automobiles' table. However, in the second DataSource control, though it can be added directly into the DataSource Control, it's a long string, so, to break it up, and save more horizontal real estate on the screen, we're showing it here, in the 'Page_Load' event routine:
Sub Page_Load(Source as Object, E as EventArgs) DS2.SelectCommand="SELECT Models.id, Models.Model From " & _ "Models INNER JOIN Automobiles ON Automobiles.id = Models.Auto_ID " & _ "Where ((Models.Auto_ID = @ID))" End Sub

The second DataSource (DS2), as you will notice, adds a ControlParameter, referencing the SelectedValue of the ddlBrand DropDownList. If you want to see an online example of this code, along with the source code, check out: Multiple DropDownLists Sample/Source That's pretty much it. That's all you need to be able to add an item to the first DDL, after databinding, allowing the user to select all models, changing the SQL statement which returns the models, displaying them in the second DropDownList.

Creating a Popup Details Page


Here's the scenario - you have an order page, to view the details of specific orders. Now, from that order page, you'd like to see the details of the customer who made the order, but you don't want to leave the order page behind. The answer is a popup page. I know many people do not like popup pages, but for specific purposes, like this one, they can be very useful. To implement this scenario, first, let's put a label on the page, for the Customer Name:
<asp:Label ID="lblCustName" Runat="server" />

Now, create a function to return a link to the page:

Function ShowCustName(sName as String, CustNum as String) if sName<>"" then Return "<a language=""Javascript"" href=""#"" onClick=""window.open('CustInfo.aspx?custnum=" & _ CustNum & "','Cust_Info', 'scrollbars=1,resizable,width=350, height=450');return false;""><b>" & sName & "</b></a>" end if End Function

What this function does, is to create a hyperlink to a second page ("CustInfo.aspx"), which will be the popup page, using the Customer # and the Customer name as arguments. The Customer name is only used, however, for the display part of the hyperlink.

10

Beginners Guide to the BulletedList


The BulletedList is an ASP.net server control which is new, with v2.0 of ASP.Net. At first glance, you might think that, being a way to use a database to populate an HTML select list is a really nice feature. However, if that's all there was too it, you'd be correct, but the feature list is really nice! First off, let's start with the data binding features. Naturally, as you'd expect with a v2.0 control, the DataSourceID can be used to populate the list, along with DataTextField and DataValueField properties for populating the Text and Values of each list item. Now, let's couple that with the DisplayMode property. There are three modes:

HyperLink LinkButton Text (default)

First, let's look at the Hyperlink mode. It can be used with either Databound or nonDataBound BulletedLists. When using a Databound BulletedList, the DataValueField can be populated with the actual URL, while any text field can be used for populating the DataTextField. If the BulletedList is non-DataBound, the actual URL can be added to the 'Value' attribute of each ListItem. Also, the Linkbutton mode can be used to fire off a subroutine or function to do just about anything within the confines of ASP.net. Using code, or another DataSourceID, by choosing an item in the BulletedList to trigger that code. For instance, the display text of each item can be used in a SQL statement's 'Where' clause, or any other use which uses the text or value of the selected list item. In the BulletedList tag, the OnClick event is used:
<asp:BulletedList ID="BL1" Runat="Server" OnClick="Choose_Item" />

Then, the actual code is placed in a subroutine, somewhat like this:

Sub Choose_Item (Src As Object, e As BulletedListEventArgs) dim MySQL as String="Select (FieldList) from (TableName) where (FieldName)='" & _ BL1.Items(e.Index) & "'" ' Rest of code or DataSource SelectCommand assignment goes here End Sub

There are 8 different style which can be used with the BulletedStyle property, which are, for the most part, fairly self-explanatory:

Circle - Hollow Circle Disc - most common Bullet LowerAlpha - Letters LowerRoman - Roman Numerals Numbered Square UpperAlpha - Letters UpperRoman - Roman Numerals CustomImage

11

Naturally, along with that, all the normal Server Control properties are available, Backcolor, Forecolor, Borderstyles, Fontstyles, etc. If you notice, the last item in the list is 'CustomImage'. When this style is chosen, along with the 'BulletImageURL' property assignment, a custom bullet image can be used instead of using one of the default styles. Here's an example: <asp:BulletedList ID="blexample" Runat="Server" Item BulletImageUrl="/images/bluearrow.gif" 1 BulletStyle="CustomImage"> Item <asp:ListItem>Item 1</asp:ListItem> 2 <asp:ListItem>Item 2</asp:ListItem> Item 3 As you can easily see, Bulletedlists can be very useful in your every day ASP.Net coding life. It kind of makes you wonder "Why wasn't this included before?"
<asp:ListItem>Item 3</asp:ListItem> </asp:BulletedList>

12

Emailing Form Results w/AsP.Net 2.0


(It's much easier than you might think) The task at hand is taking the input from a form, and emailing those results to a desired target. If you've worked with ASP.Net v1.1, things have changed a little. Please check out the basic email precepts in this tutorial. Even if you are new to programming, you're going to be amazed at how simple this really is. This is an updated/revamped Tutorial, based on the same scenario as a previous tutorial, using ASP.Net v1.1. The first thing that's necessary, of course is the form. For this example, we're using VB.Net and ASP.Net server controls. Naturally, for the purposes of this tutorial, we're going to keep it fairly simple, but the same principles apply for a much more expanded form. Here's a sample of the HTML section for the form:
<Form id="form1" runat="server"> First Name: <asp:TextBox id="txtFname" runat="server" /> Last Name: <asp:TextBox id="txtLname" runat="server" /> Email: <asp:TextBox id="txtEmail" runat="server" /> CC: <asp:TextBox id="txtCC" Runat="server" /> <br />Favorite Color: <asp:DropDownList id="ddlColor" Runat="server"> <asp:ListItem>Blue</asp:ListItem> <asp:ListItem>Red</asp:ListItem> </asp:DropDownList><br /> <asp:Button id="btnEmail" Text="Email Form" onclick="doEmail" runat="server" /> </Form>

The next thing to make sure we have listed on our page is a reference to the correct namespace. For emailing, it's: <%@ Import Namespace="System.Net.Mail" %> As you probably noticed, there is an 'onclick' event referenced for the form's button, 'doEmail'. This is where we'll take the output of the form and do the actual emailing of the input.
Sub doEmail(Source as Object, E as EventArgs) Dim sMsg as String sMsg+="Hi there - here's the information I entered in the form." & vbcrlf sMsg+="First Name : " & txtFname.Text & vbcrlf sMsg+="Last Name : " & txtLname.Text & vbcrlf sMsg+="Favorite Color: " & ddlColor.SelectedItem.Text Dim Msg as MailMessage = new MailMessage() Dim MailObj As New SmtpClient("mail.YourDomain.com") Msg.To.Add(new MailAddress(txtEmail.text) Msg.CC.Add(new MailAddress(txtCC.text) Msg.BCC="JohnnyWhite@jwmason.com" '<- - - you can send it to yourself at the same time. Msg.From = new MailAddress("me@Here.com", "Big D") Msg.Subject="Here's the subject of the email" Msg.Body=sMsg Msg.IsBodyHtml = "False" MailObj.SmtpServer ="mail.Wherever.com" < - - check with your hosting provider on what to put in here MailObj.Send(Msg)

13

End Sub

In this sub, you'll notice that the first thing we're doing is creating a string variable to store our email message. The first part of the message is the opening line, but then you'll see we're adding and formatting the specific data from the form, item by item. Naturally, that can be formatted pretty much most anyway you'd like. Next, we actually reference and instantiate the email object (MailMessage), followed by the essential, basic parts of any email message, the To, From, Subject and Body segments, along with the CC (carbon copy) section. We could also add a BCC section if wanted (Blind Carbon Copy). Remember that string variable we created at the first of the subroutine? We assign it in the Body section. You'll probably notice that there are no quote marks around sMsg, and that's BECAUSE it's a variable. If you wanted to hard code a BODY section here, you'd surround it with double quotes. Before sending the message, there are two things necessary - assigning a format (Text or HTML), and assigning an SMTP server. If you are using a hosted site, many of them use the format - 'mail.Wherever.com', with 'Wherever.com' section being your own domain name. In this case, we're using a pure text format, but, just as easily, we could have used an HTML format: Msg.IsBodyHtml = "True" You could then use just about any valid HTML markup tags you wanted inside the BODY section. Of course, you'd need to make sure the person to whom the email is being sent (most likely YOU, in this case) can accept HTML emails correctly. Then, the last line is what really creates and sends the email message: MailObj.Send(Msg) Naturally, you'd probably want to add in some validation (ASP.Net validation will be addressed in another Tutorial here), so blank form field results are not sent in the email. So, here you have it in a nutshell - create an input form, along with a subroutine to actually send the email, and you're ready to go. The user just fills in the information for which you asked, clicks the 'Email Form' button and the email is on it's way. 'What about attachments?', you may ask. That's a very good question. In continuing with my 'It's not as hard is it may sound' way of presenting - that's exactly right - it's very simple. All you need to do (before the SMTP.Send method, of course is to add this line:
Dim myFile As New Attachment(txtAttachmentPath.Text) MyMessage.Attachments.Add(myFile)

The only catch here is that the file that you're sending MUST to be ON the file server, and the path you include here needs to be a valid path, either using 'Server.Mappath', or an explicit path. Well - that's all there is to it...no pain, right?

14

Two Page Data Retrieval


(With HyperLinkField) Here's the scenario, using ASP.Net 2.0 (and above): We have two web pages called GV1.aspx and NewPage.aspx. In GV1.aspx, we have a GridView, listing only a few fields from a database. From that page, we will designate one field as a HyperLinkField, so that, by clicking on it, we will be transferred to the second page (Newpage.aspx), using a QueryString. In that second page, we will retrieve all fields in the table based on the ID used in the QueryString. This actually very easy to accomplish using ASP.Net 2.0, and most of the technology has already been included here, at ASPNet101.com: Code Sample - Master Detail Solution Really, the only 2 new things are the use of the HyperLinkField and the two-page scenario. For those of you who are familiar with ASP.Net 1.x, the HyperLinkField looks pretty much like the HyperLinkColumn, used with a DataGrid. The format is:
<asp:HyperLinkField DataTextField="au_lname" DataNavigateUrlFields="au_ID" DataNavigateUrlFormatString="NewPage.aspx?id={0}" HeaderText="Click For Details" />

Like the BoundField (or BoundColumn, with the DataGrid), it is not necessary to use a TemplateColumn. In our scenario, the first page will consist of a GridView and SQLDataSource control only, using the Pubs database for the example. The last name field will be used for the Hyperlink:
<asp:GridView Runat="server" Id="gvAuthors" GridLines="Both" DataSourceID="SQLDS2" DataKeyNames="au_id" SelectedItemStyle-Backcolor="Pink" AllowPaging="True" AutoGenerateColumns="False"> <Columns> <asp:BoundField DataField="au_fname" HeaderText="au_fname" /> <asp:HyperLinkField DataTextField="au_lname" DataNavigateUrlFields="au_ID" DataNavigateUrlFormatString="NewPage.aspx?id={0}" HeaderText="Click For Details" /> <asp:BoundField DataField="state" HeaderText="state" /> </Columns> </asp:GridView>

The SQLDataSource control looks like this:


<asp:SqlDataSource ID="SQLDS2" runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [Authors] Order by [state]" ConnectionString="<%$ ConnectionStrings:Pubs %>"> </asp:SqlDataSource>

15

The ConnectionString here, is using the ConnectionString section of the Web.Config file, with an entry titled 'Pubs'. What happens on this page, is that, all the records are returned from the Authors table and, with the use of the HyperLinkField, the end-user is then, taken to the second page, based on the item selected in the GridView. Now, on the second page (NewPage.aspx), we again have only two controls - a DetailsView and a SQLDataSource control. The DetailsView is fairly straightforward, using all BoundFields for display. Naturally, if there were other needs or possibilities here, we could use TemplateColumns, or add an Edit Button, etc.
<asp:DetailsView DataKeyNames="au_id" DataSourceID="SQLDS3" GridLines="Both" cellpadding="0" cellspacing="0" Headerstyle-Font-Size="12" Font-Name="Arial" Font-Size="10" HeaderText="Author Details" AutoGenerateRows="False" ID="dvPubs" runat="server"> <Fields> <asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" /> <asp:BoundField DataField="au_lname" HeaderText="au_lname" /> <asp:BoundField DataField="au_fname" HeaderText="au_fname" /> <asp:BoundField DataField="phone" HeaderText="phone" /> <asp:BoundField DataField="address" HeaderText="address" <asp:BoundField DataField="city" HeaderText="city" /> <asp:BoundField DataField="state" HeaderText="state" /> <asp:BoundField DataField="zip" HeaderText="zip" /> <asp:CheckBoxField DataField="contract" HeaderText="contract" /> </Fields> </asp:DetailsView>

/>

The way in which this is populated depends on two things. The main thing is the DataSource control. Here, we assign the ID of the DataSource control in the DataSourceID property, in the same way most or all new 2.0 compliant controls are handled. In that DataSource Control, though, we add a QueryStringParameter for the SelectParameter. Therefore, the data displayed will depend on whatever is assigned in the QueryString, when the page is accessed.

<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:Pubs %>" ID="SQLDS3" runat="server" SelectCommand="SELECT * FROM [PBAuthors] WHERE ([au_id] = @au_id)"> <SelectParameters> <asp:QueryStringParameter Name="au_id" QueryStringField="id" /> </SelectParameters> </asp:SqlDataSource>

As you can see here, there's a 'Where' clause in the Select statement. It's requesting (from the same Database and table) all fields concerning an author, based on the 'au_id' field. That au_id field is in the QueryString. When you copy and paste these two pages and create them on your own website, on the second page. The URL will be something like:
http://localhost/NewPage.aspx?id=118-45-7412

16

In the QueryStringParameter, the QueryStringField property relates to the the 'id' in the URL and the Name property relates to the actual field in the table, from where we retrieve the data. At this point, you can take a big breath, and take this all in. But, that's all you need to do, because, in its simplicity, that's all there is to accomplish this task. Now that wasn't bad at all, was it?

17

Using Parameterized Queries in ASP.Net


Making your Coding Life a Little Easier There are two impelling reasons everyone should learn about Parameterized Queries. One entails one keyboard character and is more of a hassle reliever than anything else. That character, in code, can become either of two different objects, the single quote and the apostrophe. When you're coding, either one can make your life truely miserable at times. The second, and MOST compelling reason to learn Parameterized Queries is to protect your database from SQL Injection Injection Attacks. If you have never heard of them, you need to hear about them now. These attacks can reak havoc on your server and, more importantly, your data. Check out these articles on SQL Injection Attacks: http://msdn.microsoft.com/msdnmag/issues/04/09/SQLInjection/ http://www.tech-faq.com/sql-injection-attack.shtml http://www.codeproject.com/aspnet/SqlInjection.asp Simply by using Parameterized Queries, this becomes a first line of defense, and SQL Injection attacks are stopped in their tracks. Anyone who has ever put together a long, involved SQL statement with variables, juggling single quotes, along with the double quotes (Tutorial on Single and Double Quotes), will tell you that it's not much fun. And - on top of that, when we then talk about the apostrophe, it gets even more complicated. Of course, as most of you know, in an Insert statement, if the last Name is O'Hara, the engine looks at the string, and only sees the apostrophe as a single quote, thereby truncating your perfectly structured SQL statement. Naturally, there are fixes for the latter (Replace statement to double up on the apostrophes, which tells the DataBase engine to interpret the two apostrophes as only one true apostrophe and not a single quote), but that's extra care you must take that's really not needed - but only if you use Parameterized Queries. Let's put together a scenario - we're searching Employees of the Northwind Trading Company by last name. We have a DropDownList (DDL) with all the last names. From that, the end user will choose one, so that the rest of that employee's information will appear. This, naturally, is a fairly simple scenario to start. We don't want to get too complicated too quickly. Since we're searching the database by the last name, The SQL statement, using single quotes would be something like this: sql = "Select * from Employees where Lastname = '" & ddl.selecteditem.text & "'" As you can see, this could get pretty complicated, adding AND clauses and/or OR clauses on the end of the WHERE clause. Using a Parameterized Query, it would look like this: sql = "Select * from Employees where Lastname =@LastName" All we'd need for this to work is to add the following to your code, after instantiating your Command: (assuming you have defined a Command called 'cmd') cmd.Parameters.Add(New SQLParameter("@LastName", ddl.SelectedItem.text)) 18

Of course, this is an example for SQL Server. For OleDb (MS Access, and others), you would use (you guessed it!): cmd.Parameters.Add(New OleDbParameter("@LastName", ddl.SelectedItem.text)) Of course, if you wanted to do a LIKE query (Select * from tablename where fieldname LIKE, etc), you would substitute the '=' sign for 'Like'. THEN, you could add your wildcards ('%' for SQL Server and '*" for MS Access) into the actual data being used for the search. For instance, if you had a text box for the end user to enter data to do a LIKE search - just have them put the wildcards in where they want (at the end, start, or both). Where this really comes in handy is when you create an Insert or Update SQL statement. Suppose you were inserting a FirstName, LastName, Address, City, State, Zip, Phone, and Email address. Here's the older way you would have done this with single quotes: sql="Insert into Employees (Firstname, Lastname, City, State, Zip, Phone, Email) Values ('" & frmFirstname.text & "', '" & frmLastName & "', '" & frmCity & "', '" & frmState & "', '" & frmZip & "', '" & frmPhone & "', '" & frmEmail & "')" As you can see, this can get pretty cumbersome, doing it by hand. Here's the way you would take care of it with a Parameterized Query: Dim MySQL as string = "Insert into NewEmp (fname, LName, Address, City, State, Postalcode, Phone, Email) Values (@Firstname, @LastName, @Address, @City, @State, @Postalcode, @Phone, @Email)" Then, of course, you'd need to specify the parameters: With SQL Server:
With cmd.Parameters: .Add(New SQLParameter("@Firstname", frmFname.text)) .Add(New SQLParameter("@LastName", frmLname.text)) .Add(New SQLParameter("@Address", frmAddress.text)) .Add(New SQLParameter("@City", frmCity.text)) .Add(New SQLParameter("@state", frmState.text)) .Add(New SQLParameter("@Postalcode", frmPostalCode.Text)) .Add(New SQLParameter("@Phone", frmPhone.text)) .Add(New SQLParameter("@email", frmemail.text)) end with

With OleDb:
With cmd.Parameters: .Add(New OleDbParameter("@Firstname", frmFname.text)) .Add(New OleDbParameter("@LastName", frmLname.text)) .Add(New OleDbParameter("@Address", frmAddress.text)) .Add(New OleDbParameter("@City", frmCity.text)) .Add(New OleDbParameter("@state", frmState.text)) .Add(New OleDbParameter("@Postalcode", frmPostalCode.Text)) .Add(New OleDbParameter("@Phone", frmPhone.text)) .Add(New OleDbParameter("@email", frmemail.text)) end with

Here's one note I received from a reader, Randy, that I'd like to mention here: "I found out the hard way that the delineating of parameters must be in the SAME ORDER as they appear in the SQL command."

19

As far as using Stored Procedures, check out this code sample on using a Stored Procedure to populate a DropDownList - naturally, using parameters. We'll discuss wldcards and using the 'Like' operator in another Tutorial called "Parameterized Queries - Part II". I'm sure at this point, it's easy to also see, that consistent naming, from the Form Field names, to the Parameter Names is by far the best way to go. It's much easier to see at a glance, exactly what's going on in the code. I've seen many examples on the net and in books that go into length concerning filetypes, sizes, etc when defining parameters. And while that's a more exact way of doing it, this tutorial shows that there is not just one way to do things in the ASP.Net world. Of course it's always best to make sure the data going in is in the exact form the database needs, in all cases. Therefore, whichever way you decide to do it, make sure your validation is the best it can be.

Parameterized Queries - Part II


Using 'Like' in the Where Clause The basics of using Parameterized Queries in ASP.Net is another tutorial. Be sure to read Part 1. Using 'Like' in the Where Clause, in Parameterized Queries, is one of the more powerful options in SQL. However, it can also be very draining, resource-wise, if used improperly. Sometimes, way too many records can be returned - and in doing so, not only does it take much longer to retrieve, but the resource drain is very costly. When using 'Like' in a Where Clause, we must use a 'wildcard'. In the old days, SQL Server's wildcard was the percent sign (%), while pre-Jet MS Access databases used the asterisk (*). Luckily, now, for both the OleDb Managed Provider (since it uses the Jet engine), and the SQL Server Managed Provider, no matter which database we're using, we can use the percent sign (%). For instance, let's say we have a Name field in the table that includes both first and last names. To query the table for all those people with the last name of Smith, we couldn't use an SQL statement like: Sql="Select * from TableName where Name='Smith'" Since first AND last names are in one field, this query wouldn't return any records. To accomplish the above scenario, we'd need to use 'Like' in the Where Clause. Sql="Select * from TableName where Name Like 'Smith'" But, as you can probably guess - here's where the wildcards come into play. Actually, this SQL statement isn't good enough quite yet. We need to use a wildcard either before, after or both before AND after the criteria, like: Sql="Select * from TableName where Name Like '%Smith'" This would return records if any portion of the field searched ENDED with 'Smith'. To return records if 'Smith' was anywhere in the field searched, it would become necessary to put the % before AND after the criteria ('%Smith%').

20

Now - on to the Parameterized Query uses. Technically, there are three ways in which wildcards, with the 'Like' operator can be used. Number 1: You can use the wildcards in the actual SQL statement, like this: sql="Select * from Tablename where Name Like '%' + @Name + '%'" Again, this sample shows the wildcard at both ends of the parameter, but you can include the wildcards at the first, the end or both places. Number 2: You can use the wildcards in the 'Add Parameter' portion: cmd.Parameters.Add(New SQLParameter("@Name", "%" & text1.text & "%")) If you were using MSAccess, or any database using the OleDb Managed Provider, it would be : cmd.Parameters.Add(New OleDbParameter("@Name", "%" & text1.text & "%")) Number 3: You can leave the use of the wildcards up to the end user. To do this, you would not include wildcards anywhere in these two statements: sql="Select * from TableName where Name Like @Name" Then, in the 'Add Parameter' portion: cmd.Parameters.Add(New SQLParameter("@Name", Text1.text)) (Again, here, changed the managed provider to OleDbParametner as necessary.) By doing it this way, you'd need to put extra instructions in your web form so the end user would know how to do it. When the end user typed their criteria into the textbox, he/she would need to enter wildcards according to his or her own particular needs. If searching the names for 'Smith', they would enter '%Smith' or '%Smith%'. Well, that's basically the run-down of the major points of using the 'Like' operator and how to use wildcards effectively in ASP.Net

21

Beginner's Guide to Master Pages


All of us have struggled over the years to get a consistent look and feel for our web pages. There have been many ways, but now, with ASP.Net 2.0, Master Pages have created a very simple way for this to happen. To begin with, there's a new page extension (.Master). So, the first thing to do is to create a new Master page, with the .Master extension, and lay it out any way you'd like. At the top of that page, there's a Master Directive, much like the Page Directive (and others) you're already familiar with:
<%@ Master Language="VB" %>

The basic concept is, that you will then create Content pages, which in the Page Directive, will refer to the master page:

<%@ Page Language="VB" MasterPageFile="Main.master" Title="My Content Page" %>

Within each master page, you can have one or more ContentPlaceHolders (a new ASP.Net control):
<asp:contentplaceholder id="cph1" runat="server"> </asp:contentplaceholder>

Then, in the Content Pages, there are new Content controls, which refer back to the ContentPlaceHolder's ID in the Master Page:

<asp:Content ID="first" ContentPlaceHolderID="cph1" Runat="Server"> Here's where you put the actual content </asp:Content>

The Content Pages use the normal '.aspx' extension. One of the really cool features, is that, you can, from the Content pages, refer to any control on/in the Master Page, and change the properties of it. Let's say you have an ASP.Net Image Control in the top left corner of the Master Page, and you want to change it in your Content page. Just create your image control, using whatever properties you'd like to assign:
<asp:Image id="imMain" Runat="server" />

Then, inside the Page_Load event of your Content page, your code would look something like this:
Dim Img As Image = Master.FindControl("ImMain") Img.ImageUrl="page2.gif"

You can do this with any DotNet control you put on the Master Page. Let's say you also have a label control at the bottom of your Master page, for the footer, called 'lblFooter'. You want it to always say the same on every page, at least. But then, on one or more of your Content pages, you need to add something. So - in the Content Page's Page_Load event:
Dim lbl as Label=Master.findControl("lblFooter") lbl.Text=lbl.Text & " Special Content - Copyright by the Author - Harold Magnolia"

This will keep the same footer that you have on every other page, and also add the extra text (on a second line) above. To see these basic concepts in action Click Here. Code for the Master Page: 22

<%@ Master Language="VB" %> <html> <head> <title> Master Page </title> <style type="text/css"> <!-BODY { font-family: Arial; font-size: ; } .fullBorder { border-left: thin solid #000000; border-right: thin solid #000000; border-top: thin solid #000000; border-bottom: thin solid #000000; } --> </style> <body> <form id="form1" Runat="server"> <table width="100%"> <tr> <td align="Left" valign="Top" <table class="fullBorder" <tr> align="Center" valign="Top"> <asp:Image id="imMain" Runat="server" /> align="Left" valign="Middle"> align="Left"> <font Size="5" color="#0000FF"><i> <b>My Company Logo</b></i> </font> </tr> </table> </td> </td> <td <div <td

</head>

width="100%"> width="100%">

</div>

</td> </tr> <tr>

<td align="Center" valign="Top"> <div> <a href="./content_First.aspx">Page 1</a> | <a href="./Content_Second.aspx">Page 2</a> | <a href="./content_third.aspx">Page 3</a> <hr> <asp:contentplaceholder id="cph1" runat="server">

23

</asp:contentplaceholder> </tr> <tr> </td>

</div>

ID="lblFooter" My Company All Rights Reserved"

<td align="Center" valign="Top"> <hr> <font Size="2"> <asp:Label Text="Copyright 2006 </font> Runat="server" />

</form> </html> </body>

</tr> </table>

</td>

Code for the Second Content Page:


<%@ Page Language="VB" MasterPageFile="Main.master" Title="Second Content Page" %> <script language="VB" Runat="server"> Sub Page_Load(Source as Object, E as EventArgs) Dim lbl as Label=Master.findControl("lblFooter") lbl.Text=lbl.Text & " _ <br>Special Included Copyright by the Author - Harold Magnolia" Dim Img As Image = Master.FindControl("ImMain") Img.ImageUrl="page2.gif" End Sub </script> <asp:Content ID="first" ContentPlaceHolderID="cph1" Runat="Server"> Content on Second Page </asp:Content>

24

Function Libraries
An Alternative to Includes Remember the old days of Classic ASP, when you could have one file, included on each page, which housed all your common functions? Well, it's still possible today. But, instead of having an 'Include' file, today, in ASP.Net, you can create a Function Library, all in one file. Yes, includes are still possible in ASP.Net, in fact, simple, headers and footers are still a good a very clean and efficient way, in my opinion, to handle these. But, when it comes to common functions, referencing a Function Library on each page is the way to go. Let's start out by creating a clean, new file (save with .cs or .vb). Since this is a VB.Net example, we'll call it 'LIB.vb'. First, let's Import a few namespaces (you'll want to import whichever ones fit your needs). In our case, we'll need these :
Imports Imports Imports Imports System.Data System.Data.SqlClient System.Web.UI System.Web.UI.WebControls

Then, let's create our own Namespace, called 'ASPNet101:


NameSpace ASPNet101 End Namespace

Inside that new namespace, on that page, we'll create a new Class:
Public Class LB End Class

Now, let's create several variables, inside that class that we'll need to use:
Public Shared strConn as string = "server=YourServer;uid=YourUID;pwd=YourPWD;database=Your_DB" Public Shared MyConn as New SQLConnection(strConn) Public Shared MySQL as String Public Shared objDR as SqlDataReader

Now, since this a common function repository, we'll include one function, to start out with, called 'FillListBox', and we'll give it several arguments (Listbox, TblName, TblField, and TblID:

Public Shared Function FillListBox(LBName as ListBox, TblName as String, TblField as String, TblID as String) MySQL = "Select " & TblField & ", " & TblID & " from " & TblName MyConn.Open() Dim Cmd as New SQLCommand(MySQL, MyConn) objDR=Cmd.ExecuteReader(system.data.CommandBehavior.CloseConnection) lbName.DataSource = objDR lbName.DataTextField=TblField lbName.DataValueField=TblID lbName.DataBind() MyConn.Close() End Function

Click here, to see everything we have so far.


Imports Imports Imports Imports System.Data System.Data.SqlClient System.Web.UI System.Web.UI.WebControls

25

NameSpace ASPNet101 Public Shared strConn as string = "server=YourServer;uid=YourUID;pwd=YourPWD;database=Your_DB" Public Shared MyConn as New SQLConnection(strConn) Public Shared MySQL as String Public Shared objDR as SqlDataReader Public Shared Function FillListBox(LBName as ListBox, TblName as String, TblField as String, TblID as String) MySQL = "Select " & TblField & ", " & TblID & " from " & TblName MyConn.Open() Dim Cmd as New SQLCommand(MySQL, MyConn) objDR=Cmd.ExecuteReader(system.data.CommandBehavior.CloseConnection) lbName.DataSource = objDR lbName.DataTextField=TblField lbName.DataValueField=TblID lbName.DataBind() MyConn.Close() End Function End Class End Namespace

Now, you're probably asking, "But, how do I use it in my web page?" That's no problem. In fact, that's all that's left to do in this tutorial. First, at the top of the page, let's reference the '.vb' file we just created:
<%@ Import Namespace="ASPNet101" %> <%@ Assembly src="LIB.vb" %>

Let's create a Listbox on the page first, called 'Listbox1'. Then, in the code section, we'll reference populate the listbox with the Category Names from the Categories Table in the Northwind Database, using the code in the .vb file:
<script language="VB" Runat="server"> Sub Page_Load(Source as Object, E as EventArgs) if not Page.IsPostBack then LB.FillListBox(listbox1,"Categories","CategoryName", "CategoryID") end if End Sub </script>

Notice, that we used 'LB.', in front of the Function, referencing the specific class that contains the function. That's all there is to it. You can add as many Functions or Subs as you'd like. Also, if you would like to 'deparmentalize' your Functions and Subs, you can create multiple classes, inside the namespace, using the appropriate class name, ahead of the function name. Here, hopefully, breaking each part of the concept down into parts will help you more easily understand a very core concept of ASP.Net - The Common Function Library.

26

Sending Multiple Emails At Once


(Mass Emailing - kind of) Just like setting up emailing from a form, in general, is not difficult, neither is sending emails to multiple people at the same time. First, we need to dimension a variable called 'MyVar': to hold all the email addresses in a string: Dim MyVar as String In inline coding, this would be placed inside the script tag, but outside any Sub or Function. Next we need to set up the BCC field, grabbing all the emails from a database field called (surprise!) 'email':
Dim MySQL as string = "Select email from yourTableName" Dim MyConn As SqlConnection = New SqlConnection(ConfigurationSettings.AppSettings("UrAppString")) Dim objDR as SQLDataReader Dim Cmd as New SQLCommand(MySQL, MyConn) MyConn.Open() objDR=Cmd.ExecuteReader(system.data.CommandBehavior.CloseConnection) MyVar="" While objDR.Read() MyVar+=objDR("email")& ";" End While MyVar=MyVar.substring(0,(MyVar.Length-1))

The last line merely removes the semi-colon from the end that will naturally be placed there due to the line inside the While section. You might want to check out another Tutorial here, called 'Emailing Form Results'. It goes over much of this next section also.
Dim objEmail as New MailMessage objEmail.To="News@YourDomain.com" objEmail.FROM="You@YourDomain.com" objEmail.BCC=MyVar objEmail.SUBJECT="This is my Subject" objEmail.Body="Put text or a variable which represents the text - here" objEmail.BodyFormat = MailFormat.Text SmtpMail.SmtpServer ="mail.YourDomain.com" SmtpMail.Send(objEmail)

The main sections that needs addressing here are the BCC field, the BODY field, and the TO field. For most, the TO field will be fairly trivial. You don't need any of the people in the email addresses for this one. I usually use a mail back to me, in order to be sure the email actually went out. In the BCC field, you see that the list of emails in the 'MyVar' variable goes here, without double quotes surrounding it, since it's a variable and not an explicit email address. The same goes for the BODY section. If you wanted to define a section of text, and assign it to a variable, before this block of code, then, you would merely put the variable name there, without double quotes. Naturally, the SMTP server is important, since that's the mail server which you assign to send the emails out. Hopefully, this takes a little mystery out of the whole 'sending multiple emails at the same time' scenario.

27

Part 2 examines how to accomplish this, sending a single email to each recipient, allowing both personalization and customization in each email.

Sending Mass Emails Part 2


(Sending Separate Emails to each Recipient) If you haven't read Part 1 in this series, you can do so now, by clicking here: Sending Multiple Emails At Once One of the major drawbacks of creating a mass emailing like we did in Part 1, was personalization and customization were practically non-existent. All email addresses were kept in a string, which populated the BCC section. Each recipient could easily see that this was a mass email. Naturally, that's normally OK, but by being able to personalize an email gives the recipient a better feeling when he things that the 'Sender' of the email took the time to send the email to him, personally. By building your mass email this way, practically any level of personalization and customization is all up to you. For instance, you could create a link in the email itself, that, when clicked, can run a script on your web site to delete that user from the email list automatically. For this example, all you'll really need is: 1. Import the System.Web.Mail namespace 2. Import the Database namespaces necessary 3. A table of Data, in the Database (for this sample, we only have two fields (Name and Email) 4. One subroutine for the code (for this example, we'll use Page_Load) 5. A label with an ID of 'lblEmails' (only to show the list of emails for the test) First, we'll Import the namespaces. For emailing, we must add:
<%@ Import Namespace="System.Web.Mail" %>

For the database (we're using SQL Server for this tutorial), we must add:
<%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SQLClient" %> Dim sEmail as String Dim sBody as String

Now, for the real 'meat' of this tutorial, first, we'll add two Global variables: Next, in a Subroutine of your choice, add this code:

Dim objEmail as New MailMessage sBody = "This is our test email to you" objEmail.Subject="This is my Subject" Dim MySQL as string = "Select Name, email from TestMail" Dim MyConn As SqlConnection = New SqlConnection(ConfigurationSettings.AppSettings("YourConfigSettings")) Dim objDR as SQLDataReader Dim Cmd as New SQLCommand(MySQL, MyConn) MyConn.Open() objDR=Cmd.ExecuteReader(system.data.CommandBehavior.CloseConnection) While objDR.Read() sEmail = objDR("email") objEmail.To =sEmail objEmail.FROM="fromYou@YourDomain.com" objEmail.Body=sBody & vbcrlf & "Name: " & objDR("Name") & vbcrlf & "Email: " & sEmail

28

objEmail.BodyFormat = MailFormat.Text SmtpMail.SmtpServer ="mail.YourDomain.com" SmtpMail.Send(objEmail) lblEmails.text+=sEmail & "<br>" End While MyConn.Close

Here, in the While/End While loop, we do all the real work. We iterate through each record of the table, sending a separate email, personalized, to each email address in the table. For the sake of this tutorial, we're also adding each email address to a label to show how many emails were sent, and to whom. Naturally, this is not a necessary step - it's there only for visualizing what actually has happened. Remarkably, this is all you really need to get started. The customization and/or personalization is up to you!

29

Beginners Guide to Forms Authentication


There are four basic parts to simple forms authentication. Those parts are: 1. 2. 3. 4. The form (to gather user ID & pwd) itself The Web.Config File entry The Data Store (the place where you keep the usernames and passwords The Validation Process, triggered in the click event of the form.

Here is an example of the simplest of Forms (let's call the page 'Login.aspx'), designed to gather the user ID and password:
<table> <tr> <td align="Right" valign="Top"><b>User ID: </b></td> <td align="Left" valign="Top"> <asp:TextBox id="txtUID" Runat="server" /> </td> <td align="Right" valign="Top"><b>Password: </b></td> <td align="Left" valign="Top"> <asp:TextBox id="txtPWD" TextMode="Password" Runat="server" /> </td> <td align="Right" valign="Top" Colspan="2"> <asp:Button id="submitButton" Text="Login" onclick="doLogin" Runat="server" /> </td> </tr> </table>

</tr> <tr>

</tr> <tr>

In the Web.Config file, add this:


<authentication mode="Forms"> <forms name=".FormName" loginUrl="login.aspx" ' remember how we named the page for the form? protection="All" timeout="480" path="/" /> </authentication> <authorization> <deny users ="?" /> </authorization>

For the DataStore - you can use anything you'd like - however, I'm a bit partial to databases for quick interaction, so this example will be using a database. You'll need to create a table in

30

your database to store your names, User ID and Passwords. Here's a list of the basic table fields you'll need: Field DataType Notes<> Name id Integer (for Access, use AutoNumber; for SQL Server, create Identity) Name MS Access: Text; SQL Server: use a length you feel is appropriate VarChar - you can also make this two fields (First and Last names) to be able to more easily use their first name other places on the site, once they're logged in Login MS Access: Text; SQL Server: Varchar, unless you want an exact number of characters. Password (same as above)

For the actual work to do this, create a click event for the button in the form. Let's call it 'doLogin'. Also, you'll create a Function to do the validation - - let's call it 'ValidateUser', with a couple of arguments, 'uid' and 'pwd'. Also, create a label with an ID of 'lblError', just in case the login attempt fails.
Function ValidateUser(uid As string, pwd As string) As Boolean Dim sFirst,sName as string Dim strConn as string = " server=UrSrvr;uid=UrUid;pwd=UrPwd;database=UrDB" Dim MySQL as string = "Select [Name], [Login], " & _ "[Password] from Employees " & _ "Where Login=@uid AND Password=@Pwd" Dim MyConn as New SQLConnection(strConn) Dim objDR as SQLDataReader Dim Cmd as New SQLCommand(MySQL, MyConn) cmd.Parameters.Add(New SQLParameter("@Uid", uid)) cmd.Parameters.Add(New SQLParameter("@Pwd", pwd)) MyConn.Open() Try objDR=Cmd.ExecuteReader(system.data.CommandBehavior.CloseConnection) While objDR.Read() sUser=objDR("login") sPwd=objDR("Password") sName=objDR("Name") End While Dim sText as String if sFirst = "" and sLast="" then blnValidUser="False" else blnValidUser="True" session("Name")=sName End If Catch ex as Exception lblError.visible="true" lblError.text="Sorry Errors have occurred" Finally ValidateUser = blnValidUser MyConn.Close()

31

End Try End Function

In the "doLogin" sub, you'd create it like this:

Sub doLogin(Source as Object, E as EventArgs) If ValidateUser(txtUID.text,txtPWD.text) =True Then FormsAuthentication.RedirectFromLoginPage(txtUID.text, False) Else lblError.Visible="True" lblError.text="We're sorry, but the information you provided " & _ "does not match our database. Please try again." label1.text="" End If End Sub

As you can see, using the 'ValidateUser' function, the user ID and password are verified against the database. If it matches, it also retrieves the Name of the user and assigns it to a Session to use anywhere in the site you'd like, along with assigning the True or False of the login attempt to the blnValidUser boolean variable, which, in turn is assigned to the output of the ValidateUser Function. From here, the user is authenticated for any portion of the site, for the length of the session. Naturally, it this process can be further expanded, for roles and separating out sections of the site for roles or certain people logged in, but we'll attack that at a later date. I'm sure, that, if you're a novice, this may seem pretty complicated, but in the total realm of the programming world, this is fairly simple. MS has done a pretty nice job here, in my opinion. Just remember, the simplest way to attack a seemably difficult piece of code, is to break it into parts, the way it's done here. Study each part, piece by piece, and then see how they all fit together.

32

Using MySQL in ASP.Net


(It's Easier than you think) Many people have asked me for this tutorial, so here goes. For those of you who don't know, MySQL is an open-source DataBase server. Being that it's open-source, it's also free. That's about as low-cost as you can get. Of course, you may ask 'Why use MySQL'? Did you read the previous sentences?? It's free, as well as being a fairly robust database server! To be able to use MySQL, there are a couple of downloads that must be done: 1. MySQL Itself 2. MySQL ODBC Driver The Database Server (MySQL), itself can be downloaded here: http://dev.mysql.com/downloads/mysql/4.0.html The Driver (for Windows) can be downloaded here: http://dev.mysql.com/downloads/connector/odbc/3.51.html The biggest hurdle in using MySQL, is the setup - much like many other users of MSDE have found out. Without a user interface, it's quite cumbersome, requiring a command prompt to do all the work. Here's the best page I've found so far to take you, step-by-step through this process: http://www.analysisandsolutions.com/code/mybasic.htm#installation Now, once this is all set up - guess what - you have no data. If you want, the above installation page will also help you get started creating databases, tables and fields for your sample data. But, if you want a much quicker way to populate your database server, so you can get started, AugustWind Software has user interface for MySQL called Data Management Toolkit. Check it out here Now - the part you actually came here for - - the easy part! On other parts of this site, you've seen many samples, using MS Access and SQL Server. As you might have noticed, there are only three major differences in using these. 1. Namespaces used 2. Connection String 3. Prefix to data classes (like: OleDbDataAdapter vs. SQLDataAdapter, specific to the Imported Namespaces For MySQL, the driver which you downloaded (above), is an ODBC Driver, therefore, numbers 1 and two in the above list use 'ODBC':
<%@ Import Namespace="System.Data.ODBC" %>

And, you use classes like ODBCDataAdapter, ODBCDataReader, ODBCCommand, etc.

33

To finish out the three items in the above list, here, we show you the Connection String needed:
"Driver={MySQL ODBC 3.51 Driver};uid=YourUID;password=YourPWD;Server=YourServerIP;Option=16834;Datab ase=YourDB;" or, you can use: "DRIVER={MySQL};SERVER=ServerIP; DATABASE=YourDB;USER=YourUID;PASSWORD=YourPWD; OPTION=3;"

Just change these few things, in your code, and you're off and running, using MySQL in your own ASP.Net documents! Now, do you believe me, when I say that using MySQL in your ASP.Net documents is the easy part? In fact, if you have a hosted web site, chances are, most of the setup can be done by someone else and all you will need to do is the pages themselves! Now, you can't put off using MySQL, for lack of knowledge!

34

Matching Regular Expressions


(in Code) There may come a time when you want to match a Regular Expression against a string and you don't necessarily want or need to use one of the built in ASP.Net Regular Expression Validators. For instance, using a validator, if the match doesn't occur, you are not allowed to submit your form data. But, let's say, you want to validate the data, but you don't really mind if the data is a match or not and you merely want to send the user a message that the data didn't match the correct format. Using the System.Text.RegularExpressions Namespace (don't forget to import it!), you can accomplish this in code. Note the following function:
Function RegExMatch(sItem as String, sRegEx as String) as Boolean Dim r As Regex = New Regex(sRegEx) Dim m As Match = r.Match(sItem) Return m.Success End Function

Here, we're taking the first argument in the function (sItem) and matching it against the Regular Expression, which is in the second argument. Since the Function returns a boolean, naturally, the only two possibilites are TRUE or FALSE. So, to implement this in code, let's create a scenario where you are entering parts into your online system. For the partnumber itself, you use the format: ####.## - where all characters must be numeric. The Regular Expression for this would be: ^[1-9][0-9][0-9][0-9]\.[0-9][0-9] So, in your code, you can do something like this:
if RegExMatch(txtPartNum.text, "^[1-9][0-9][0-9][0-9]\.[0-9][0-9]") ="False" then lblError.Text+="Part # must be in ####.## format" 'do other processing Else 'do whatever processing you need here End If

That's all there is to it. As you can see, with ASP.Net, it using validation with Regular Expressions is much simpler than it sounds. The hardest part is learning Regular Expressions. If you'd like to delve a little deeper, and start learning AND understanding Regular Expressions, take a look at this tutorial:

35

Defining Error Displays Globally


(for Site-Wide Consistency) If you have many pages on a site, you may fall into a very easy situation. That situation is that, in each Try/Catch block that you've defined on on each page, you may have a different method of displaying in each section on each page. This is where the need for consistency comes in. Of course, in a perfect world, you would have programmed it so well, that there would be no errors. But we know that's not always going to happen. So, using the ASP.Net Try/Catch blocks, we try to encapsulate the errors and display them in a consistent manner. However, in each 'Catch' section, we are free, as programmers, to trap and display the error messages any way we want. In this tutorial, we will attempt to show how to add a little more 'global consistency' to your pages in this area. First, in a class in your .VB file (can be used with Inline coding also), we'll create a Global variable called 'sErrorMsg':
Public sErrorMsg as String

Second, we'll create a function called 'ShowErrors'. At first glance, you will probably think that it's really a simple function. But as you know, sometimes the greatest problems are solved with the greatest simplicity.
Function ShowErrors(sProc, sMsg) as String sErrorMsg= "An error has occurred (Proc: " & sProc & ")<br>" & sMsg Return sErrorMsg End Function

If you're using the Inline Coding method, if you have an existing .VB file you're using, just include the function in your that page, or just create a new .VB file and create a new class inside that page. Then, add the function inside that class:
Public Class Basics Inherits System.Web.UI.Page Public sErrorMsg as String 'Put your Function here End Class

In the Page Directive of your .ASPX page, just add:


Inherits="Basics" src="PageName.vb"

In this function, we take the two strings as input from the page (as we'll see below), as arguments in the function, and create another string, and assign it's contents to the 'sErrorMsg' variable we created before. The first of the arguments will be defined on the page itself (the Procedure/Sub/Function being used in code). The second argument will also be defined, but not by you. In another Tutorial on this site, you learned about the Try/Catch block, for error trapping and display. In this tutorial, you learned that we could define the error(s) and display in the 'Catch' section, like this:
Catch ex as Exception

There are different ways this can be utilized, but for the sake of simplicity, in this tutorial, we're using that method. Now, of course, somewhere on the page, you need to have a label, in order to display the error messages. The name and location on the page are choices for you, but, again, for consistency's sake, let's call the label, 'lblError'. Inside the Catch section, you now only need one line: 36

lblErrors.text=ShowErrors("ProcedureName", ex.Message)

Above, you'll just need to change 'ProcedureName' to the Sub or Function name where your Try/Catch block is trapping errors. You could customize this, of course, any way you'd like. Add this line to every Catch section on each page on your site to add a global look and feel to your error messages. Here, as you see, we've shown you a simple, yet powerful way to get started with a consistent look and feel for Error Trapping and the Display of the Errors. From here, customize it to your heart's content!

37

Creating a FeedBack Form


(using SQL Server or MS Access) It's rather simple in ASP.Net to create a generic FeedBack form. You can make it as simple or as complicated as you need. The simplest form would be merely a Form-To-Email version, which would ONLY send an email of the feedback to a specific destination. In many cases, this would for many users. However, most often, the reality is that sometimes emails get lost. Therefore, it would be more preferable to enter the data from the form, and then, also send the results by email. This way, if the email gets lost, there is still a record of the FeedBack. There are a couple of things to consider when starting the design process. They are: 1. Which database are you going to use? 2. How many pieces of Information are you needing to capture? 3. How do you want to interact with the data, once it's in the database? You can use any you want in this scenario, of course, but we're only covering SQL Server and MS Access. It really doesn't matter, in the long run. For most ANSII sql compliant databases, everything is going to be the same, except for the methods used to talk back and forth to the databases. We also will only cover the basic fields needed in the form, but you can make the form as simple or complex as needed for your own purposes, as stated before. Just remember - for every field you have in the form, you should have a corresponding field in the database table which will be capturing the end-user's input. The fields we'll be covering here are: 1. 2. 3. 4. 5. Title Email Address (the address of the person entering the feedback,for follow-up) Feedback (multi-line textbox, sized as needed) Time Entered (automatic) Follow-up

You will need to create a database table with these fields - start with an ID field (autonumbering in MS Access or Identity in SQL Server - set as Primary Key also). Then, create the other fields however you'd like, size-wise, making the Time Entered field a Date/Time field and in our case, we'll make the Follow-up field very small so that a 'Yes' can be entered when follow-up is finished concerning the feedback. If you'd like, you can add an extra field for follow-up notes. Here is how the Form will look on the page:
Title: <asp:TextBox id="txtTitle" Runat="server" /><br> Email Address: <asp:TextBox id="txtEmail" Runat="server" /><br> Feedback:<br> <asp:TextBox id="txtFeedback" Rows="4" Width="500" TextMode="MultiLine" Runat="server" /><p> <asp:Button id="btnSubmit" Text="Submit" onclick="doInsert" Runat="server" />

38

As you probably noticed, the last two items in the list (Time Entered and Follow-Up) above are not included in the visual code for the feedback form. That's because we will automatically get the system date and time and enter it into the database when the data is inserted, and the Follow-Up field is not for input, but obviously, as the name implies, for 'follow-up' - AFTER the data has been captured from the form. Now, next, we'll need an input sub that takes care of gathering the data entered into the form. Here is the code for doing just that:
Sub doInsert(Source as Object, E as EventArgs) Dim strConn as String = "server=YourServer;uid=sa;pwd=YourPWD;database=YourDB;" Dim MySQL as string = "Insert into feedback (Title, Email, Feedback, dtEntered, Followup) " & _ "Values (@Title, @Email, @Feedback, @dtEntered)" Dim MyConn as New SQLConnection(strConn) Dim Cmd as New SQLCommand(MySQL, MyConn) With Cmd.Parameters .Add(New SQLParameter("@Title", frmTitle.text)) .Add(New SQLParameter("@Title", frmEmail.text)) .Add(New SQLParameter("@Feedback", frmFeedback.text)) .Add(New SQLParameter("@dtEntered", DateTime.Now())) End With MyConn.Open() cmd.ExecuteNonQuery() 'Put your Success statement Here 'Create a label on the page and assign the success statement to the label's text value, like: 'Label1.Text="Your inormation has been successfully received. " & _ "We will get back to you as soon as possible" 'Remember to Import the SQLClient Namespace also MyConn.Close End Sub

For MS Access, your code would be:

Sub doInsert(Source as Object, E as EventArgs) Dim strConn as String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & _ "server.mappath("\pathAndNameToYourDB.mdb") & ";" Dim MySQL as string = "Insert into feedback (Title, Email, Feedback, dtEntered, Followup) " & _ "Values (@Title, @Email, @Feedback, @dtEntered)" Dim MyConn as New OleDbConnection(strConn) Dim Cmd as New OleDbCommand(MySQL, MyConn) With Cmd.Parameters .Add(New OleDbParameter("@Title", frmTitle.text)) .Add(New OleDbParameter("@Title", frmEmail.text)) .Add(New OleDbParameter("@Feedback", frmFeedback.text)) .Add(New OleDbParameter("@dtEntered", DateTime.Now())) End With MyConn.Open() cmd.ExecuteNonQuery() 'Put your Success statement Here 'Create a label on the page and assign the success statement to the label's text value, like: 'Label1.Text="Your inormation has been successfully received." & _ "We will get back to you as soon as possible" 'Remember to Import the OleDb Namespace also MyConn.Close End Sub

39

The final piece of this will be to setup a SubRoutine for emailing the form results to yourself (or a designated email address). Here, we'll just use a text based (instead of HTML) email, for simplicity's sake. First we'll create a string variable and assign the results of the feedback form to it:
Dim sMsg as String sMsg= "Feedback has been sent to you." & vbcrlf & "The results are as follows:" & vbcrlf sMsg+="Title : " & frmTitle.text & vbcrlf sMsg+="Email : " & frmEmail.text & vbcrlf sMsg+="Feedback : " & frmFeedback.text & vbcrlf sMsg+="Time Entered : " & DateTime.Now()

The rest is fairly simple, as outlined in a previous Tutorial entitled Emailing Form Results. Here's the whole subroutine:
Sub doEmail() Dim sMsg as String Dim sBody as String sMsg= "Feedback has been sent to you." & vbcrlf & "The results are as follows:" & vbcrlf sMsg+="Title : " & frmTitle.text & vbcrlf sMsg+="Email : " & frmEmail.text & vbcrlf sMsg+="Feedback : " & frmFeedback.text & vbcrlf sMsg+="Time Entered : " & DateTime.Now() Dim objEmail as New MailMessage objEmail.To=YourEmail@wherever.com objEmail.FROM=frmEmail.text objEmail.SUBJECT="You have Feedback" objEmail.BODY=sMsg objEmail.BodyFormat = MailFormat.Text SmtpMail.SmtpServer ="mail.Wherever.com" SmtpMail.Send(objEmail) End Sub

Lastly, just put a line inside the 'doInsert' sub, at the very end, in order to send the email, once it's entered into the database:
doEmail()

As you can see, it's fairly straightforward to create a Feedback form in ASP.Net. Your last step is only to customize it anyway in which you'd like for your own purposes.

40

Examining New String Properties - Part 1


(and thereabouts) There were many functions we used to parse strings in Classic ASP, like Mid, Right, Left, Instr and Len. But now there are new items - properties assigned to the strings, like Substring, IndexOf, EndsWith, and StartsWith. Before, we had mid and right. Now we have 'SubString'. In Classic ASP, to parse just a bit of a string, from a certain position in the string, we would use :
Dim sItem sItem="This is my String" Mid(sItem,5)

This would start 5 characters into the string, and give you what was left. The new way to do it is with the SubString Property. Here's how you use it for the same function:
Dim sItem as String sItem="This is my String" sItem.SubString(5)

What you would end up with is 'is my String'. One other variation of the SubString property will allow you to start at a certain character (from the left) of the string, and parse the string by a certain number of characters past that starting point. In other words, you could do this:
Dim sItem as String sItem="This is my String" sItem.SubString(5, 8)

The text you would end up with would be 'is my st'. It started at the 5th character in from the left of the string (just before the word 'is') and proceded to crop/parse the text for another 8 characters. We also previously had the instr function, which, by using it, could find the position in the string of another string. For instance, if the string was "Where is the big black dog?" and we wanted to find the position (in that string) of the word "the", we would use the instr function. To do this, the cleanest way possible, we'd assign the entire string to a variable (let's call it 'sItem'), then, the code would look something like this (including the use of the position, after finding it):
Dim lg lg=instr(1, sItem, "the") response.Write (lg)

Then, of course, we could response.Write lg or use lg in any way we wanted, from there. Now, we have the indexof property. It's a little simpler - a little cleaner. Let's use the same string (sItem): Response.write (sItem.IndexOf("the")) Another variation of this would be more like the original instr function, it finds the position of a particular string, based on a starting location in that string. Response.write (sItem.IndexOf("the", 5))

41

This would actually look for the position of the word 'the', but it would start looking at the 5th character position. There are two new items we'll look at now. They are 'EndsWith' and 'StartsWith'. I'll only go into the explanation of 'EndsWith', because after that, 'StartsWith' will be self explanatory. The return value is a boolean in this case, and not a numeric position in the string. Let's say sItem, in this case, is 'We're really having fun now!". What these two properties do is check for certain strings or characters and, if the string ends with or starts with that character or string, the return is 'True'. Otherwise, of course, the return is 'False'. Here's how you would use it: Response.Write (sItem.EndsWith("!")) Naturally, in this case, it would return 'True'. One last thing we need to look at in this tutorial is the replacement for 'Len'. In Classic ASP, we'd write: response.Write (len(sItem)) In ASP.Net, it's a little different - as before, each string is an 'object'. Therefore, you assign the length property to it: response.Write (sItem.Length) There are many more properties in the String Class, but this at least gets you up to speed on a few of them. We'll examine others in "Examining New String Properties - Part 2"

Examining New String Properties - Part 2


(and thereabouts) In this tutorial, we'll visit one new method (Compare), and new ways older methods are treated in ASP.Net (Trim, Replace and Split). If you haven't done so already, please also read "Examining New String Properties - Part 1" The Compare property is a pretty neat addition to ASP.Net and works in a a couple of different ways. In each case, lets go with the fact that sFirstItem is "Chevy" and sSecondItem is "Ford". Here's the basic format in which you would see it used: String.Compare(sFirstItem, sSecondItem) This, of course, shows you the format using variables, which is more like what will be encountered in day to day programming. You could use exact strings also, with double-quotes around each item. However, since they are exact strings, In the Classic ASP days, we'd need to attack it something like this:
if sFirstItem=sSecondItem then response.Write ("It's a Match") else response.Write ("It's Not a Match") End If

It's not really more compact in ASP.Net, but here's the way it's utilized:
if String.Compare(sFirstItem, sSecondItem) =0 then response.Write ("It's a Match") else response.Write ("It's Not a Match") End If

42

By default - this compare method is NOT case-sensitive. However, you have the option to 'turn-on' case-sensitivity, if the requirements dictate such. To do so, you would add a third argument "True" to the comparison. The format of the first line would then be:
if String.Compare(sFirstItem, sSecondItem, True) =0 then

As before, the Trim function is still available. For those who don't know about it, let's say, when someone enters their password, they inadvertently typed in a space either before, or at the end of the password. Therefore, when the login occurred, technically, the password would not match, since the original password did not have the space in it. To get around this in Classic ASP, you would use the Trim Function like this: Response.Write (Trim(sPassword)) In ASP.Net, the format is : response.Write (sPassword.Trim()) This would take what was originally typed in as " ThisisMyPassword " and make it "ThisisMyPassword" Along with the Trim function, there is TrimStart and TrimEnd, which specifically trim from the - you guessed it - start and end of the string. Each of the Trim functions also accept a character array as a parameter in order to remove characters other than basic white space from the strings. Also, in Classic ASP days, we had the Replace Function. It's still here in ASP.Net, but with a different formatting, as usual. Instead of using: sItem = Replace(sItem, "CharacterToBeReplaced", "ReplacementCharacter") We now use: sItem = sItem.Replace("CharacterToBeReplaced", "ReplacementCharacter") Along with the Replace Function, there is now, also an Insert Function: sItem = sItem.Insert(10, "Wow - this is really cool!") Here, we insert the string "Wow - this is really cool!", 10 characters into the string. Again, as before, we had, and still have the Split function, but now it's formatted a little differently. The Split function takes a string and 'splits' the string into sections, at certain intervals, based on a common separator between those characters, and puts the sections into an array. As a default, it defaults at any white space being the separator. So, if you had a string that was separated by a space or tab, etc, and just use : arrNewSplit = sString.Split() If it was a comma-delimited string, you would use: arrNewSplit = sString.Split(",") This pretty well wraps up what these tutorials are going to cover. By no means is this all ASP.Net does with strings, but what has been mentioned in the last two tutorials is, what we believe are some of the most common useages and the most helpful points of the String Class.

43

Adding 'Last Updated' To Footer


(Last Updated Date/Time) In the 'old' Classic ASP days, we could use the FileSystemObject, in an include file, to automatically display a 'Last Modified' section. This possibility has not gone away, with the advent of ASP.Net. In fact, using the System.IO namespace, there are a couple of ways to do it. You'll probably recognize this Classic ASP code, using the FileSystemObject:
<% Dim oFS Dim sPath Dim oFile Set oFS = Server.CreateObject("Scripting.FileSystemObject") sPath = Request.ServerVariables("Path_Translated") Set oFile = oFS.GetFile(sPath) response.write "Last Updated " & oFile.DateLastModified & _ " 2004 YourCompanyName - All rights reserved" Set oFile = Nothing Set oFS = Nothing

%>

Now, we merely import the System.IO namespace, add a label to the page and we change it to this:
Dim sPath as String = Request.ServerVariables("Path_Translated") Dim dt As DateTime = File.GetLastWriteTime(sPath ) lblBottom.Text= "Last Updated " & dt.ToString & _ " / 2004 YourCompanyOrWebSiteName / All rights reserved"

There are a couple of ways you can do this, also. One way is to create a Footer User Control. As you probably know, User Controls are new wtih ASP.net. I won't go into an explanation of User Controls here, since another Code Sample on this site shows how to create a simple header or footer User Control. The other way might surprise you. Most people are under the impression that Include Files have simply gone away, with the advent of ASP.Net. However, this is not true. There are some things that won't work in an include file, but in general, it can still be used. With the above sample, all that would be needed is to create a new ASPX file, to use as your footer. In that file, create a script block and Page_Load routine, just as you would with any other ASP.Net page which uses inline coding. You would put any text or formatting you need, however you need it, and then, put a label where you'd want this to appear. Here is a sample:
<%@ Import Namespace="System.IO" %> <script language="VB" Runat="server"> Dim sPath as String Dim dt as DateTime Sub Page_Load(Source as Object, E as EventArgs) sPath = Request.ServerVariables("Path_Translated") dt = File.GetLastWriteTime(sPath ) lblBottom.Text= "Last Updated " & dt.ToString & _ " / 2004 YourCompanyName / All rights reserved" End Sub </script> <div align="center"><Font Size=2>Please, email your questions or comments to :

44

<a href="mailto:questions@yourSite.com?Subject=Questions"> (questions@yourSite.com)</a></Font> <BR> <font Size="1"> <asp:Label ID="lblBottom" Runat="server" /> </font></div>

That's basically it - - as you can see, just like other samples and tutorials on this site, it's much simpler than you might have thought! Happy coding!

45

Creating a Hit Counter


(in ASP.Net, of course) Remember the ASP Classic Hit Counter? You'd create a text file for each page you wanted to record that page's hits. To start with, you'd just type in a zero to begin the counting process. Then, you'd put this code in your ASP document:
Set fs = CreateObject("Scripting.FileSystemObject") CounterPage = Server.MapPath ("/counters/YourASPDoc.cnt") Set a = fs.OpenTextFile(CounterPage) ct = CLng(a.ReadLine) ct = ct + 1 a.Close Set a = fs.CreateTextFile(CounterPage, True) a.WriteLine (ct) a.Close Response.Write ct

Naturally, things are quite different in ASP.Net. But, then again, you will see some of the same stuff. First, you'll want to import the System.IO namespace:
<%@ Import Namespace="System.IO" %>

First, we'll create (Dim) two global variables:

Dim ct as String Dim CounterPage as String = Server.MapPath("/counters/YourASPNetDoc.cnt")

I added the 'cnt' extension here, but this can be a 'txt', or any text file extension. For the actual coding, we'll break this up into two separate subs to make it more easily understandable. First, we'll create the subroutine to open the file, read the contents and add 1 to the amount written in the file:
Sub ReadFile() Dim objStreamReader as StreamReader ' Here, we use the Counter Page created in the global variable.com objStreamReader = File.OpenText(CounterPage) ct = objStreamReader.ReadToEnd() ct=CLng(ct) ct=ct+1 objStreamReader.Close() End Sub

Next, we create the subroutine to write the new data back to the existing file:
Sub WriteFile() Dim objFileWriter as StreamWriter objFileWriter = File.CreateText(CounterPage) objFileWriter.Write(ct.ToString) objFileWriter.Close() End Sub ReadFile() WriteFile()

The only thing left is to actually call the subs. You can do this in the Page_Load routine: Then, if you actually need or want to show this count, visually, on the page, just create a label wherever you'd like and, also, in the Page_Load routine, add this last line:
label1.text = ct

As you can see, this is quite simple, even in ASP.Net!

46

Using the MS IE TabStrip


You've probably heard of Microsoft's IE WebControls. They're a 'group', if you will of controls that are not part of the DotNet Framework, but can be downloaded separately and installed on your computer. If you haven't downloaded them, you can do so here: http://www.asp.net/IEWebControls/Download.aspx?tabindex=0&tabid=1. One thing that won't be self evident for the casual web guy, is that there is a batch file that needs to be run, once the download and subsequent installation is complete. I'ts called 'Build.bat' This creates a dll (Microsoft.Web.UI.WebControls.dll) that you will need to copy from it's newly, installed location (downloadLocation/build/) into your /bin directory (you will need to create it if it isn't already there). Once that's done, you can begin the work of designing your page with the TabStrip Control. In this sample, I contain the data for the separate Tabs inside ASP.Net Panel Controls, using the Visible property of the Panel Control. This is just one way of doing it - not 'THE' way. Also, I'm sure there are more efficient ways to do the visible/invisible thing, but for the sake of purity and 'directness', I did not bother to expand that portion past what you see here. The code is fairly self explanatory, with a few comments along the way, so I'll just leave it at that for now. What it really boils down to is a combination of three things -- The TabStrip (instantiating it on the page and designing it's look and feel), the Content (separating it into sections), and the code for linking the Tabs with the correct sections. Here, this is accomplished with the Sub called 'doChange' The code below shows how to use the Tab Strip. To see an example of this exact code, click here: TabStrip Example And here's the code needed to accomplish what you see in the example:
<%@ Register TagPrefix="aspnet" Namespace="Microsoft.Web.UI.WebControls" Assembly="Microsoft.Web.UI.WebControls" %> <script language="VB" Runat="server"> Sub Page_Load(Source as Object, E as EventArgs) dochange End Sub Sub IndexChange(sender As Object, e As EventArgs) doChange End Sub Sub doChange() Dim i as Integer 'Makes each Panel Visible or Invisible, depdending on which Tab is clicked. 'indexes are 0 based, therefore, the panel names start numbering with 0 for i = 0 to 4 dim pnl as Panel = ctype(FindControl("pnl" & i.tostring), Panel) if mytabstrip.SelectedIndex = i then pnl.Visible="True" else pnl.Visible="False" End If

47

next End Sub </script> <html> <head> <meta name="GENERATOR" Content="ASP Express 3.0"> <title>Using the TabStrip</TITLE> <STYLE TYPE="text/css"> <!-BODY { font-family : Arial, Helvetica, sans-serif; font-size : 11pt; } --> </STYLE> </head> <body> <form id="form1" Runat="server"><p> <b><font Size="5" Color="#9900CC">TabStrip Example (MS IE Webcontrols)</font></b> <table border="0" cellpadding="0" cellspacing="0" width="600"> <tr> <td align="Left" valign="Top"> <aspnet:tabstrip id="mytabstrip" onSelectedIndexChange="IndexChange" runat="server" Width="338px" Height="18px" Font-Size="8pt" AutoPostBack="True" TabSelectedStyle="backgroundcolor:#ffffff;color:#000000;" TabHoverStyle="backgroundcolor:#E0E0E0;color:#000000;" TabDefaultStyle="background-color:#C0C0C0; font-family:verdana; border-style:solid; border-width:1px; border-color:black; font-weight:bold; color:#ffffff; text-align:center;"> <aspnet:Tab Text="Step 1"></aspnet:Tab> <aspnet:Tab Text="Step 2"></aspnet:Tab> <aspnet:Tab Text="Step 3"></aspnet:Tab> <aspnet:Tab Text="Step 4"></aspnet:Tab> <aspnet:Tab Text="Step 5"></aspnet:Tab> </aspnet:tabstrip></td> </tr> <tr> <td align="Left" valign="Top" height="1"></td> </tr> <tr> <td align="Center" valign="Top"> 'Here is where the Panels start, which contain the content for each Tab clicked: <asp:panel ID="pnl0" BorderColor="Red" Height="100"

48

BorderWidth="2" Width="100%" Visible="False" Runat="server"> <div align="center"><b><font Size="4" Color="#FF0000">This is Panel 1 </font></b></div> <i>Make sure the MS Web Controls are properly installed.</i><br> The '<font Color="#0033FF">Microsoft.Web.UI.WebControls.dll</font>' should be in the /BIN directory, in your web server's root. </asp:panel> <asp:panel ID="pnl1" BorderColor="blue" Height="100" BorderWidth="2" Width="100%" Visible="False" Runat="server"> <div align="center"><b><font Size="4" Color="#3300FF">This is Panel 2 </font></b></div> Put this at the top of your page:<br> <font Size="3" Color="#3333FF"> <%@ Register TagPrefix="aspnet" Namespace="Microsoft.Web.UI.WebControls" Assembly="Microsoft.Web.UI.WebControls" %> </font> </asp:panel> <asp:panel ID="pnl2" BorderColor="Green" Height="100" BorderWidth="2" Width="100%" Visible="False" Runat="server"> <div align="center"><b><font Size="4" Color="#009966">This is Panel 3 </font></b></div> Adjust the styles as desired for the tabs/hovering/selecting, etc. </asp:panel> <asp:panel ID="pnl3" BorderColor="Purple" Height="100" BorderWidth="2" Width="100%" Visible="False" Runat="server"> <div align="center"><b><font Size="4" Color="#9966FF">This is Panel 4 </font></b></div> Create a subroutine as an event handler to handle each Tab change,<br> using the 'onselectedindexchange' event, and <br> creating a Select Case statement referencing the Tabstrip's SelectedIndex. </asp:panel> <asp:panel ID="pnl4" BorderColor="Orange" Height="100" BorderWidth="2" Width="100%" Visible="False" Runat="server"> <div align="center"><b><font Size="4" Color="#FF9933">This is Panel 5 </font></b></div> Create separated content for each Tab, inside each Panel, or other container, as desired. </asp:panel> </td> </tr> </table> </form> </body> </html>

49

Adding Dynamic Content to Your Pages


(Data Driven Page Title, Meta Tags and Content)
In a data-driven website, there becomes a need to have only one page serve up different data, based on the call to the database. Naturally, you wouldn't want to have the same Title on the page's drag bar, and you certainly would like to have different Keywords in your meta tag along with every section of content received from the database. This tutorial will attempt to provide a simple example/overview of how to dynamically add, not only the content, but the Title of the page and the Keywords for the HTML Meta Tags in order to get you started in this direction. First we'll start with the database table structure. Keep in mind, I previously said 'a simple way', so, keeping that in mind, here would be four fields needed to do this:

id (in MS Access, Autonumber/in SQL Server - Identity) Title Keywords Content - content for the page

For each section of content we plan to show in this page, when we enter the data into the table, we will, of course, make the fields not accept nulls.Since the ID field is autonumbering, we don't need to worry about that field when inserting data. When we call this page (let's call it 'Content.aspx'), it will need a querystring added to it, which will be based on the ID field something like 'Content.aspx?id=1". This way, we will then query the database in the Page_Load event, requesting record #1 from our table. it will then return the Title, Keys and the Content for the page. Outside of Page_Load, we dimension the variables: Dim sKeys, sTitle, sContent as String We'll only need a DataReader to retrieve this information, and we can put the information into variables for use within the page, like this:
While objDR.Read sContent=objDR("Content") sTitle=objDR("Title") sKeys=objDR("keywords") End While

For the Meta Tag Keywords, we'll use an ASP.Net Literal control, within the HTML Head Tags called 'litMeta': <asp:Literal ID="litMeta" runat="server"></asp:literal> Then, when we retrieve the information from the database, we'll populate the Meta Tag like this: litMeta.text="<META NAME='KEYWORDS' CONTENT='" & strKeys & "'>" For the Title of the page, we'll use another Literal Control, called 'litTitle': <title><asp:Literal ID="ltTitle" runat="server"></asp:literal></title> Then, to populate the Title when we retrieve the information for the database: ltTitle.text="The Basic Name of your page - " & strTitle As you can see, each of these uses the Literal control in different ways, based on the needs of that particular tag, showing that there are many different ways HTML tags can use data in ASP.Net.

50

Now - for the content portion of the page. This can be done in many different ways. For my tutorial pages on the site, I put each tutorial in a user control, and then, all I add to the Content field in the database is the name of the ASCX page itself. I place an ASP.Net Panel Control (called 'ph1') on the page where I want the user control loaded. When the page loads, I then just ad the particular user control to the panel: Dim myControl as Control=CType(Page.LoadControl(sContent), Control) ph1.Controls.Add(myControl) ph1.visible="true" Naturally, you could just enter the HTML text for your page into the Content field and not have to worry about loading controls. To do this, you could just add another Literal Control to the page (let's call it 'litContent'), and add the HTML text in the database to that literal: litContent.Text=sContent Of course, if you didn't want to worry with the HTML markup of the page, you could purchase one of the great Rich Content Controls on the market, which will replace the Multiline textbox with their control, and you could add the content in much the same concept as a MSWord or any of the WYSIWYG HTML editors. As you see, this tutorial has given you an 'overview' in how to get started with a Data-Driven website concept. Hopefully, it has met its purpose and given you lots of ideas on how you can now recreate this concept on your own website.

51

Creating a Menu User Control


(With Rollovers)
Many people have asked about using Rollover button images in Forums and ListServs lately. Therefore, this tutorial will attempt to explain how to create a menu system as a user control, using Javascript Rollover images. If you've read any of the tutorials on this site before, you know how many times they've started out with something like, "This is not going to be as hard as it sounds". Well, this time is no exception. If you've ever used an HTML/Javascript solution for creating Javascript Rollover Buttons, you know how complicated it can get if you're not using an editor that will help you do it. Technically, the way that is about to be explained uses the same Javascript principles, but in a much less complex way. First, we start out with creating a new User Control. Call it menu.ascx. You can create the visual portion anyway you want it - vertically or horizontally, in a Table or not. However, today, we're creating one in an HTML table, horizontally. In our new menu, there will be three buttons, Art, Contact and Web Design. Keep in mind here, that, for each of these three menu buttons, you will need to create 3 buttons for the different 'States' of the buttons (basic, OnMouseOver, OnMouseDown). As you can see, at this point, this tutorial is going a little bit further than just having a 'Hover' or 'OnMouseOver' state. the 'OnMouseDown' state is for two things - when the button is clicked, and defining a button for when the page relating to the button is the current open page. To enable the Current Page concept, we need to use the old, tried and true Request.ServerVariables("SCRIPT_NAME") method. Just inside the <Script> Tag, we add this line: Dim sScript as String Then, the first line, inside the Page_Load event of the User Control is: sScript=request.ServerVariables("SCRIPT_NAME") This assigns the Current Page name to the variable 'sScript'. In this case, we're going to use the ImageButton ASP.Net Server control for each of the visible buttons in the menu. You will probably ask yourself, "Why not use a HyperLink control?". The answer is fairly simple. I decided to go this way, because, to be perfectly honest, I was not able to get all three states working with the HyperLink Control. The ImageButton Control has an ImageURL property (defining the path of the Image for the button), which we will NOT set inside the control itself because we'll need to check the name of the Current Page before we assign that (in the Page_Load event). The following code snippet will need to be copied/pasted for each ImageButton Control you have in your menu, changing the IDs for each ImageButton.
if Trim(sScript)="/ibtest.aspx" then IB1.ImageURL="art3.gif" else IB1.ImageURL="art.gif" IB1.Attributes.Add("onMouseOut", "this.src = 'art.gif';") IB1.Attributes.Add("onMouseOver", "this.src = 'art2.gif';") IB1.Attributes.Add("onMouseDown", "this.src = 'art3.gif';") end if

52

As you can see, we're adding events to the Attributes collection of the ImageButton. This adds Javascript events to use Client Side for each of the ImageButtons. First, it checks for the Current Page Name, replacing the image with a different basic image, depending on the name of the page. We could use more compact coding methods here, but doing it this way (copying/pasting for each ImageButton) shows it more distinctly for most programming levels . Then, there is one more subroutine that needs to be added, in order to get the redirection we need for the HyperLink-type action. Here, notice the sub routine has two parameters we are going to look at : Source as Object E as ImageClickEventArgs The first parameter, 'Source', we will need to check the ID of the actual ImageButton being clicked. As far as the 'E' parameter goes - notice it says "as ImageClickEventArgs" This is what is needed to recognize the click event for ImageButtons. Here's the subroutine:
Sub doImage(Source as Object, E as ImageClickEventArgs) Select Case Source.ID Case "IB1" response.Redirect("ibtest.aspx") Case "IB2" response.Redirect("another.aspx") Case "IB3" response.Redirect("third.aspx") End Select End Sub

The only thing left, at this point, is the Display code for the ImageButtons, inside the HTML Table:
<div align="center"> <Form id="form1" runat="server"> <table cellpadding="0" cellspacing="0"> <tr> <td align="Center" valign="Top"> <asp:ImageButton id="IB1" onclick="doImage" runat="server" /> </td> <td align="Center" valign="Top"> <asp:ImageButton id="IB2" onclick="doImage" runat="server" /> </td> <td align="Center" valign="Top"> <asp:ImageButton id="IB3" onclick="doImage" runat="server" /> </td> </tr> </table> </Form> <hr> <asp:Label ID="label1" runat="server" /><hr> </div>

53

If you want to download the files to duplicate this on your system, Click here for the User Menu User Control Files. (Naturally, since this example assumes you are using the sample from the root directory of your website, with all the images there too, you would most likely want to pay attentiion to the paths of the images and the file names and put them in a subdirectory/folder on your system, so they wouldn't be in the root). As I told you at the beginning, compared to the hoops you'd need to jump through handcoding Javascript version of this, it is, indeed, fairly simple. So - now the rest is up to you Have Fun!

54

Transferring Form Results to Another Page


(Using Server.Transfer) Since ASP.Net forms submit to themselves by default, many people have asked how to get the form results passed on to another page. There is more than one way to do this. One pretty much entails not putting the 'runat="server"' designation in the form tag, building it just like it was in Classic ASP. However, the main focus of this tutorial is showing you how to accomplish this using the Server.Transfer method. Server.Transfer actually transfers the user to a new page, but there is one down side to this, in some people's eyes. The fact that you are on another page may not be readily known by the end-user. The TITLE of the page changes, but the address bar of the receiving page remains the same as the first page. So here's the full code of what we need on the first page: Yes, Server.Transfer DOES technically work by itself because it moves the browser to the next page, but it takes a little extra work to be able to take all the form results with it when the system gets to the next page. Everything starts with the form, naturally. Here's a sample form for the scenario.
<Form id="form1" runat="server"> First Name: <asp:TextBox id="txtFirst" runat="server" /><br> Last Name: <asp:TextBox id="txtLast" runat="server" /> <asp:Button id="button1" Text="Submit" onclick="doSubmit" runat="server" /> </Form>

As you can see, it's basically two text boxes for User input - FirstName and LastName. The click event of the button goes to a subroutine that does all the work, as it would for any form action. Here we are going to come in contect with the Context Collection. What needs to be done here, in preparation for sending the form results to the next page, is to add each form field item to the Context Collection.
Context.Items.Add("first", txtFirst.text) Context.Items.Add("last", txtLast.text)

The first parameter is the name we give to the item, which will also be referred to on the following page. Then, the second parameter is pointer to the exact form field property (in this case, the textbox TEXT property), to populate the first parameter. To get to the next page, we merely use the following code, which can be copied and pasted in to a page on your computer: Server.Transfer("NextPage.aspx") So here's the full code of what we need on the first page:
<script language="VB" runat="server"> Sub doSubmit(Source as Object, E as EventArgs) Context.Items.Add("first", txtFirst.text) Context.Items.Add("last", txtLast.text) Server.Transfer("Page2.aspx") End Sub </script> <Form id="form1" runat="server"> First Name: <asp:TextBox id="txtFirst" runat="server" /><br>

55

Last Name: <asp:TextBox id="txtLast" runat="server" /> <asp:Button id="button1" Text="Submit" onclick="doSubmit" runat="server" /> </Form>

Then, in the Page_Load event of the receiving page, we need to retrieve those context items. In Classic ASP, we would normally use the Request.form Method. Here's how we 'get' those Context Items we added on the previous page:
Context.Items("first") Context.Items("last")

So, for simplicity's sake, we will display the results on the second page, by adding a label (label1) to the page, displaying and populating it with the context items from the previous page. Here's the full code for Page2.aspx:
<html> <head> <meta name="GENERATOR" Content="ASP Express 2.2"> <title>Second Page</title> <script language="VB" runat="server"> Sub Page_Load(Source as Object, E as EventArgs) label1.text = "The Name you entered was : " & Context.Items("first") & " " & _ Context.Items("last") End Sub </script> <asp:Label ID="label1" runat="server" /> </body> </html>

That's all there is to it. Now, you can create two pages (Page1.aspx and Page2.aspx) on your site and then copy and paste the code you see above to the appropriate pages and duplicate it locally. It's that easy!

56

Using the Ad Rotator


(It's not as difficult as it sounds!) Here's where it all starts: <asp:adRotator AdvertisementFile="/myads.xml" Runat="server"/> Let's say you want the ads on your site to be at the top or bottom of the page. You merely place the adRotator control wherever you want it on your page. This is one of the built in ASP.Net server controls. As you can see, the property 'AdvertisementFile' must point to an xml file. Here, it is named 'myads.xml', but you can name it anything you want - but it needs to be in xml format. Therefore, you might want to brush up on the basics of xml if you don't know what an xml file is. If you know a little about the basics of databases, the format should at least look a little familiar. Just have the path to the xml file an exact one so that the server control can find it, in reference to the page it's on.If you wanted the URLs loaded in a new blank page, you could add the 'target' property inside the adRotator control (target='blank'). Here's the basic format of what's needed in the xml file:
<Advertisements> <Ad> <ImageUrl>/Path/Banner.gif</ImageUrl> <NavigateUrl>http://aspnet101.com</NavigateUrl> <AlternateText> The best ASP.Net web site in the world! </AlternateText> <Impressions>3</Impressions> </Ad> </Advertisements>

Here you see that the base tag (Root element) is 'Advertisements'. All tags which define your particular advertisement/banner will be between the 'Advertisements' tags (child elements to the root element). For those of you unfamiliar with xml, think of a database. 'Advertisements' is a little like the database container itself. (This illustration is not an exact one, by any means - just a general concept type of illustration.) Then, each particular ad needs to go inside it's own open/close 'Ad' tags. Think, then, of a database table - the 'Ad' tags would be the database table. Inside each set of 'Ad' tags, you have properties which apply to that particular 'Ad', which are also child elements of the Ad child element where it resides. Carrying the database illustration to its end, these properties would then be the fields of the database table. For those of you who are familiar with xml - remember, in this illustration, I'm just trying to break it down to a simple means for anyone to understand. The properties in the Ad section are :

ImageURL - this is the full path to the banner ad itself NavigateURL. - This is the URL to which the user will go when the banner is clicked AlternateText - This is the same as the Alt Text for any image in HTML. Impressions - here's how we determine how often the ads run in regards to one another (relative 'weighting'). The higher the number, the more often the ad will run.

One very nice feature is the 'Keyword' feature. You can assign a 'KeyWord' child element for each ad, which sort of assigns a category for that ad. Then, in the server control, itself, you can use the KeywordFilter property in the server control. Let's say you want to only show ads on one page that have to do with Products which are available. You would then add

57

KeywordFilter="Products" to the server control, and it would only show ads on that page which had the keyword 'Products' assigned to the Keyword element in the Ad element. As I said at the start - it's not as difficult as it sounds. All you need to do to start is to create an xml file to house the ads, and point to that file in the Advertisements File property of the adRotator server control. That's all there is to it. Now - just DO IT!

58

Tracking & Displaying Sessions/Visitors Online


(How to show the current number of people at your site) One of the more common questions I've found on the net is 'How do you show the number of current users browsing my site?", like ASPNet101.com has on the bottom left of each page. This tutorial will take the mystery out of this by breaking it down, piece by piece. It all starts with the Global.asax file. For those of you who have come from the Classic ASP world, you will probably recognize the name of this file, since Classic ASP also had a Global.asa file. Here, we track the active Sessions for our application. There are three subroutines into which we'll be looking to do this - Application_OnStart, Session_OnStart, and the Session_OnEnd. First, in the Application_OnStart sub, we basically set the user count to 0, when the server starts
Sub Application_OnStart (Sender as Object, E as EventArgs) ' Set our user count to 0 when we start the server Application("ActiveUsers") = 0 End Sub

Next, in the Session_OnStart subroutine, there are several things happening:


Sub Session_OnStart (Sender as Object, E as EventArgs) Session.Timeout = 10 Session("Start") = Now Application.Lock Application("ActiveUsers") = Cint(Application("ActiveUsers")) + 1 Application.UnLock End Sub

The first thing is the Timeout - you don't need to put anything here, but, the default Timeout is 20 minutes, so you can change or add it, depending on the needs of your particular application. To set the session start time, we add (Session("Start") = Now). Basically, when the user hits the site and opens a web page (asp.net), at the time he/she opens the page, the session starts. Next, we increase the active visitors count when we start the session (Application("ActiveUsers") = Cint(Application("ActiveUsers")) + 1 ). The Application lock & unlock adds more stability to the counting. Next, we must decrement the number of online sessions in the Session_OnEnd subroutine:
Sub Session_OnEnd(Sender as Object, E as EventArgs) Application.Lock Application("ActiveUsers") = Cint(Application("ActiveUsers")) - 1 Application.UnLock End Sub

As you can see, it's pretty much the same code as adding to the current session count - Except - we subtract one from the count, decreasing the active visitors count when the session ends. The last thing to do is to display the count on the page. In this site, I have a user control that shows up on the left side of every page, which does this. Including it in a user control makes it much easier to maintain, since it only needs to be changed in one place and not on every page.

59

As you can see here, very little code is actually necessary to show the current session/user count:
<% Dim intNumber as Integer intNumber =Application("ActiveUsers") response.write (intNumber ) %> Currently Online

Of course, you can use any html tags you'd like to format this in exactly the way you'd like for your site. So now, you can see that the tracking and displaying the number of current sessions/users is a very simple process and can be implemented with little or no fuss on your own site.

60

Inserting Data Into Two Tables


(Getting ID from Table 1 and inserting into Table 2) One of the most common questions on the net these days is how to do the following scenario: "How do I insert data into one table, get the ID from that table and insert that ID and other data, into the second table?" This tutorial uses the SQL Server managed provider for demonstration purposes. The most widely accepted 'best' way to accomplish this, would be to create a Stored Procedure in SQL Server to do it all for you, so that's the direction this tutorial will take.... Here's one I just snipped out of one of mine and edited a little:
CREATE PROCEDURE procInsSamples @CategoryID int, @Title varchar(100), @Description text, @Link varchar(150), @Whatever AS Begin Set NoCount on DECLARE @WhateverID INT Insert Table1(Title,Description,Link,Whatever) Values (@title,@description,@link,@Whatever) Select @WhateverID=@@Identity Insert into Table2 (CategoryID,WhateverID) Values (@CategoryID,@WhateverID) End

This way, you take input from a form (wherever) and insert it into table one - then the next line gets the ID from the newly entered data: Select @WhateverID=@@Identity The next section of the Stored Procedure inserts into Table two what is needed, including the new ID..... So to do all this - First, you must make a connection to your database (SQL Server in this case): Dim strConn as string = "server=(local);uid=sa;pwd=pwd;database=Northwind" Dim MyConn as New SQLConnection(strConn) Then, once you've made your connection to the database: Dim MySQL as string = "YourStoredProcedure Name" Next, we define the command: Dim cmd As SqlCommand = New SqlCommand(strSQL, conn) cmd.CommandType=CommandType.StoredProcedure And add some parameters to the command: cmd.Parameters.Add(New SQLParameter("@CategoryID", strCategory)) cmd.Parameters.Add(New SQLParameter("@Title", strTitle)) cmd.Parameters.Add(New SQLParameter("@Description", strDescription))

61

cmd.Parameters.Add(New SQLParameter("@link", strLink)) cmd.Parameters.Add(New SQLParameter("@Whatever", strWhatever)) (the variables come from assigning textbox input, from a form (or whatever), to each of them, in this case) Then, to wrap it up, open the connection, execute the the command and close the connection: MyConn.Open() MyConn.ExecuteNonQuery() MyConn.Close() Of course here, you'd probably want to put some sort of text telling the user that his task has been accomplished, but basically -- Voila - there you have it in a nutshell.

62

File System List Using System.IO Namespace


This tutorial is more a code sample than a tutorial, but we can't create an online example of it due to security issues. Basically, what you see here is a use of the System.IO namespace to get the file structure of your PC. To get the list of Logical Drives, we use the GetLogicalDrives method. From there, click on the drive you want to get the file structure of that drive. It will list the folders and files from that drive. Naturally, like Explorer, you can drill down as far as you wish here. As you will also see, we show how to display certain files, depending on the file's extension. In this case, we use GIF or JPG files. Each of them should show up as a link. Click on that link and it will open a new window with that image. To download the images used in this tutorial, use these images ( -- -- ) and put them in an images folder. Like we said earlier, there is no online example, but all you'll need to do is to copy this code to a new page on your system, and run it from a file server. Here's the code:
<%@ Import Namespace="System.IO" %> <html> <head> <meta name="GENERATOR" Content="ASP Express 2.1"> <title>Drives/Folders/Files</title> <script language="VB" runat="server"> Dim sSystemDrives as String() Dim intNumberOfDrives as Integer Dim sDrive Dim strParent As String Dim sDriveList as string Sub Page_Load(Source As Object, E As System.EventArgs) Dim Dim Dim For drives As String() = Directory.GetLogicalDrives() count As Integer = drives.Length i As Integer i = 0 To count - 1 sDriveList += "<span class=""dobig""><a href=Files.aspx?d=" & drives(i) & " class='dobig'>" & _ drives(i) & " </a> </span> " Next i Literal1.text+=sDriveList Literal1.text += "<hr>" if request.Querystring("d") <> "" then Dim d as String d=request.querystring("d") GetFiles() End If End Sub Sub GetFiles() Dim strDir As String = Request.QueryString("d") strParent = strDir.Substring(0, strDir.LastIndexOf("\")) 'strParent += strParent.EndsWith(":") ? "\\" : "" if strParent.endswith(":") then strParent=strParent & "\" Try

63

End If upLink.NavigateUrl = "files.aspx?d=" + strParent txtCurrentDir.Text = "Address: <b>" + strDir + "</b>" Dim DirInfo As New DirectoryInfo(strDir) Dim subDirs As DirectoryInfo() = DirInfo.GetDirectories() Dim Files As FileInfo() = DirInfo.GetFiles() txtFileList.Text = "<table border=""0"" width=""50%"">" Dim i As Integer For i = 0 To subDirs.Length - 1 txtFileList.Text += "<tr><td><img src='images/folder.gif'><a href=""files.aspx?d=" & _ subDirs(i).Fullname & _ chr(34) &">" & subDirs(i).Name & "</a></td><td valign='bottom'>" & _ subDirs(i).LastWriteTime & "</td></tr>" Next i For i = 0 To Files.Length - 1 if right(Files(i).Name, 3) = "gif" or right(Files(i).Name, 3) = "jpg" then txtFileList.Text += "<tr><td><img src='images/file.gif'><a href='" & _ strDir & "/" & Files(i).Name & "' target='_blank'>" & _ Files(i).Name & "</a></td><td valign='bottom'>" & _ Files(i).LastWriteTime & "</td></tr>" else _ End If txtFileList.Text += "<tr><td><img src='images/file.gif'>" & Files(i).Name & "</td><td valign='bottom'>" & _ Files(i).LastWriteTime & "</td></tr>"

Next i txtFileList.Text += "</table>" Catch txtFileList.Text = "Error retrieving directory info - Check Drive (" & strParent & ")" End Try End Sub </script><STYLE TYPE="text/css"> <!-BODY { font-family : Arial; font-size : 10pt; } TD { font-family : Arial; font-size : 10pt; } .DoBig { font-family : Verdana; font-size : 12pt; font-weight : bold; } --> </STYLE> </head> <body>

64

<div align="center"><asp:Literal ID="literal1" text="<b>Drives:</b><br>" runat="server" /></div> <form runat="server"> <asp:HyperLink id="upLink" runat="server" ImageUrl="images/up.gif"/> <br/> <asp:Label id="txtCurrentDir" Font-Name="MS Sans Serif" Font-Size="8pt" runat="server"/> <br><br> <asp:Label id="txtFileList" Font-Name="MS Sans Serif" Font-Size="8pt" runat="server"/> </form> </body> </html>

65

Understanding Regular Expressions


(an Introduction to Regular Expressions and their Syntax) This tutorial is not meant to be an exhaustive one, but merely a 'look' at some of the syntax used in Regular Expressions, so that it will not look quite so 'foreign' to you, the next time you look at a Regular Expression inside the Regular Expression Validator in ASP.Net. The use of regular expressions is based on the contents of a string, matching criteria set in play by the assigned Regular Expression. It tests for a pattern within a string. For instance, let's say the string to search comes from a text box called 'Text1'. Let's say that the Regular Expression (matching characters) we are searching for is any lower case letter. The Regular Expression would be [a-z]. Therefore, the string returned from 'Text1.text' will be searched and matched against the Regular Expression. Regular Expressions in ASP.Net, used in Validator Server Controls are kind of like applying rules to the text input. If the Regular Expression above were put into a validator for 'Text1', then, since anything other than lower case letters would NOT match, if we put in the number 6, it would FAIL validation. On the otherhand, 'top' would PASS validation. At this point, we need to stop and discuss several characters (Metacharacters) we must come to understand when using Regular Expressions. Above, we saw two of them - the brackets ([])and the dash (-). First of all, we call any characters we use for search or matching, 'Literals'. The 'a' and the 'z' in the example above are 'Literals'. Next we come to the 'Metacharacter'. Metacharacters in the above example are the brackets and the dash. You can also use the caret (^)/(Shift-6). Also, we can use the dollar sign ($), the question mark (?), the asterisk (*), the plus sign (+), and the period (.). The meanings for these Metacharacters are described below. Metacharacter Meanings: The brackets denote searching for anything laid out inside the brackets. The dash is a 'range separator'. Instead of listing the entire lowercase alphabet, we can merely list a-z, as above, to show all the characters. Therefore, in this example, basically, using [a-z] for the regular expression would mean that we would search the text, and only match, lower case alphabetic characters. That brings up another anomaly about Regular Expressions - case sensitivity. Yes, Regular Expressions ARE case sensitive. This means that if we wanted any alphabetic character to be matched, we would need to put in [a-z], plus [A-Z]. Of course, we could put numeric ranges here, too, like '[0-9]' to match ONLY numeric characters. Another special identifier '\d' does the same thing - the 'd' stands for a digit character. The Caret (^)/(Shift-6), if it is INSIDE brackets will match anything BUT what is listed in the characters next to it - but - it 'negates' whatever is in the Regular Expression (like [^Aa] - this will match anything except the lower or upper case 'A'. However, if it is quite different when used outside brackets. Here, it will look for the characters next to it, and test them against only the BEGINNING of the string, but it looks for an exact match. For instance: '^Dav' will be found in the string 'David is here today', but it will not be matched in 'We're going to find David', since it's not at the beginning of the string. The dollar sign ($), as opposed to the Caret, will look at the END of the target string. For instance, '$fox' will find a match in 'silver fox' but not in 'the fox jumped over the log'

66

The period (.) can be used like a wildcard. Anyone who has used databases should know a little about wildcards, hopefully. Let's say the Regular Expression was 'exp.' - It would match if it found 'expression', 'experience', or 'exponential'. The question mark (?) matches the preceding character 0 or 1 times The asterisk (*) matches the preceding character 0 or more times. It is also sort of like a wildcard. The plus sign (+) matches the previous character 1 or more times. If we need to use one of the metacharacters, literally, then we need an 'escape' character. In this case, we'd precede the metacharacter with a backwards slash mark (\). For instance, since the dash is a range separator, to include the dash itself in the character sequence, we'd have to do it like this: [\-] Two additional metacharacters are the parentheses and the vertical bar (|), sometimes called a pipe, in the Dos/Windows world. Parentheses can be used to group sections of the search expression together, while the pipe will have characters on the right and left of it, and it's used as an either/or type of search. For instance, gr(a|e)y will find 'gray' or 'grey'. What we've seen here is a hint or glimpse into the syntax of Regular Expressions. Hopefully, this will help you the next time you check out any of the Regular Expressions you encounter. This isn't all there is to know about Regular Expressions at all. In later tutorials, we will delve deeper into other characters and how to assemble Regular Expressions. In the mean time, if you would like to see a web site full of Regular Expressions, go to http://www.regexlib.com/ .

67

Das könnte Ihnen auch gefallen