Académique Documents
Professionnel Documents
Culture Documents
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
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" />
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
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" />
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.
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.
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.
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
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" />
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
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
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>
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
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.
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
The basic concept is, that you will then create Content pages, which in the Page Directive, will refer to the master 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 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
</div>
<td align="Center" valign="Top"> <hr> <font Size="2"> <asp:Label Text="Copyright 2006 </font> Runat="server" />
</tr> </table>
</td>
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
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
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
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.
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
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>
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
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
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
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
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 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
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
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
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"
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
%>
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
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" %>
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
46
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
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
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
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
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
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
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
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
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