Advanced C# Programming Unit 4-6 (CSPBC-09 V1.5) Learner Guide
Advanced C# Programming Unit 4-6 (CSPBC-09 V1.5) Learner Guide
CSPBC-09 V1.5
Advanced C# Programming
CSPBC-09
Compiled by Kyle Brunette, Angelique Kolle, Lance Whyte, and Daniel Sansom
Version 1.5
BIBLIOGRAPHY 319
Congratulations on passing the C# A course and welcome to the C# B course! When the
C# B course has been successfully completed, the requirements for C# as a first
programming language will have been met.
Resources
Foxall J, 2008, Sams Teach Yourself Visual C# 2008 in 24 Hours, New Jersey:
Pearson Education, Inc. (ISBN 978-0-672-32990-6)
The study guide does not reference the textbook. The textbook is an invaluable tool
should difficulties be experienced at any point in the course. The textbook and study guide
are based on the assumption that the concepts may be unfamiliar and detailed
explanations are always provided.
Requirements
Windows Vista
Microsoft Office Access 2007
Microsoft SQL Server 2008 Management Studio
Microsoft Visual C# 2008 Express Edition
Microsoft Visual Web Developer 2008 Express Edition
Theory – in the study guide and any extra reading from the textbook.
Theory exam – written after each unit, comprising theory and application questions.
A project must be submitted in Unit 6 and is a prerequisite to writing the theory exam for
Unit 6. The practical exam is the final exam at the end of Unit 6 and may only be
attempted when a pass mark has been achieved for both the project and the theory exam.
Be sure that each unit is thoroughly understood before writing the theory exam. The
exams are made up of theory questions based on the study guide. The application
questions in the exam refer to short pieces of code about which questions will be asked.
Go through all the examples in the study guide. The exercises will help with preparation
for the project and the exams, so it vital to complete them. The checklist provided at the
end of the study guide lists all the exercises and questions which have to be completed
before the project may be handed in, or the final theory exam written.
The theory exam consists of multiple choice questions, true/false questions, multiple
response questions, identifying errors in an existing section of code, and matching
questions. The theory exam at the end of Unit 6 will cover questions from units 1 to 6.
The practical exam involves coding programs using the knowledge gained while working
through the course. The study guide and one textbook of choice are permitted in the
practical exam.
It is advisable to start planning and preparing the project as soon as possible. This
spreads the workload over a longer period of time, and ensures that the project is fully
functional and ready in time. Naturally, the coding of the project cannot commence until
such a time as all the necessary concepts are understood; however, the necessary
research may be done and decisions made about the look and feel of the project.
Diagrams, flowcharts, etc. are invaluable tools in the logical planning of the project.
Use all the available study aids – they help to gain a better understanding of the material.
Structure of a unit
Each unit is broken down into smaller sections. The first section is always an Objectives
section, which outlines what is of particular importance in that section. There are
exercises in each section to test knowledge of the material. Please note that the exercises
are not optional. The exam includes material from these exercises. Therefore, make
sure that all the exercises are done and should something not be clear, please ask for
help. Revision questions are a good indication of what to expect in the exam, although
some exam questions will undoubtedly be more difficult than the revision questions.
Each unit ends with a Test your knowledge section. These sections contain questions
similar to those found in the theory exams. It is therefore very important to attempt these
questions and then to check the answers with an instructor.
The Project specifications are found at the end of Unit 6. It is very important to start with
the project as soon as possible. The project specifications are guidelines which need to
be followed in order to meet the project requirements. Any project which does not meet
the specifications will have to be resubmitted. The instructor will give advice as to which
project should be completed.
Course outcomes
2 Create Web pages using Create a basic Web page using the An IDE and
ASP.NET ASP.NET.
Illustrate the use of events and event handlers
in an ASP.NET application.
Create an advanced Web from using code-
behind files.
Illustrate the use of data binding and database
connection in an ASP.NET application.
Make an ASP.NET application visible to others.
Beginning a project
The project should be started as soon as possible and must be completed by the end of
Unit 6. In order to complete a project successfully, the following should be kept in mind:
1. Read the relevant sections in the study guide to be familiar with the material.
2. Go through the relevant sections of the textbook with the study guide at hand. The
study guide contains extra information on certain topics which provides a broader
knowledge base for the exams, as well as pointers to important concepts that could be
applied in the project.
3. Type in the examples from the study guide. This might seem pointless, but it is an
easy way to become familiar with the language. Make sure to experiment with the
code; make deliberate mistakes to get a feel for the way the compiler handles errors.
4. Do the exercises at the end of every unit in the study guide. The best way to learn a
language is through practice.
5. Plan the application in advance. Decide what the user interface will look like, what
classes need to be created, etc.
6. Start with the project as soon as possible.
If these guidelines are followed, the project should not prove too difficult.
Required documentation
Once the project is complete it must be submitted on a disk and placed in a folder that has
the learner’s name and learner number clearly displayed, together with the following
documentation:
An instructor will mark the project and a project evaluation form consisting of various
sections will then be returned. The general expectations for each of the sections are given
below:
Program design
The project specifications must be followed. For example, if the project specification
specifies the use of a class, then that class must be used. Creativity is encouraged, but
certain elements must be incorporated into the project.
Source code
The program listing (or source code) must be clear and well laid out.
The naming standards for variables and method names must be followed.
Method and variable names should be descriptive.
Each file must be clearly labelled, with a prologue giving the details for that file.
There should be adequate and suitable comments in the code.
User documentation
This should include the program name, the date on which the document was last
modified, and the name and contact details of the author.
Give an indication of the data that will have to be entered, as well as valid values for
these data items.
If any files are read from or written to, include these details.
Outline any errors which may occur, and how to handle them.
There should be no mistakes in the user/operation documentation.
User interface
Coding
o If the program does not run, or there are warnings of any kind. If the program
does not run, the project will be failed.
o If there are any syntax errors.
o If there is redundant or inefficient code.
o If there are any logic errors.
o If variable names are not descriptive.
o If variables are declared as the incorrect type.
o If method names are not descriptive or self-explanatory.
o If the specifications are not followed.
User interface
o If the interface is not eye-pleasing.
o If any functionality does not work, or is missing.
o If the interface is not reasonably self-explanatory, i.e. someone who has not used
it before should be able to understand how it works with minimal effort.
o If the specifications are not followed.
User documentation
o If the user documentation does not adequately explain how to install and run the
application, working on the assumption that the end-user has no prior experience
of doing so.
o If the user documentation does not explain how to use each feature of the
application. The screenshots included must clarify each operation.
o If the user documentation is not handed in with the project, printed in colour.
Project documentation
Printed copy of all the documentation must accompany the project disk that is handed in to
the instructor as it is also evaluated.
Those who have to maintain the code know what every single line of code is intended
to do (program design documentation and source code documentation).
Those who have to use the program know how to run it, what to expect, and what
output will be displayed or printed (user documentation).
A well-documented program will be easier to follow, modify, debug, and maintain. At the
minimum, comments should be included for each program flow or control statement (e.g.
For, If, While, etc), stating what is intended.
It is also important to include a prologue at the top of each file listing (the printout of that
file), which should look similar to the following example:
/*
* Filename: MyProgram.cs
* Author: John Doughnut
* Created: 03/11/2008
* Operating system: Windows Vista
*
* Description:
* This program was written to convert Fahrenheit to Celsius.
*/
Name of file
Name of author
Date created
Operating system
‘Big picture’ description of the code
Any modification information
User documentation
The user documentation is a separate document to the source code documentation. The
emphasis should be on how the program is used, rather than a description of code. The
user documentation must contain the following information:
Screenshots of the application, and any output it might generate, should be included in the
user documentation. When the program is running, screenshots can be taken using the
Print Screen key (hint: hold down the <Alt> key while pressing <Print Screen> to take a
screenshot of the current window). After the screenshot has been taken, the image can be
pasted into a graphics editing application (for example, Microsoft Paint) and saved. Once
saved, the image can be inserted into the user documentation to give the user an idea of
what to expect when the program runs.
Symbol guide
Font guide
This unit counts 10% towards part B (Units 4, 5, and 6) of the C# mark, and there are 12
days to complete it. The time and marks are scheduled as follows:
Reading 10 days
Exam preparation and exam 2 days 10%
This unit covers user controls, deploying applications, maintaining and supporting
applications, attributes, reflection, file I/O, and ADO.NET.
A custom control will be referred to from now on as a user control. Make sure that all the
steps below, demonstrating how to create a user control, are followed precisely and
accurately, paying attention to all the details. Also note that there are two ways to add a
user control to a project.
The application should look like the one in Figure 4.1 below:
Not much can be done with this application at the moment, so the custom control itself
must now be created. For this example, a user control called TimerControl is created.
User controls can be contained in a .dll file, but they do not themselves contain .dll files.
Create a new user control class by going to Project > Add User Control…
A dialog window will appear with user control already selected.
Name the user control TimerControl.cs and click OK.
An empty grey rectangle will appear where the Form was previously (as in Figure 4.2). It
can be treated just like a Form, because controls can be added to it to create functionality.
A user control can be made up of other existing controls. This means that other controls
such as the Label, TextBox, and Button controls can all be added to make up the user
control. In the end, these controls will have to function together in order to perform one
task that will be controlled by the user control.
The next step is to add the necessary controls to the new user control and add some code
to it.
Add a Label control named lblTime and a Timer control named tmrNow to the
empty user control.
Set the Text property of lblTime to “Time”.
Set the Enabled property of tmrNow to true, and the Interval property to 1000.
At this stage, the TimerControl should look like Figure 4.3 below:
Press the <F7> key or right-click on the form and select View Code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CustomUserControl
{
public partial class TimerControl : UserControl
{
public TimerControl()
{
InitializeComponent();
}
}
}
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9
10 namespace CustomUserControl
11 {
12 public partial class TimerControl : UserControl
13 {
14 public TimerControl()
15 {
16 InitializeComponent();
17 }
18
19 private void tmrNow_Tick(object sender, EventArgs e)
20 {
21 lblTime.Text = DateTime.Now.ToLongTimeString();
22 }
23 }
24 }
Note that lines 19 to 22 have been added to the previous code snippet. The
ToLongTimeString() method converts Now to a string containing the current time.
The get and set properties are used to expose the colour to be added to the user control.
Add the following private variables to the TimerControl class just below the first
curly bracket ({):
In order for these variables to work add the following properties below the public
TimerControl() class:
The entire section of code, incorporating all the additions outlined above, should look as
follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CustomUserControl
{
public partial class TimerControl : UserControl
{
// Private variables.
private Color colFColour;
private Color colBColour;
public TimerControl()
{
InitializeComponent();
}
Now that the TimerControl has been created, press the <F6> key to build the
project.
This should add the TimerControl to the top of the Toolbox window. If it still does not
appear in the Toolbox window, go to the Design view in the main form and it should
appear.
Once the user control has been added to the form, check the Properties window. It is
now possible to set the background and foreground colour of the timer, as shown in Figure
4.4:
Add a Label control named lblOne to the form and change the Text property to
“The current time is:”
Drag and drop the TimerControl onto the form.
Press the <F5> key for the application to run.
One way of adding a user control to a form has now been explored but if the user control
needs to be available to other applications, a different approach must be taken.
Create a new Class Library by going to File > New Project > Class Library and
name it TimeUserControl.
Right-click on the project name (CustomTimerControl) in the Solution Explorer.
From there select Add > User Control. Name it TickTimeUserControl. This process
is shown in Figure 4.6:
The Solution Explorer contains a file called Class1.cs as shown in Figure 4.7. This
file must be deleted!
The same controls that were created in the previous example can be added to this user
control. After the controls have been added, the TickTimeUserControl should look
identical to Figure 4.7.
Add the same code that was added to the previous example for the tmrNow_Tick
event-handler.
Make sure that the project is built before closing it and after any changes are made. This
is done by going to Build > Build Solution or by pressing the <F6> key on the keyboard.
If this is not done, the user control will not be available for use in other applications.
These were simple examples to explain the concept of user controls and how to add and
use them.
Right-click on the form and select View Code to go to the Source code view.
Alter the code as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TestControl
{
public partial class TestUserControl : UserControl
{
private int maximum = 100;
private int minimum = 0;
private int val = 0;
public TestUserControl()
{
InitializeComponent();
}
Please note that if the properties have private access, they will not be recognized when
adding the user control to the main form and these properties will not be accessible. All
properties must have public access.
Build the TestUserControl and switch to the Design view of the Windows Forms
Application that was created at the start of the example. The TestUserControl control
should appear at the top of the Toolbox window.
Add the TestUserControl control to the form.
Add two Button controls to the form: btnValueAdd and btnMaxAdd (Figure 4.9).
Double-click on the btnValueAdd Button control and change the code as follows:
Double-click on the btnMaxAdd Button control and change the code as follows:
The output should look as follows if both Button controls have been pressed once
(Figure 4.10):
4.1.2 Exercises
1. As what is a user control also known?
2. Which event is used in this section for the TickTimer control?
2. In which directory will a class library (.dll) be found once the project
has been built?
a. obj/Debug
b. bin/Debug
c. bin/Release
d. obj/Release
It is not possible to pass a string value (e.g. a value entered into a TextBox control)
directly to a DateTime variable. The string must first be parsed before assigning it to
the DateTime variable. The example below parses the string and then assigns it to the
DateTime variable:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace StringToDateTimeExample
{
class Program
{
static void Main(string[] args)
{
string myDate = "11/04/2009";
DateTime dt = Convert.ToDateTime(myDate);
Console.WriteLine("Year: {0}, Month: {1}, Date: {2}", dt.Year,
dt.Month, dt.Day);
}
}
}
Note that when converting a string to a DateTime, the following syntax is used, but it
can be changed:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime myDate = new DateTime(1999, 11, 4);
DateTime newMyDate = myDate.AddMonths(6);
Console.WriteLine("Initial date: {0}", myDate);
Console.WriteLine("New date: {0}", newMyDate);
}
}
}
Note that no additional namespaces have to be imported, as those that were automatically
included will suffice. Also note the time added after the date. This is a default time placed
in a DateTime variable when only a date is specified.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime myDate = new DateTime(1999, 11, 4);
DateTime newMyDate = myDate.AddMonths(-1);
Console.WriteLine("Initial date: {0}", myDate);
Console.WriteLine("New date: {0}", newMyDate);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime myDate = new DateTime(1999, 11, 17);
DateTime newMyDate = myDate.AddYears(9);
Console.WriteLine("Initial date: {0}", myDate);
Console.WriteLine("New date: {0}", newMyDate);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime myDate = new DateTime(1999, 11, 17);
DateTime newMyDate = myDate.AddHours(2);
Console.WriteLine("Initial date: {0}", myDate);
Console.WriteLine("New date: {0}", newMyDate);
}
}
}
The application will have the following result. Notice how only the time value has changed
and not the date.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime myDate = new DateTime(1999, 11, 04);
int yearResult = myDate.Year;
Console.WriteLine("The year: {0}", yearResult);
int monthResult = myDate.Month;
Console.WriteLine("The month: {0}", monthResult);
The following example is very similar to the previous one, except the day (in words) will be
retrieved here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime myDate = new DateTime(1999, 11, 04);
int yearResult = myDate.Year;
Console.WriteLine("The year: {0}", yearResult);
int monthResult = myDate.Month;
Console.WriteLine("The month: {0}", monthResult);
string dateResult = Convert.ToString(myDate.DayOfWeek);
Console.WriteLine("The day: {0}", dateResult);
}
}
}
This is the date and time at a specific moment. The DateTime class provides a property
which can be used to access the current date and time. The following example shows
how this is done:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CurrentDateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime curDateTime = DateTime.Now;
Console.WriteLine("The current date and time: {0}", curDateTime);
}
}
}
In order to access only the current date, the DateTime.Today property is called:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CurrentDateTimeExample
{
class Program
{
static void Main(string[] args)
{
DateTime curDateTime = DateTime.Today;
Note that a default time is added because it was not specified. Remember that
DateTime.Now accesses both the date and time, and DateTime.Today accesses only
the date.
4.2.6 Exercises
1. What needs to be done when passing a string value to a
DateTime variable?
2. Which method is used to subtract a month from a certain date?
Select the The application will not check for updates option.
Click the Next > button.
The folder where the application was published automatically opens. In this case, it has
been published to the desktop. The window displayed in Figure 4.16 should appear:
If images are used in an application, it is very important to note the following procedure
when adding the images to the project.
Click on the Button control, select its Image property, and add all the images to the
resources folder as shown below in Figure 4.19:
Click on the “…” button and the window displayed in Figure 4.17 should appear:
Click on the Import… button and browse the folders to select the images that need to
be added to the project.
Click the OK button and the images should now appear in the Solution Explorer
window as shown in Figure 4.21:
When the images are added to the project in this way and the application is added to any
other folder, the application will not crash since it knows where to find the images.
Select the image in the Solution Explorer window and change the following properties:
The properties will look like the image displayed in Figure 4.22 below:
One advantage of deploying an application in this way is that the application is added to
the Start menu automatically and it can be found in the Control Panel.
Should the need to delete the deployed application ever arise, follow this procedure: go to
Start > Control Panel > Programs and Features. The application name is the same as
the project name.
Select the application and click on the Uninstall/Change button at the top of the
window as shown in Figure 4.23:
4.3.2 Exercises
1. Name one advantage of deploying a Windows application.
2. What is the technique of deploying an application called?
Below is a list of standards for writing high-performance applications when using the .NET
Framework:
4.4.2 Exercises
1. Why should frequent boxing and unboxing be avoided?
2. When working with collections, which method should be used in
preference to the Add() method?
3. What should be used instead of a DataSet and why?
4.5 Attributes
Identify attributes.
Use single and multiple attributes.
Use attribute targets.
Create custom attributes.
Attributes defined in the CLR (Common Language Runtime), i.e. existing attributes.
These are also known as intrinsic attributes.
Attributes created by the programmer to add information to the program code. These
attributes are known as custom attributes.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace AttributesExample
7 {
8 public class Attributes
9 {
10 [Obsolete("Generating error...", true)]
11 static void ObsoleteMethod() { }
12 static void Main(string[] args)
13 {
14 ObsoleteMethod();
15 }
16 }
17 }
Figure 4.24 shows the error message which is displayed when attempting to run this
application:
An error message is printed notifying that the method is obsolete. Now change the true
value on line 10 to false. The result should look like Figure 4.25 below:
The program runs, but this time a warning is generated instead of an error.
[Obsolete, Serializable]
OR
[Obsolete]
[Serializable]
1 #define CONDITION_TRUE
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6
7 namespace MultipleAttributesExample
8 {
9 class MultipleAttributes
10 {
11 [System.Diagnostics.ConditionalAttribute("CONDITION_TRUE")]
12 static void NextMethod()
13 {
Nothing appears in the command prompt window. In other words, the condition was not
met, i.e. CONDITION_TRUE did not appear in the program, so NextMethod() method
was not executed and nothing is displayed in the output.
[assembly: SomeAttribute]
Table 3 – Attributes
Member Description
All Applied to any of the following elements: assembly, class,
class member, delegate, enum, event, field, interface,
method, module, parameter, property, return value, or struct.
Class Applied to the instance of the class.
ClassMembers Applied to classes, structs, enums, constructors, methods,
properties, fields, events, delegates, and interfaces.
Constructor Applied to a given constructor.
Delegate Applied to the delegate method.
Enum Applied to an enumerator.
Interface Applied to an interface.
Struct Applied to a struct.
All attributes are actually classes which inherit from System.Attribute. As such, an
attribute can be defined as follows:
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7
8 namespace CustomAttributeExample
9 {
10 public class CustomAttribute : Attribute { }
11 }
Note how CustomAttribute class inherits from the Attribute class on line 10. Once
the attribute has been created, it can be used anywhere in the program:
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8
9 namespace CustomAttributeExample
10 {
11 public class CustomAttribute : Attribute { }
12 [CustomAttribute()]
13 public class TesterClass { }
14 }
The example shows how CustomAttribute is created and inherits the Attribute
class on line 11. The custom attribute CustomAttribute is then used on line 12 and will
represent the TesterClass class on line 13.
4.5.6 Exercises
1. Name the process which can be used to access attributes at
runtime.
2. Name the two types of attributes.
3. What are attribute targets?
4.6 Reflection
4.6.1 Reflection
Reflection and attributes go hand in hand. Reflection only occurs during runtime. This is
done using classes in the Reflection namespace, as well as the System.Type and
System.TypedReference classes.
Figure 4.26 begins with the assembly at the top of the hierarchy. The assembly is a
partially compiled code library which takes the form of an executable file. An assembly
may consist of one or more script files, referred to as modules. Each module can consist
of one or more types (i.e. class, delegate, enum, or struct). Each type may consist
of one or more events, fields, properties, and/or methods. The inheritance hierarchy
should be kept in mind when progressing through this section.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Reflection;
6
7 namespace ReflectionExample
8 {
9 class ReflectionEx
10 {
11 static void Main(string[] args)
12 {
13 string inputString = "";
14 do
15 {
16 Console.WriteLine("Choose an option: (1, 2, " +
17 "3 or q)");
18 Console.WriteLine("1. System.String");
19 Console.WriteLine("2. System.Int32");
20 Console.WriteLine("3. System.Console");
21 Console.WriteLine("4. Quit (q)");
22
23 inputString = Console.ReadLine();
24
25 if (inputString == "1")
26 {
27 displayInfo(typeof(System.String));
28 }
29 else if (inputString == "2")
30 {
31 displayInfo(typeof(System.Int32));
32 }
33 else if (inputString == "3")
34 {
35 displayInfo(typeof(System.Console));
36 }
37 else
38 {
39 inputString = "q";
40 }
41 } while (inputString != "q");
42 }
43
44 static void displayInfo(Type type)
45 {
46 // Obtain information about the types of methods
47 MemberInfo[] m = type.GetMethods();
48 foreach (MemberInfo mem in m)
49 {
50 Console.WriteLine("Method: " + mem);
51 }
52
53 // Obtain information about the types of interfaces
54 m = type.GetInterfaces();
55 foreach(MemberInfo mem in m)
56 {
57 Console.WriteLine("Interfaces: " + mem);
58 }
59 // Obtain information about the types of fields
60 m = type.GetFields();
61 foreach(MemberInfo mem in m)
62 {
63 Console.WriteLine("Fields: " + mem);
64 }
65 }
66 }
67 }
The first thing to note in the above example is that System.Reflection has to be
imported (line 5) to be able to apply reflection. Lines 15 to 20 prints a menu from which
the user will have to select an option. Line 22 reads the input from the user and from line
24 to 41 the input is interpreted and checked so that necessary methods are performed.
These activities occur within a do…while loop (refer to Unit one).
The displayInfo() method on line 46 displays one of three options that may have been
selected by the user. It will display either method information by using GetMethods(),
interface information by using GetInterfaces(), or field information by using
GetFields().
The Type class is at the root of all reflection classes and is therefore the primary way to
access metadata. The typeof operator returns an object of the type Type. The
MemberInfo class is derived from the Type class and encapsulates information about the
class members. These include methods, properties, fields, and events. MemberInfo is
provided to discover the attributes of a member and to provide access to metadata.
4.6.4 Exercises
1. How can reflection be used in late binding?
2. The “Type” level in the inheritance hierarchy can be a(n) _______,
_________, _________, or _________.
File Class
Methods Function
Create Creates a file in a specified directory.
CreateText Creates a file and returns a StreamWriter object that can be
used to write text to that file.
AppendText Returns a StreamWriter object to a specific existing file. The
text will be appended to the end of the file. If the file does not
exist, AppendText creates one.
Exists Returns true if a file in a specific path exists, otherwise it returns
false. It only has a path and filename as parameters.
Copy Copies a file into another folder.
Move Moves a file to another directory.
Open Opens a file and returns the FileStream object.
OpenRead Opens a file as read-only and returns the FileStream object.
OpenText Opens a file and returns the StreamReader object.
OpenWrite Opens a file and returns the Stream object.
GetAttributes Obtains the file’s attributes and returns a bitwise combination.
SetAttributes Changes the attributes of a file.
FileInfo Class
Methods Function
Create Same as Create from the File class. It creates a file in a
specified directory.
Here are a few important facts to know when working with files and directories:
Both the File and FileInfo classes can be used to create files. However, the
usage of each is slightly different:
4.7.3 Streams
The Stream class is primarily used to transfer data from one place to another. The
Stream class provides functionality to manipulate streams, but is itself an abstract class.
Subclasses such as FileStream, BufferedStream, and CryptoStream inherit from it
to provide specific functionality. Table 5 lists the most common methods of the Stream
class:
The FileStream class is used to read and write bytes to a file. FileStream objects are
frequently used in conjunction with BufferedStream objects, which can improve
performance. The example below creates a file and writes three bytes to it. If the file
already exists then the information stored in that file will be overwritten.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6
7 namespace FileStreamExample {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 FileStream fs = new FileStream("C:/newBytes.txt", FileMode.Create);
13 Byte[] bytes = new Byte[3];
14 bytes[0] = 50;
15 bytes[1] = 51;
16 bytes[2] = 52;
17 fs.Write(bytes, 0, 3);
18 fs.Close();
19 }
20 }
21 }
The Write() method on line 17 contains three parameters. The general syntax looks as
follows:
The first parameter takes the bytes array. The second parameter indicates the position in
the array from which the bytes are retrieved, and the last parameter indicates how many
bytes must be read from the array.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace StreamReaderExample
{
class Program
{
static void Main(string[] args)
{
StreamReader sr = new StreamReader("c:/StreamReader.txt");
if (byLine != null)
{
Console.WriteLine(byLine);
byLine = sr.ReadLine();
}
else
{
Console.WriteLine("File is empty!");
}
sr.Close();
}
}
}
The BufferedStream class is used to wrap the Stream class and improve performance.
Note that the BufferedStream class is derived from the Stream class and therefore
inherits the methods and properties of the Stream class.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6
7 namespace StreamWriterExample
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 FileStream fs = new FileStream("c:/Examples/StreamWriter.txt",
14 FileMode.Create);
15 BufferedStream bs = new BufferedStream(fs);
16 Console.WriteLine("File created...");
17 fs.Close();
18
19 StreamWriter sw = new
20 StreamWriter("c:/Examples/StreamWriter.txt");
21 Console.WriteLine("Writing to a file...");
22 sw.WriteLine("Using the StreamWriter to write data to this " +
23 "file");
24 sw.Close();
25 }
26 }
27 }
File created...
Writing to a file...
Line 13 creates a new text file on the c drive in the Examples folder. Remember to close
the FileStream object first (as done on line 17) before proceeding, otherwise the
application will cause an exception and the application will exit. Note the
BufferedStream object used on line 15.
In order to see the full extent of the example, go to the Examples folder and open the text
file. The text in swLine is displayed in the file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace BinaryReaderExample
{
class Program
{
static void Main(string[] args)
{
BinaryReader br = new BinaryReader(File.OpenRead
("c:/BinaryReader.bin"));
Byte b = br.ReadByte();
string s = br.ReadString();
Console.WriteLine(b);
Console.WriteLine(s);
br.Close();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace BinaryWriterExample
{
class Program
{
static void Main(string[] args)
{
BinaryWriter bw = new BinaryWriter(File.Create("c:/BinaryWriter.bin"));
string str = "Hello";
Byte b = 10;
bw.Write(str);
bw.Write(b);
// Always remember to close the BinaryWriter.
bw.Close();
}
}
}
4.7.5 CryptoStreams
CryptoStreams are used to write encrypted data to a file and decrypt data read from a
file. The encryptor and decryptor need to use the same byte array to be able to decrypt
the message written. The CryptoStream class inherits from the Stream class and
contains the methods listed in Table 7.
The following methods of the Console class can be used to change the location of the
input and output:
Console.SetIn(TextReader);
Console.SetIn(TextWriter);
Console.SetError(TextWriter);
The following example changes the standard error stream to a log file named
LogBobError.txt and the standard output to a file named OutFile.txt. The standard input
is received via the keyboard.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6
7 namespace StandardIOExample
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Console.Out.WriteLine("Enter a few names:");
14
15 StreamWriter streamOut = new StreamWriter(new FileStream
16 ("c:/OutFile.txt", FileMode.Create, FileAccess.ReadWrite));
17
18 StreamWriter streamError = new StreamWriter(new FileStream
19 ("c:/LogBobError.txt", FileMode.Create));
20
21 Console.SetOut(streamOut);
22
23 Console.SetError(streamError);
24
25 String str = null;
26
27 do
28 {
29 str = Console.ReadLine();
30 Console.Out.WriteLine(str);
31
32 if (str.Equals("Bob"))
33 {
34 Console.Error.WriteLine("'Bob' was entered!");
35 }
36 } while (!str.Equals(""));
37
38 Console.Out.Close();
39 Console.Error.Close();
40 }
41 }
42 }
The Console.Out.WriteLine() method on line 13 uses the default output stream that
is printed to the console. All text input from line 15 onwards is written to the
OutFile.txt file. The program concludes when no text is entered and <ENTER> is
pressed. If “Bob” was one of the names entered, “’Bob’ was entered!” will be written to the
LogBobError.txt file.
The input and output in the command prompt should look as follows:
Figure 4.27 shows what the OutFile.txt file looks like after the application is run:
Figure 4.28 below shows what the LogBobError.txt file looks like:
4.7.7 Exercises
1. Which namespace is used for file input and output?
2. Name four options which can be used with the FileMode property.
4.8 ADO.NET
Create a database.
Create a connection to a database.
Select and display data from a database.
Manipulate data in a database.
Populate a data source with DataSet.
Class Description
SqlConnection A SqlConnection object represents a connection to a SQL
Server data source. It can be used together with SqlCommand
and SqlDataAdapter to increase performance when
connecting to a Microsoft SQL Server database.
SqlCommand A SqlCommand object executes commands at a SQL Server
database, e.g. ExecuteReader and ExecuteNonQuery.
These will be dealt with in more detail at a later stage.
SqlDataReader The SqlDataReader object creates a way of reading a
forward-only stream of rows from a SQL Server database. The
ExecuteReader (as mentioned above) is used in conjunction
with the SqlDataReader.
SqlDataAdapter The SqlDataAdapter object represents a set of data
commands and a database connection that are used to fill a
DataSet (this will be dealt with in more detail at a later stage)
and update a SQL Server database.
NOTE
MS Access 2007 is used here to create the tables.
The UniqueID value in the Appointment table refers to the UniqueID of the client for whom
the appointment was made. Therefore, a relationship must be created between the
UniqueID fields in each table. It is not necessary to enforce referential integrity for this
relationship. Make a note of where the database is saved because it will be needed when
specifying the path.
On the left-hand side of the table, next to the UniqueID field, there is a small +. Click on it
to expand the Appointment table (as in Figure 4.30). It is possible to expand the table in
this way because a relationship was created between the tables and they are linked by the
UniqueID field.
USE master
GO
USE Salon
GO
Press the Execute button in SQL Server Management Studio to execute the script file
and insert the tables.
Create another script file which will insert sample data into the tables that have just
been created. The script file may look something like the one shown below.
USE Salon
GO
If you would like to see how the data was inserted into the tables, enter the following in
a new script file. This should not be anything new to you as this was explained in
detail during the SQL Server module.
USE Salon
GO
SELECT * FROM CLIENT
GO
The image shown in Figure 4.32 should be displayed at the bottom of the SQL Server
Management Studio:
A window appears where the path of the database must be selected. Make sure the file
type is changed to Data Files on the right-hand side of this window.
The Data Source Configuration Wizard window will appear as shown in Figure 4.34.
No tables or views are selected here because we do not need to create a data source.
The database will now appear on the right side of the screen in the Solution Explorer as
shown in Figure 4.35:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.OleDb;
7
8 namespace DatabaseExample
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 string connString = "Provider=Microsoft.ACE.OleDb.12.0;" +
15 "Data Source=../../Salon.accdb";
16 OleDbConnection conn = new OleDbConnection(connString);
17 conn.Open();
18 }
19 }
20 }
Take note of the connection string that is used in lines 14 and 15.
There are two new namespaces: System.Data and System.Data.OleDb. These must
be added in order to work with ADO.NET and databases. The connection string can also
include a user ID and password, but this is not necessary for a Microsoft Access database
unless it has been password-protected.
The connection string highlights one advantage of importing the database into the project.
If this had not been done, the absolute path to the database would need to have been
specified. However, because the database has been imported, a simpler, relative path
can be used.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace DatabaseExample2
{
class Program
{
static void Main(string[] args)
{
string connString = "Integrated Security=SSPI; " +
"Initial Catalog=Salon; " +
"Data Source=localhost";
SqlConnection sqlConn = new SqlConnection(connString);
sqlConn.Open();
}
}
}
There are some subtle changes in the connection string which are easy to spot. The
Initial Catalog in the connection string is the name of the database being used, and
the Data Source is the name of the PC on which you are working. To avoid errors with
the Data Source when moving the application to another computer, the localhost
keyword will be acceptable. This basically acts a replacement for the name of the PC.
OR
while (reader.Read())
{
int uniqueID = (int)reader["UniqueID"];
string name = (string)reader["Name"];
string surname = (string)reader["Surname"];
string address = (string)reader["Address"];
string telephone = (string)reader["Telephone"];
All the data above was retrieved with knowledge of the data type. If the data type is
unknown, the GetValue() method is used instead of the GetInt16() or GetString()
methods:
Remember that any exceptions that may occur must be caught (this will be included in all
subsequent examples). The OleDbException is caught in the example below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace DatabaseExample
{
class Program
{
static void Main(string[] args)
{
try
{
string connString = @"Provider=Microsoft.ACE.OleDb.12.0;
Data Source=Salon.accdb";
// Connection to the database.
OleDbConnection conn = new OleDbConnection(connString);
// Opening the database.
conn.Open();
conn.Close();
}
catch (OleDbException ole)
{
Console.WriteLine(ole.Message);
}
}
}
}
ID: 1, Name: Angelique, Surname: Kolle, Address: 58 First Ave, Alberton North,
Telephone: 0735149000
ID: 2, Name: Brian, Surname: Scott, Address: 12 Peach Str, Primrose,
Telephone: 0825055972
ID: 3, Name: Kim, Surname: Crous, Address: 109 West Str, Johannesburg,
Telephone: 0765894258
ID: 4, Name: Bradley, Surname: Smith, Address: 23 Seventh Ave, Sandton,
Telephone: 0796584123
Press any key to continue. . .
In the code above, the @ symbol is used. This allows the connection string value to be
read as a whole. This means it is read as if it was never split by the line.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
namespace SqlConnectionApplication
{
class Program
{
static void Main(string[] args)
{
string stringConn = @"Integrated Security=SSPI;
Initial Catalog=Salon;
Data Source=localhost";
SqlConnection sqlConn = new SqlConnection(stringConn);
try
{
sqlConn.Open();
while (reader.Read())
{
// Assigns the data in each field to a variable.
int uniqueID = (int)reader["UniqueID"];
string name = (string)reader["Name"];
string surname = (string)reader["Surname"];
string address = (string)reader["Address"];
string telephone = (string)reader["Telephone"];
sqlConn.Close();
}
catch (SqlException se)
{
Console.WriteLine(se.Message);
}
}
}
}
ID: 10, Name: Angelique, Surname: Kolle, Address: 58 First Ave, Alberton
North, Telephone: 0735149000
ID: 11, Name: Brian, Surname: Scott, Address: 12 Peach Str, Primrose,
Telephone: 0825055972
ID: 12, Name: Kim, Surname: Crous, Address: 109 West Str, Johannesburg,
Telephone: 0765894258
ID: 13, Name: Bradley, Surname: Smith, Address: 23 Seventh Ave, Sandton,
Telephone: 0796584123
Press any key to continue . . .
The following example shows how this can be done using an OleDb connection:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 // Namespaces needed to work with ADO.NET.
6 using System.Data;
7 using System.Data.OleDb;
8
9 namespace DatabaseExample
10 {
11 class Program
12 {
13 static void Main(string[] args)
14 {
15 try
16 {
17 string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
18 Data Source=../../Salon.accdb";
19 // Connection to the database.
20 OleDbConnection conn = new OleDbConnection(connString);
21 // Opening the database.
22 conn.Open();
23
24 OleDbCommand cmd = conn.CreateCommand();
25 // SQL query used to retrieve data.
26 cmd.CommandText = "SELECT * FROM Client";
27
28 OleDbDataReader reader = cmd.ExecuteReader();
29
Lines 45 to 48 have been added to the previous example. The output looks as follows:
ID: 1, Name: Angelique, Surname: Kolle, Address: 58 First Ave, Alberton North,
Telephone: 0735149000
ID: 2, Name: Brian, Surname: Scott, Address: 12 Peach Str, Primrose,
Telephone: 0825055972
ID: 3, Name: Kim, Surname: Crous, Address: 109 West Str, Johannesburg,
Telephone: 0765894258
ID: 4, Name: Bradley, Surname: Smith, Address: 23 Seventh Ave, Sandton,
Telephone: 0796584123
The only difference in the result is the addition of the last line that indicates how many
columns there are in the current row. The number of rows can be counted using a SQL
connection in exactly the same way as with the OleDb connection (as shown above). Use
the example in section 4.8.11 and add the FieldCount property.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 // Namespaces needed to work with ADO.NET.
6 using System.Data;
7 using System.Data.OleDb;
8
9 namespace DatabaseExample
10 {
11 class Program
12 {
13 static void Main(string[] args)
14 {
15 try
16 {
17 string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
18 Data Source=../../Salon.accdb";
19 // Connection to the database.
20 OleDbConnection conn = new OleDbConnection(connString);
21 // Opening the database.
22 conn.Open();
23
24 OleDbCommand cmd = conn.CreateCommand();
25 // SQL query used to retrieve data.
26 cmd.CommandText = "SELECT * FROM Client";
27
28 OleDbDataReader reader = cmd.ExecuteReader();
29
30 // Loop that reads all records in the dbReader.
31 while (reader.Read())
32 {
33 // Assigns the data in each field to a variable.
34 int uniqueID = (int)reader["UniqueID"];
35 string name = (string)reader["Name"];
36 string surname = (string)reader["Surname"];
37 string address = (string)reader["Address"];
38 string telephone = (string)reader["Telephone"];
39
40 // Displays the retrieved data to the console.
41 Console.WriteLine("ID: {0}, Name: {1}, Surname: {2}, " +
42 "Address: {3}, Telephone: {4}", uniqueID, name, surname,
43 address, telephone);
44 }
45
46 int fieldCount = reader.FieldCount;
47 Console.WriteLine();
48 Console.WriteLine("There are {0} columns!", fieldCount);
49 Console.WriteLine();
50
51 string columnName = reader.GetName(1);
52 Console.WriteLine("The second column's name is: {0}",
53 columnName);
54 Console.WriteLine();
55
56 conn.Close();
57 }
58 catch (OleDbException odbe)
59 {
60 Console.WriteLine(odbe.Message);
61 }
62 }
63 }
64 }
Lines 51 to 54 have been added to the previous example. The output looks as follows:
ID: 1, Name: Angelique, Surname: Kolle, Address: 58 First Ave, Alberton North,
Telephone: 0735149000
ID: 2, Name: Brian, Surname: Scott, Address: 12 Peach Str, Primrose,
Telephone: 0825055972
ID: 3, Name: Kim, Surname: Crous, Address: 109 West Str, Johannesburg,
Telephone: 0765894258
ID: 4, Name: Bradley, Surname: Smith, Address: 23 Seventh Ave, Sandton,
Telephone: 0796584123
The column names can be retrieved using a SQL connection in exactly the same way as
with the OleDb connection (as shown above). Use the example in section 4.8.11 and add
the GetName() property.
Please take note that although the INSERT, UPDATE, and DELETE statements follow one
after the other, they have to be executed separately. In order to achieve this, simply
comment out the two statements that are not being used at a particular time.
The following example shows how a record can be inserted into the database using an MS
Access connection:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace ManipulatingDataExample
{
class Program
{
static void Main(string[] args)
{
try
{
string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=..\..\Salon.accdb";
OleDbConnection conn = new OleDbConnection(connString);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (OleDbException ole)
{
Console.WriteLine(ole.Message);
}
}
}
}
Remember that when a database is added to a project, a copy of the database is made in
the project directory. Thus, any changes made to the database in the project will not be
reflected in the original; they will be reflected in the database attached to the project.
To be able to see what changes have occurred in the Salon database, the database can
be opened in Visual C#.
Double-click on Salon.accdb in the Solution Explorer on the right side of the screen.
The Database Explorer will open on the left side of the screen where the Toolbox is
usually situated.
Right-click on the Client table and select the Retrieve Data option.
A new tab will open that displays all the data in the table. Although nothing was displayed
on the console, notice that a new record has been added, the second record’s address
has changed, and the fourth record has been removed.
From the perspective of the application, you can see that the DELETE and UPDATE
statements function in much the same way as the INSERT statement demonstrated in the
example above.
Always remember to establish the connection to the specified database and to close it
again when all desired operations are concluded.
Please take note that although the INSERT, UPDATE, and DELETE statements follow one
after the other, they have to be executed separately. In order to achieve this, simply
comment out the two statements that are not being used at a particular time.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace SqlConnectionApplication
{
class Program
{
static void Main(string[] args)
{
string stringConn = @"Integrated Security=SSPI;
Initial Catalog=Salon;
Data Source=localhost";
SqlConnection sqlConn = new SqlConnection(stringConn);
try
{
sqlConn.Open();
cmd.ExecuteNonQuery();
}
catch (SqlException ole)
{
Console.WriteLine(ole.Message);
}
finally
{
sqlConn.Close();
}
}
}
}
Notice that the table is modified just as it was in the previous example with the MS Access
database. To see the changes, open Microsoft SQL Server Management Studio and
select all the values in the table.
Once the result of a query has been loaded into a DataSet, the database connection can
safely be closed. This makes the DataSet component very resource-efficient, as it does
not require a continuous connection to the database. A side effect of this is that any
changes made to the contents of the DataSet will not be reflected in the database unless
an update is explicitly specified.
DataSource DataSet
DataSource
DataSource reconnected
disconnected
Data changes
DataAdapter made in
dataset without
affecting data
source.
Figure 4.36 represents the connections between a data source, DataAdapter, and
DataSet. A connection is made to the data source, which is used by the DataAdapter
to fill the DataSet. Once the data has been retrieved, the DataAdapter will disconnect
from the data source and the connection can safely be closed. If the content of the
DataSet needs to be saved back to the data source after the connection has been
closed, it will be necessary to reconnect.
The example below connects to the MS Access database that has been manipulated
(4.8.14), retrieves data using the DataAdapter, and fills the DataSet:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.OleDb;
7
8 namespace DataSetExample
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 try
15 {
16 string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
17 Data Source=../../Salon.accdb";
18 OleDbConnection conn = new OleDbConnection(connString);
19 conn.Open();
20
21 // Creates an empty DataSet.
22 DataSet ds = new DataSet();
23
24 // Creates a DataAdapter that queries the database.
25 OleDbDataAdapter dba = new OleDbDataAdapter
26 ("SELECT * FROM Client", conn);
27
28 // DataSet is filled with the data retrieved by the
29 // DataAdapter query.
30 dba.Fill(ds, "Client");
31
32 // Creates a DataTable object.
33 DataTable dt = ds.Tables["Client"];
34
35 // Displays the data in the DataSet one row at a time.
36 foreach (DataRow client in dt.Rows)
37 {
38 Console.WriteLine("{1} {0}", client["Name"],
39 client["Surname"]);
40 }
41
42 Console.WriteLine();
43 }
44 catch (OleDbException ole)
45 {
46 Console.WriteLine(ole.Message);
47 }
48 }
49 }
50 }
Lines 16 to 19 establish and open the connection to the Salon database. An empty
DataSet is created on line 22, while the DataAdapter specifies the query sent to the
database on lines 25 and 26. Line 30 fills the DataSet. The DataTable object is
created on line 33 to add the DataSet. Lines 36 to 40 loop through the DataTable to
read all the rows present and displays each one as it is read.
As previously explained, any information changed will not be sent to the database. In
order to send changes to the database, an UPDATE statement must be used. The result of
the example will be:
Kolle Angelique
Scott Brian
Crous Kim
Kruger Bob
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace SqlConnectionApplication
{
class Program
{
static void Main(string[] args)
{
string stringConn = @"Integrated Security=SSPI;
Initial Catalog=Salon;
Data Source=localhost";
try
{
sqlConn.Open();
Console.WriteLine();
}
catch (SqlException se)
{
Console.WriteLine(se.Message);
}
}
}
}
Kolle Angelique
Scott Brian
Crous Kim
Kruger Bob
Notice that the connection path is the same as in the example where new data was
inserted. In this example, the database is updated so the same connection path is
needed. When selecting data from the database, the normal path is not required. The
following example searches for existing data to update, adds a new record, and deletes a
record. The previous example is used with some changes:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.OleDb;
7
8 namespace DataSetExample
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 try
15 {
16 string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
17 Data Source=..\..\Salon.accdb";
18 OleDbConnection conn = new OleDbConnection(connString);
19 conn.Open();
20
21 // Creates an empty DataSet.
22 DataSet ds = new DataSet();
Note that lines 16 to 30 are the same as in the previous example and continue again on
line 66, but lines 32 to 64 have been added.
An extra loop has been created to show what the table contains before the last record is
deleted and after the record has been deleted. Line 32 creates a DataColumn which can
store two values. Remember that when incrementing, start at zero. Line 33 stores names
within the first value. Line 34 makes the first value the primary key going forward. The
result will be as follows:
Kolle Ang
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
Kolle Ang
Scott Brian
Crous Kim
Kruger Bob
Notice that when the application is run, the first record is updated and the last record is a
new entry. The last record (the new entry) is then deleted.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.SqlClient;
7
8 namespace SqlConnectionApplication
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 string stringConn = @"Integrated Security=SSPI;
15 Initial Catalog=Salon;
16 Data Source=localhost";
17
18 SqlConnection sqlConn = new SqlConnection(stringConn);
19
20 try
21 {
22 sqlConn.Open();
23
24 // Creates a DataAdapter that queries the database.
87 {
88 sqlConn.Close();
89 }
90 }
91 }
92 }
The only lines in the code example which differ from the previous example are lines 14 to
26. Although lines 24 to 26 are very similar, remember that the OleDbDataAdapter
becomes the SqlDataAdapter when connecting to a SQL database. The output looks
exactly the same as the output from the previous example.
4.8.16.5 Updating the data source with the DataSet using MS Access
Use the OleDbCommandBuilder when performing a simple update to the database. The
example from section 4.8.16.3 is used but it contains a few modifications:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.OleDb;
7
8 namespace DataSetExample
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 try
15 {
16 string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
17 Data Source=..\..\Salon.accdb";
18 OleDbConnection conn = new OleDbConnection(connString);
19 conn.Open();
20
21 // Creates an empty DataSet.
22 DataSet ds = new DataSet();
23 // Creates a DataAdapter that queries the database.
24 OleDbDataAdapter dba = new OleDbDataAdapter
25 ("SELECT * FROM Client", conn);
26 // DataSet is filled with the data retrieved by the DataAdapter
27 // query.
28 dba.Fill(ds, "Client");
29 // Creates a DataTable object.
30 DataTable dt = ds.Tables["Client"];
31
32 DataColumn[] cols = new DataColumn[1];
33 cols[0] = dt.Columns["name"];
34 dt.PrimaryKey = cols;
35
36 // OR USE THE FOLLOWING TO CREATE A PRIMARY KEY:
37 // dt.PrimaryKey = new DataColumn[] {dt.Columns["name"]};
38
39 // Searches for the Angelique record and changes it to Ang.
40 DataRow angeliqueRow = dt.Rows.Find("Angelique");
41 angeliqueRow["name"] = "Ang";
42
43 // Creates a new row, sets the column’s values, and adds the
44 // record to the DataSet.
45 DataRow clientRow = dt.NewRow();
46 clientRow["name"] = "Martie";
47 clientRow["surname"] = "Laurens";
48 clientRow["address"] = "12 Peach Str";
49 clientRow["telephone"] = 0821235678;
50 dt.Rows.Add(clientRow);
51
52 OleDbCommandBuilder cmdBuilder = new OleDbCommandBuilder(dba);
53
54 dba.Update(ds, "Client");
55
56 // Displays the data in the DataSet one row at a time.
57 foreach (DataRow client in dt.Rows)
58 {
59 Console.WriteLine("{1} {0}", client["Name"],
60 client["Surname"]);
61 }
62
63 Console.WriteLine();
64 conn.Close();
65 }
66 catch (OleDbException ole)
67 {
68 Console.WriteLine(ole.Message);
69 }
70 }
71 }
72 }
The first thing to notice is that the Delete() method from the previous example has been
removed because it is not required in this example. Lines 52 to 54 in this example have
replaced the Delete() method from the previous example. The
OleDbCommandBuilder communicates with the DataAdapter, which creates a
connection with the database and the Update() method on line 54 changes the new
record which is created on lines 45 to 49. The output of the above example should look as
follows:
Kolle Ang
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
When updating, deleting, selecting, or inserting data into a data source with a DataSet,
the commands have to be specified along with the parameters that must update the
database. The following code snippet displays how the Update() and Delete()
commands are used instead of the CommandBuilder with a DataSet when using an MS
Access database:
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Data;
6 using System.Data.OleDb;
7
8 namespace DataSetExample
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 try
15 {
16 string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;
17 Data Source=..\..\Salon.accdb";
18 OleDbConnection conn = new OleDbConnection(connString);
19 conn.Open();
20
21 // Creates an empty DataSet.
22 DataSet ds = new DataSet();
23 // Creates a DataAdapter that queries the database.
24 OleDbDataAdapter dba = new OleDbDataAdapter
25 ("SELECT * FROM Client", conn);
26 // DataSet is filled with the data retrieved by the DataAdapter
27 // query.
28 dba.Fill(ds, "Client");
29 // Creates a DataTable object.
30 DataTable dt = ds.Tables["Client"];
31
32 DataColumn[] cols = new DataColumn[1];
33 cols[0] = dt.Columns["name"];
34 dt.PrimaryKey = cols;
35
36 // UPDATE.
37 DataRow angeliqueRow = dt.Rows.Find("Angelique");
38 angeliqueRow["name"] = "Ang";
39
40 OleDbCommand upCmd = new OleDbCommand(@"UPDATE Client
41 SET surname = @surname
42 WHERE name = @name",
43 conn);
44
45 upCmd.Parameters.Add("@surname", OleDbType.VarChar, 20,
46 "Surname");
47 upCmd.Parameters.Add("@name", OleDbType.VarChar, 20, "Name");
48
49 dba.UpdateCommand = upCmd;
50
51 // DELETE.
52 dt.Rows[0].Delete();
53
54 OleDbCommand delCmd = new OleDbCommand(@"DELETE FROM Client
55 WHERE name = @name",
56 conn);
57
58 delCmd.Parameters.Add("@name", OleDbType.VarChar, 20, "Name");
59
60 dba.DeleteCommand = delCmd;
61
62 dba.Update(ds, "Client");
63
64 // Displays the data in the DataSet one row at a time.
65 foreach (DataRow client in dt.Rows)
66 {
67 Console.WriteLine("{1} {0}", client["Name"],
68 client["Surname"]);
69 }
70
71 Console.WriteLine();
72 conn.Close();
73 }
74 catch (OleDbException ole)
75 {
76 Console.WriteLine(ole.Message);
77 }
78 }
79 }
80 }
Delete lines 43 to 54 from the previous MS Access example in this section and replace
them with lines 40 to 62 from this example.
Comment out the section of code which will delete a record (lines 51 to 62).
This is done to see the effect of the UPDATE statement. The result should look as follows:
Kolle Ang
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
It is clear that the first record “Kolle Ang” was deleted. Please note that in order to run this
application again, the record will have to be recreated in the database. It is possible to run
the update and delete sections of code at the same time without having to comment out
any code, but then only the second output will be seen as and the first output is done in
the background.
Lines 45, 47, and 58 have a property called OleDbType. This is used to determine the
type of data that has to be entered into the database. In this case VarChar was used
which evaluates to a string. Any other data type can be specified here. The rest of the
code is quite self-explanatory.
4.8.16.6 Updating the data source with the DataSet using SQL
The examples shown in the previous section are shown again, but the parts that apply to
an MS Access database will be replaced with parts that apply only to SQL databases. The
first example uses CommandBuilder, whereas the second example uses the UPDATE
and DELETE methods.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace SqlConnectionApplication
{
class Program
{
static void Main(string[] args)
{
string stringConn = @"Integrated Security=SSPI;
Initial Catalog=Salon;
Data Source=localhost";
try
{
sqlConn.Open();
angeliqueRow["name"] = "Ang";
// Creates a new row, sets the column’s values, and adds the
// record to the DataSet.
DataRow clientRow = dt.NewRow();
clientRow["name"] = "Martie";
clientRow["surname"] = "Laurens";
clientRow["address"] = "12 Peach Str";
clientRow["telephone"] = 0821235678;
dt.Rows.Add(clientRow);
dba.Update(ds, "Client");
Console.WriteLine();
}
catch (SqlException se)
{
Console.WriteLine(se.Message);
}
finally
{
sqlConn.Close();
}
}
}
}
Kolle Ang
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
Note that the same lines that were commented out in the previous example (section
4.8.16.5) must also be commented out here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace SqlConnectionApplication
{
class Program
{
try
{
sqlConn.Open();
// UPDATE.
DataRow angeliqueRow = dt.Rows.Find("Angelique");
angeliqueRow["name"] = "Ang";
dba.UpdateCommand = upCmd;
// DELETE.
dt.Rows[0].Delete();
dba.DeleteCommand = delCmd;
dba.Update(ds, "Client");
Console.WriteLine();
}
catch (SqlException se)
{
Console.WriteLine(se.Message);
}
finally
{
sqlConn.Close();
}
}
}
}
The output of the above example is as follows (with the DELETE section commented out):
Kolle Ang
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
Uncomment the DELETE section and comment out the UPDATE section.
The example has the following output for the UPDATE section:
Scott Brian
Crous Kim
Kruger Bob
Laurens Martie
Note that the SqlDbType property in the SQL connection replaces the OleDbType
property in the MS Access connections.
There are five special characters which are used to define tags in XML. As such, these
characters cannot be used to define entity names or values. These need to be replaced
with an entity reference. The five pre-defined entity references are listed in Error!
Reference source not found.:
Table 13 – Special characters in XML
Special characters
Character Meaning Entity reference
< less than <
> greater than >
& ampersand &
" apostrophe '
' quotation mark "
4.8.17.1 Reading data from a DataSet and writing it as XML using MS Access
It is possible to write an XML representation of data within a DataSet. The data can be
written with or without its schema information. The schema information contains the table
definition of the DataSet as well as the constraint definitions. It is then written in XML
Schema definition language (XSD).
The GetXml() method returns the XML representation without schema information. In
order to include the schema information, the GetXmlSchema() method is used.
The following example incorporates both the GetXml() and GetXmlSchema() methods:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace XMLDataSetExample
{
class Program
{
static void Main(string[] args)
{
try
{
OleDbConnection conn = new OleDbConnection(@"
Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=..\..\Salon.accdb");
conn.Open();
conn.Close();
}
catch (OleDbException ole)
{
Console.WriteLine("Error {0} occurred!", ole);
}
}
}
}
4.8.17.2 Reading data from a DataSet and writing it as XML using SQL
The same XML methods that were used in the previous section (4.8.17.1) will be used in
the SQL connection:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace XMLDataSetExample
{
class Program
{
try
{
sqlConn.Open();
adap.Fill(ds, "Client");
A new xml file has been created in the same folder as the text file as shown in Figure 4.37:
Right-click on the xml file and select Edit. The file will open like a text file.
Enter the following code into the file.
<Age>21</Age>
</Item>
<Item>
<Id>9605124589658</Id>
<Name>Brad</Name>
<Age>12</Age>
</Item>
</GymMembers>
The file should open in Internet Explorer and it should look like the output shown in
Figure 4.38:
Create the .xsd (XML schema) file in the same way that you created the .xml file.
The file will open in Microsoft Visual Web Developer. The following code can be entered
there:
<xs:choice maxOccurs="unbounded">
<xs:element name="Item">
<xs:complexType>
<xs:sequence>
<xs:element name="Id" type="xs:decimal" minOccurs="0" />
<xs:element name="Name" type="xs:string" minOccurs="0" />
<xs:element name="Age" type="xs:int" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace ReadXmlExample
{
class ReadXmlWriteData
{
static void Main(string[] args)
{
ReadXmlWriteData rxwd = new ReadXmlWriteData();
rxwd.MyXmlRead();
}
/* Goes through each table in the DataSet, and then each row
printing the values for each record */
foreach (DataTable table in dataset.Tables)
{
Console.WriteLine("*****" + table.TableName + "*****");
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
*****Item*****
8901230858087 Angelique 19
8711042584569 Brian 21
9605124589658 Brad 12
Note that ReadXml and ReadXmlSchema methods are overloaded, so they can be used
to read from various sources.
4.8.13 Exercises
1. What is the function of the DataReader object?
2. Which two namespaces are used with ADO.NET?
3. What is the function of the OleDbDataReader object?
4. What is the function of the DataSet object?
5. What does the acronym XML stand for?
6. Create an application in which a user can enter the details of new
students using TextBox controls. Each student’s name, address,
age, gender, and telephone number must be included. These values
should be checked to ensure that they are the correct type before
they are inserted into the database.
7. Create another application which uses the same database. This
application must allow the user to search for students by their name
or gender. A ComboBox must be used to make the selection, and the
result must be displayed in a ListBox control.
The questions in this section are similar to those asked in the exam. Try answering these
questions and then check the answers with the instructor. The questions are taken from
the study guide and textbook. The questions comprise theory and application questions
which will be in multiple choice, multiple response, true/false, and selection formats. Allow
about 20 minutes for all the questions. Good luck!
Questions
True/False
Multiple Choice
1. Which one of the following best describes the function of this piece of code?
using System;
using System.IO;
a. The code writes the numbers 0 to 100 to a new file called TheFile.txt.
b. The code writes the numbers 1 to 100 to an existing file called TheFile.txt.
c. The code writes the numbers 0 to 99 in binary to a new file called TheFile.txt.
d. The code writes the numbers 1 to 99 in bytes to a new file called TheFile.txt.
while (read.Read())
{
Console.WriteLine(read.GetString[0]);
}
a. The code will print out details of all the plants in the database that have a summer
season.
b. The code will print out names of all the plants in the database that have a summer
season.
c. The code will print out the name of the first plant in the database that has a
summer season.
d. The code will print out details of the last plant in the database that has a summer
season.
4. Which property of the FileInfo class is used to find out the size of a specific file?
a. Size
b. Length
c. FileSize
d. TotalBytes
Multiple Response
1. Which three of the following should be considered when improving the performance of
an application using the .NET Framework?
a. Ensure the form is as small as possible.
b. Unnecessary boxing and unboxing.
c. Using the AddRange() method.
d. When concatenating and manipulating complex strings the StringBuilder class
should be used.
e. Keeping all code in one class instead of many.
Unit 5 – ASP.NET
This unit introduces ASP.NET and the Visual Web Developer Express IDE.
This unit counts 10% towards part B of the C# mark, and there are 12 days to complete it.
The time and marks are scheduled as follows:
Reading 10 days
Exam preparation and exam 2 days 10%
ASP.NET is the successor to Microsoft’s original ASP (Active Server Pages). ASP.NET
implements the Common Language Runtime (CLR). As such, it can execute code written
in any language in the .NET Framework, which includes both VB.NET and C#.
This concept may seem somewhat confusing at this point; it will be far easier to
understand with some practical experience.
5.1.3 Exercises
1. Name two other systems which share similarities with ASP.NET.
2. What does PHP stand for?
3. What does ASP stand for?
Insert the Visual Studio Express Editions disk into the DVD-ROM drive.
In Windows Vista, a dialog appears which asks if the disc must be auto-played ‘setup.hta’.
Click Start.
Open All Programs.
Select Microsoft Visual Web Developer 2008 Express Edition.
The Visual Web Developer Express interface functions in much the same way as the other
Visual Studio Express environments.
Click OK.
The XHTML code displayed in the window will be familiar to those who understand HTML
code. However, knowledge of this code is not necessary to work with the IDE. Visual
Web Developer Express, much like Visual C# Express, provides a Design view which is
used to create the interface visually.
To switch to the Design view, click the Design tab in the bottom left-hand corner (as
shown in Figure 5.5.)
The Design view will be blank initially. This is because the Web page does not have any
content yet.
Click anywhere inside the window and type the text “Hello, World!”
Now save the project (File > Save All or <Ctrl> + <Shift> + <S>).
By default, ASP.NET Web pages are run without debugging. This is because debugging
uses up additional system resources which can slow the server down. However, in a
development or testing environment running the application in debugging mode is
essential.
Depending on the browser settings, the dialog presented in Figure 5.7 may, or may not, be
seen:
This dialog indicates that script debugging is disabled in the Internet Explorer browser.
This is not a problem.
The Web page should now open in Internet Explorer as shown in Figure 5.8:
A new icon will be displayed in the right hand side of the taskbar. This icon is shown in
Figure 5.9:
This icon indicates that Visual Web Developer Express is currently running a Web server.
This server will not automatically close unless:
This toolbar strongly resembles those used by other editing applications such as Microsoft
Office and OpenOffice. The functionality is also much the same. For example, to change
the alignment of text (or any other content), the Justification button can be used, as
shown in Figure 5.11.
Similarly, Figure 5.12 demonstrates how the font can be changed using the drop-down
menus:
Select the document itself by clicking in any empty part of the document.
Click the Background Color button.
Similarly, the Foreground Color button allows the foreground colour to be changed. In
most cases the term ‘foreground’ refers to the text.
To change the Title (i.e. what is displayed in the title bar of the Web browser) of a Web
page:
Spend some time experimenting with the different options to gain experience with
editing Web page documents in Visual Web Developer Express.
In the past, CodeBehind pages had to be created manually. However, with the advent of
Visual Web Developer, these pages are now automatically created for every page.
CodeBehind pages written in C# have the extension .cs.
In this guide, CodeBehind pages will be used frequently to provide functionality for
ASP.NET pages.
5.2.7 Exercises
1. Briefly explain the concept of a CodeBehind page.
2. Which keyboard shortcut is used to run an ASP.NET project?
3. Which view is used to create ASP.NET pages using a visual
interface?
Ensure that the Toolbox is open (if it is not, click View > Toolbox).
If necessary, switch the editor window to the Design view.
NOTE Controls can still be added (and modified) in the Source view. Those
comfortable with HTML concepts are free to do so. However, this course will
only cover the use of the Design view.
Click on the desired control in the Toolbox and drag the control to the desired position
as shown in Figure 5.13.
Take a look at the Button control (Figure 5.14) that was just added, in detail:
The Button control should be selected. If it is not, it can be selected it by clicking on it.
The text asp:button#Button1 will be seen. This text indicates two things:
The ID of a control is used to keep track of that control, and so that it may be referred to
later when writing code. As with a standard Visual C# application, always rename the
controls to a unique, descriptive name (via the ID property).
Properties were defined and explained in units 1 and 2 and these are much the same as
those shown in Figure 5.15. Properties may be of any type (i.e. int, string, collections,
any object). For example, the ID property of a control will expect a string value, while
the Visible property takes a bool value).
The first property of any control that should be modified is the ID property. This property
has the same purpose as the Name property in a standard Visual C# application. In this
case, the control will be renamed to TestButton.
The next property which will be changed is the Text property. This property controls the
text which is displayed on the button.
There are many ASP.NET controls, each of which has their own unique functionality and
properties. However, there are several properties which are common to most, if not all,
controls and these are displayed in Table 13:
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using System.Data;
{
protected void Page_Load(object sender, EventArgs e)
{
The class above (most of which has automatically been generated by Visual Web
Developer Express) is derived from System.Web.UI.Page which represents an
ASP.NET page. As with Visual C# forms, this class is defined as being partial. The
rest of the class is defined in the .aspx document itself.
5.3.2.2.1 Page_Load
Another event-handler defined as Page_Load can be seen inside the class declaration.
This is an event that belongs to the page itself (as opposed to a control) and is called
when the ASP page is loaded. This event-handler is generally used to set up the page as
necessary, such as to load information from a database or text file, check to see if a user
is logged in, or dynamically set the content of lists and other controls.
Most controls have events which are specific to them. The events listed in Table 14 are,
however, common to all controls.
Text in a Label can be changed by modifying the Text property of the Label control.
Not only may the text be changed but the font colour, background colour, font, and visibility
can all be altered as well through the respective properties.
Figure 5.20 shows some of the properties being applied to a TextBox control:
If this menu is hidden and needs to be accessed again, simply click the small arrow button
on the right hand side of the control (the same button can be used to hide the menu if it is
already visible). There are three options available here:
Once the changes have been made, click the OK button to confirm the changes. If it is
necessary to revert to the previous state (i.e. before the dialog was opened), click Cancel.
When a RadioButtonList is added to an ASP.NET page, the same menu which was
used to work with the DropDownList control will be shown (and can also be shown again
later). The functionality is identical in both cases.
Figure 5.25 below shows what the RadioButton controls / RadioButtonList control
looks like in action:
It should also be noted that (as with almost any visual control) there are properties to
modify the font, background colour, and foreground colour.
The items in the CheckBoxList can be edited in exactly the same way as items in a
RadioButtonList or DropDownList would be edited. However, because the user can
select multiple values (as shown in Figure 5.27), the way in which values are determined
differs from all the controls explained previously.
To determine whether a particular check box is checked the Items property of the
CheckBox control itself needs to be accessed. For example, to determine if the first box is
checked, the following code would be used (note that the Selected property is used in
place of the Checked property):
if (myCheckListBox.Items[0].Selected)
{
// Execute some code.
}
Likewise, if it is necessary to check the first box (without the user clicking on it), the
following code can could be used:
myCheckListBox.Items[0].Selected = true;
In order to set which image an ImageButton control uses, the ImageUrl property needs
to be used. However, before specifying which image to use, the image must be added to
the website project.
The image is copied into the website directory and will now show up in the list when
specifying which image to use for the ImageButton control’s ImageUrl property. Note
that this procedure can be used to add images to the website for any purpose.
As with any other control, should the size of an ImageButton need to be changed (i.e.
scale the image up or down), simply change Height and/or Width properties of the
ImageButton.
Panel controls (like all controls) have a property called Visible, which sets whether or
not the panel can be seen. When a panel is hidden, all of the controls displayed within it
are hidden as well.
Calendar controls are very customisable. By modifying one of the many properties of a
Calendar control, a calendar which matches the theme of the Web pages can be created
quite simply. Several pre-designed templates can also be selected using the Auto
Format… option which can be found in the Calendar Tasks menu. As with several other
control types, the Tasks menu can be opened by clicking on the small arrow button on the
top right-hand side of the control as shown in Figure 5.30:
Event-handlers can be created to handle the SelectionChanged event for this control if
it is necessary to perform any operation when the user selects a date.
This creates a default table with three rows and three columns. The area within the table
cells can be worked in the same way as anywhere else in the document, including the
addition of controls. To resize a column or row, simply click on the border and drag it in
the desired direction.
Columns and rows can be added or removed. To do this, simply right click inside a table
cell. This brings up a menu which allows for insertion of new rows or columns, deletion of
the table, selection of different parts of the table, or modification of parts of the table. The
options available in this menu are fairly self-explanatory. For example, clicking on the
Insert > Column to the Left option adds a new table column to the left of the currently
selected cell.
HTML tables created in Visual Web Developer are by default set to take up the entire
available width. This can be changed by modifying the Style property of the table.
NOTE Those who have previous experience creating HTML Tables might be more
comfortable creating them in the Source view.
Figure 5.31 shows the menu which is displayed when right-clicking inside a table cell:
Figure 5.32 shows how a table can be used to create a professional looking layout (in this
case, for a user registration form).
Knowledge of how to create and modify HTML tables will be expected for both the exams
and project, so experiment with them until a measure of comfort with their use in Web
pages is attained.
5.3.5 Exercises
1. Briefly explain the benefits of using an HTML table in an ASP.NET
page.
2. Briefly explain how the AutoPostBack property works.
3. Briefly explain what an ASP.NET control is.
5.4.1 Validation
On many websites (especially those with active content, such as PHP or ASP.NET), data
needs to be obtained from the users for purposes of registration, confirmation, etc.
However, there is no guarantee that the user will always enter the required information,
nor is there any guarantee that it will be entered correctly. For this reason, entered data
should always be validated. There are many methods of validation, such as checking to
see if the user has left a certain field blank, to more complicated checks such as
determining if a date or email address is valid.
ASP.NET introduced a new concept: validation controls. These controls, which can be
added to ASP.NET websites much like any other controls, validate data on the client side,
before the data is sent to the server. If necessary, data can be further validated on the
server (for example, on a login page where the username and password need to be
checked against entries in a database). Each validation control validates a specific control
on the page.
Validation controls appear to the user as error messages (which are only shown should
the data validation fail), so place them accordingly. To set a control to be validated, the
ControlToValidate property needs to be set to the ID of that control. To set which text
is displayed if an error occurs, modify the ErrorMessage property. As with labels, the
font and colour can be changed as required.
Create a new project. This project will be used for the rest of this section.
An HTML table with four columns (one is used as a space between the textboxes and
their descriptions) has been used to create the layout.
One TextBox control is called NameTextBox and the second SurnameTextBox.
The two RequiredFieldValidators have had their ControlToValidate
properties set to the ID of the appropriate control. They have also had their
ErrorMessage and ForeColor properties changed.
The ID for the Submit Button has been changed to SubmitButton. The
SubmitButton does not need any event-handlers in order to trigger validation.
Now run the page and click the Submit button without entering any data.
Notice from Figure 5.33 that only the RequiredFieldValidator error messages are
visible. This is because nothing is sent to the server until validation has been completed.
Figure 5.34 shows how the form looks after data has been entered and SubmitButton
has been clicked:
The image is an Image control with its ImageUrl property set to use the sample
image. The text in the image is Qx4B2P.
The CompareValidator control has its ControlToValidate property set to
imageVerificationTextBox, and its ValueToCompare property set to Qx4B2P.
5.4.3.2.2 Comparing the value in one control with the value in another
In addition to comparing the input by the user against a specific value, the
CompareValidator control can also be used to check to see if the value in one control
matches the value in another. This is commonly used to get the user to confirm a data
field, such as an email address or password.
Figure 5.36 shows how a CompareValidator can be used to compare control values:
The ControlToCompare property is used in this case. The validation control compares
the value of its ControlToValidate against the value of its ControlToCompare to
determine if they are the same.
A RangeValidator control can compare values of various data types, namely: String,
Integer, Double, DateTime, and Currency. The data type which the control is
checking is specified by its Type property.
The range which the control uses is specified by its MinimumValue and MaximumValue
properties.
In the following example (Figure 5.37), the Type for RangeValidator has been set to
Integer, the MinimumValue has been set to 13 and the MaximumValue has been set
to 110:
The controls in Figure 5.40 have been added to the form between the Age and Image
verification fields (refer to Figure 5.41). The values in the CheckBoxList have added
using the Edit Items… dialog, and the CustomValidator has not had its
ControlToValidate property set. A CheckBoxList control cannot be validated
using standard validation methods and an Exception will be thrown if this is attempted.
The solution is to use a custom validation procedure.
Note that if args.IsValid is false, the error message will be displayed to the user. If it
is true, no message will be displayed. When this Web page is run and the user selects
fewer than two newsletters to subscribe to, then the error message will be displayed.
However, it is also evident that the button text still changes to Success, even though
validation for the CustomValidator failed. This is because CustomValidators are
evaluated server-side (unlike other validation controls), which means that the page is sent
to the server and event-handlers are processed. However, ASP.NET does account for
this.
The Page object (which is part of every ASP.NET page) contains a property called
IsValid. This property has a value of true only if every validation control in the page
successfully validates their data. If any data fails validation, the IsValid property will be
false. This property can be checked at any time to determine whether or not the page
has passed validation.
Modify the SubmitButton control’s event-handler so that it looks like the following:
Note that any server-side validation (i.e. the CustomValidator control) will not be
performed until all other validation is successful.
This control is very easy to use, since all that needs to be done is to insert it into the form
in the desired location (which will usually be above the form), and specify its HeaderText
property. The HeaderText property specifies which text should be displayed before
listing any validation errors.
Should it be necessary to only display errors in the ValidationSummary control (and not
anywhere else), then each of the other validation control’s Display properties must be
set to None. The error messages will then not be displayed on the page, but will still set to
the ValidationSummary control.
Having more than one validation control for a specific field can throw the page layout out of
alignment. To fix this, set the Display properties for each control to Dynamic. Naturally,
this problem does not occur if the errors are only displayed in a ValidationSummary
control (i.e. the Display property for the control is already set to None).
Figure 5.43 shows the form (in Design view) with RequiredFieldValidators added for
each field except for the CheckBoxList.
5.4.4 Exercises
1. Briefly describe the reasons for data validation.
2. Describe two uses for a CompareValidator control.
3. Which property is used to determine if all the data on a page was
successfully validated?
5.5 Data-binding
ListBox
DropDownList
RadioButtonList
CheckBoxList
Create a new project. This project will be used to experiment with data-binding.
Add a CheckBoxList control to the default page. Give the ID a value of
TestCheckBoxList.
Open the CodeBehind page and type the following code in the Page_Load event-
handler:
As can be seen, data-binding is very easy to use. All that needs to be done is to get the
data into a collection, and then bind it to the desired list control.
5.5.2.2 PostBack
Add a Button control to the page.
Save and run the project.
Check a few items in the list and click the Button.
Notice how the selections that have been made are lost. This is because, technically, the
list is cleared and recreated each time the page is reloaded. Fortunately, ASP.NET has
functionality which can be used to avoid this.
TestArrayList.Add("Item One");
TestArrayList.Add("Item Two");
TestArrayList.Add("Item Three");
TestArrayList.Add("Item Four");
TestArrayList.Add("Item Five");
TestCheckBoxList.DataSource = TestArrayList;
TestCheckBoxList.DataBind();
}
}
Now, if selections are made in the list and the Button is clicked, those selections will not
be removed because the list is no longer recreated each time the page is reloaded.
As seen from the above example, the Page object contains a property called
IsPostBack. This property will return false the first time a page is loaded; thereafter it
will return true. This property can therefore be used to check if it is necessary to load
any data and perform data-binding and not have to worry that the code will be called
multiple times.
This dialog asks if the programmer wants to place the class source code file (.cs) in the
App_Code directory. Placing a class in this directory makes it accessible in any of the
pages for the website.
Click Yes.
Now code the class as per usual. For this example, use the following code:
/*
* The 'Product' class
* Description: A class which stores basic information about a product.
*/
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
This code creates a very basic Product class which can be used to store information
about one specific product. This class can now be used with data-binding.
// Data-bind.
TestCheckBoxList.DataSource = TestArrayList;
TestCheckBoxList.DataBind();
}
}
Save and run the project. The result should look as follows (Figure 5.46):
As can be seen from the above example, binding a collection of objects to a list is very
similar to binding a collection of type string. The main difference is in the use of the
DataTextField property for the TestCheckBoxList control. This property specifies
which of the object’s properties must be bound to the control.
The data-bound controls covered in this guide are summarised in Table 24:
All of these controls can be found in the Toolbox in the Data section.
5.5.4.1 GridView
The GridView control is a powerful control used to display data in a tabular format.
Columns are automatically generated based on the data source for the GridView. When
a GridView control is added to a page, the GridView Tasks menu will be shown. This
menu functions in much the same way as Tasks menus previously covered. However, the
options presented here are different, as shown in Figure 5.47:
The first option, Auto Format… allows a template to be chosen (from a list) which
specifies how the control should look. Should more control be needed over the
appearance of the GridView control, its properties can also be modified.
The second option, Choose Data Source: allows a data source to be chosen from a list of
sources which have already been added to the website, such as a database or XML file.
However, at this point the list will be empty.
Before continuing, try adding a GridView control to the page and binding it to the
TestArray. The table displayed in Figure 5.48 should be seen:
The third option in the Tasks menu, Edit Columns… opens a dialog called the Fields
dialog (Figure 5.49).
This is tool is similar to the Edit Items dialog which is available for list controls, but it is far
more powerful. By default, a GridView control will automatically generate columns based
on the data source to which it has been bound. In situations where the exact structure of
the data source is not known, these automatically generated columns will most likely be
sufficient. However, programmers and designers will usually want to specify their own
layouts.
Continuing with the product list, it might not, for example, be necessary for the Id column
to be visible. In this case, the auto-generation of columns would need to be disabled.
Remove the check in the Auto-generate fields check box (in the lower left-hand side
of the Fields dialog).
Now, because the fields are no longer generated automatically, the Description and Price
columns must be generated manually (or else the GridView control will have nothing to
display). There are many types of fields (columns in a GridView control) to choose from.
Table 25 shows some of these fields and what they are used for:
Using the above fields can become quite complicated, especially for those who have not
used them before.
The Description and Price fields are both text and should thus both be of the
BoundField type.
The field properties will now be seen on the right-hand side of the dialog. These
properties are used to customise the appearance and functionality of the BoundField.
The fourth option in the Tasks menu, Add New Column… is a simplified version of the
Fields dialog which is used to add a new column. This dialog is particularly useful for
creating more advanced fields, such as the HyperLinkField or ImageField types, as
it vastly simplifies the process by highlighting important properties.
The last option, Edit Templates, switches the GridView control into template editing
mode. The templates which can be edited define how (a) empty cells look and (b) how the
paging interface looks (should the GridView control use paging. Paging is used to split
large quantities of data into more manageable sections (pages)). To return to the normal
mode, open the Tasks menu and click End Template Editing.
NOTE From this point on, all data-bound controls in examples will be auto-formatted,
using the Professional style where possible. Any format style may be used,
but ensure that it is always eye pleasing and that it fits in with theme for the
rest of the website.
5.5.5 Exercises
1. Name three data-bound controls.
2. Describe two ways of binding a data source to a control.
3. Give two reasons why auto-generation of GridView fields is not
always desirable.
5.6.1 Databases
In Unit 4, opening and using database connections was covered. This knowledge will now
be put into practical use with ASP.NET.
The database will now be displayed in the Solution Explorer (Figure 5.52).
Figure 5.52 – The Solution Explorer after a database has been added
The database has now been copied into the working folder for the website.
NOTE
The original database will not be modified should any changes be made.
Select the Data source (in this case, the Microsoft Access Database File (OLE DB)
will suffice).
Click the Browse button to select the database that has been copied to the App_Data
folder in your project.
Click OK.
The Configure Data Source window shown in Figure 5.53 will appear again.
When the next Configure Data Source window asks Do you want to save the
connection in the application configuration file?, click Yes, save this connection as:
defaultName.
This dialog is used to configure exactly what data the GridView control should display.
The interface may be used to select which fields should be displayed (and in what order),
or a custom SQL statement can be created (which will generally be used for more
complicated queries or in most situations in which the database needs to be modified.).
For this example, the interface will be used.
In the Columns window, click the check box next to * (remember that, in SQL, the
asterisk symbol (*) indicates that all the columns in a table must be selected).
Notice how the SQL statement is created in the lower portion of the screen, in the
SELECT statement: window. In most situations, simply displaying the contents of a table
is not desirable – it will almost always be necessary to display more specific data. The
SQL statement that is generated here (which changes depending on the options and
conditions that are selected) will define what data is available to be worked with.
A window will now be shown which will allow the query to be tested to see whether or not
the results are as expected.
Click Finish.
This example shows how easy it is to connect to a database and display information in
ASP.NET.
Remember that the data source can always be modified as necessary by selecting it in the
design view and expanding its Tasks menu (Figure 5.58):
Figure 5.60 shows what the GridView control will look like when it is run:
Click OK.
Two things have to be entered on this window: the server name and the database name.
The server name is the server on which your MS SQL Server Management Studio is
running. This can be seen when the SQL Server Management is opened
(Figure 5.63).
As soon as the server name is entered, the database name text box will be enabled.
Click on the arrow next to the Select or enter a database name: dropdown list which
will give you a list of databases that exist in the specific server. Ensure that the
database has been created on the PC on which you are working.
Click OK.
The same window as shown in Figure 5.56 (previous section) will appear.
As can be seen, Visual Web Developer has no visual functionality for editing templates
used by a Repeater control. As such, it will be necessary to create these templates in
Source view.
This code should seem reasonably familiar to those with HTML experience. Fortunately
for those without such experience, Visual Web Developer implements a powerful code
completion feature in the Source view. Simply begin typing a tag (indicated by an opening
triangular bracket ‘<’), and a list of tags will be presented from which a selection can be
made.
As can be seen, if an item is selected in the Design view, it will also be selected in the
Source view. This can be useful to help find a specific control without wading through lots
of unfamiliar code. A template will now be created for the repeater control so that data
from the database can be displayed in the desired format.
Select ItemTemplate from the list and press the <Enter> key.
Close the ItemTemplate tag ‘>’.
Visual Web Developer will automatically provide a closing tag for the ItemTemplate.
Anything typed between the opening and the closing tags will be used for every item in the
data source.
While the above example is very basic, it does give an idea of what is possible with a
Repeater control. The XHTML code inside the Repeater control can be as complex (or
as simple) as necessary; it is perfectly possible, for example, to have a complex HTML
table which neatly formats the output.
Those without any HTML coding experience might want to try creating the layout in design
view, selecting it, copying it, and pasting it between the <ItemTemplate> and
</ItemTemplate> tags. All that then needs to be done is to add the data-binding
statements in the correct places. For an example, see Figure 5.69 (Please note that this
example only shows the first 3 items displayed by the Repeater).
The Repeater control should appear as follows (Figure 5.69 only shows the first three
items):
The various styles (e.g: style1, style2, style3) used in the above example were
created automatically by the Visual Web Developer Express IDE.
The output should look like the image shown in Figure 5.70:
The code between the starting and closing tags remains the same as shown below.
Notice that this is the same as binding data to a Repeater control.
</tr>
<tr>
<td class="style1">
Learner DoB:</td>
<td class="style2">
<%# DataBinder.Eval(Container.DataItem, "DateOfBirth") %>
</td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:DataList>
Add a data source in exactly the same way in which one was added to the GridView
and Repeater controls.
Select the Auto Format… option and change the design to Professional.
Save and run the Web page.
The output should look like the image shown in Figure 5.71:
It should be noted that, with a DataList, it is possible to edit any and all templates in the
Design view. Figure 5.72 shows how the header and footer templates can be modified:
It is also possible to create data-bound fields within a template. This is done by adding
any control (for example, a Label) and using the attached Tasks Menu. The Edit
Databindings… option will display a dialog which can be used to select which field to
data-bind. When creating a DataList control, this is generally an easier method than
writing code.
NOTE Any data-binding which has been created using the Source view will not be
visible in the Design view. However, it will be there when the page is
rendered.
Try modifying the DataList control created in this section such that it uses Label
controls (created in the Design view) to display the information about each learner. It
will be necessary to remove any code displayed in between code-render tags to
achieve this effect.
The output should look like the image shown in Figure 5.74:
It should be noted that with a DataList control, it is possible to edit any and all templates
in the Design view. Figure 5.75 shows how the header and footer templates can be
modified:
It is also possible to create data-bound fields within a template. This is done by adding
any control (for example, a Label) and using the attached DataList Tasks menu. The
Edit Databindings… option will display a dialog which can be used to select which field to
data-bind. When creating a DataList control, this is generally an easier method than
writing code.
NOTE Any data-binding which has been created using the Source view will not be
visible in the Design view. However, it will be there when the page is
rendered.
Try modifying the DataList controls created in this section such that it uses Label
controls (created in the Design view) to display the information about each learner. It
will be necessary to remove any code displayed in between code-render tags to
achieve this effect.
For the previous examples in this section, a read-only data source has been used.
However, as it is now necessary to show the full functionality of the ListView control, a
new data source will need to be created.
Create a new data source, following the same steps as in 5.6.1.2 (using the
ListView, rather than a GridView).
When you reach the Configure Data Source window (shown in Figure 5.77), the settings
will change to accommodate inserting, updating, and deleting.
A custom SELECT, UPDATE, INSERT, and DELETE statement has to be inserted next.
This option allows the query statement to be tested to see whether or not it is correct
before continuing.
UPDATE Learner
SET Name = ?, Surname = ?, DateOfBirth = ? WHERE (StudentNumber = ?)
Click Test Query to see whether or not the correct values are being selected from the
database and table.
Click Finish.
Click on the > next to the ListView control.
Select the Configure ListView… option.
Additional parameters must now be set in order for the DELETE statement to work.
With the ListView control selected, edit the DataKeyNames property in the
Properties window (Figure 5.81).
Click OK.
Ensure that the DELTE statement is exactly as shown in Figure 5.79 above.
Add the Parameters to the list. These parameters must be exactly the same as the
parameters in the DELETE command box.
Click OK.
Over and above changing the DeleteQuery property of the Data Source, the
UpdateQuery property also has to be changed.
Add all the parameters which are present in the query statement, i.e. Name,
Surname, DateOfBirth, and StudentNumber.
When dealing with both deleting and updating, it is vitally important that the correct
parameters are added to the DataKeyNames property of the ListView control. They
must be the parameters that are in the WHERE clause of both the DELETE and UPDATE
query.
If the WHERE clause of the UPDATE statement had to change from StudentNumber to
Name and Surname, an error would occur because the DELETE statement will use the
Name and Surname, but it does not exclusively specify these parameters in the DELETE
query.
Use the Delete, Edit, and Insert options to see how they work.
In the example, a new record, “Brian Scott”, has been added; the existing record, “Arnold
Ernest”, has been changed to “Arnold Paul Ernest”; and the existing record, “Raymond
Nesingwary”, has been deleted. The ListView control will be displayed as shown in
Figure 5.86:
Once again, when you reach the Configure Data Source window (shown in Figure 5.78),
the settings have to change to accommodate inserting, updating, and deleting. These
settings will be exactly the same as in the previous section (5.6.2.2.1).
This option allows the query statement to be tested to see whether or not it is correct
before continuing.
UPDATE Learner
SET Name = @Name, Surname = @Surname, DateOfBirth = @DateOfBirth WHERE
(StudentNumber = @StudentNumber)
The remaining steps after entering the query commands are exactly the same as they are
with the MS Access 2007 database. When you are finished creating the data source,
proceed as follows:
There is no need to change the DeleteQuery and UpdateQuery properties of the data
source because the SQL database adds this automatically.
Change the design of the ListView control to Professional using the Configure
ListView option.
Save and run the Web page.
The same records, as in the previous example, have been inserted, edited, and deleted.
Follow exactly the same steps that were used to add data to a DetailsView control
in the previous section. Remember to add the SELECT, INSERT, UPDATE, and
DELETE query commands.
Change the DataKeyName property of the FormView control.
Change the DeleteQuery and UpdateQuery properties of the data source.
The FormView control will automatically create a basic template based on the data source
set. The default template, using the Professional style, is shown in Figure 5.91:
The templates used by a FormView control can be created visually (like a DataList
control) or by writing source code (like a Repeater control). The FormView control will
work identically whether or not an Access or SQL database is used. If you want to create
a FormView control using SQL, it will be done in exactly the same way as adding data to a
DetailsView control.
The following example shows how data can be retrieved from an MS Access 2007
database:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
// Import the System.Data.OleDb namespace.
using System.Data.OleDb;
// If there is a result.
if (result != null)
{
// Read the next item.
while (result.Read())
{
// Add the current record’s name column.
TestListBox.Items.Add(result["Name"].ToString());
}
}
DisconnectDatabase();
}
Data Source=" +
Request.PhysicalApplicationPath +
"App_Data\\CollegeDatabase.accdb");
conn.Open();
}
// Method which executes a query and returns the result (if any).
private OleDbDataReader ExecuteQuery(String query)
{
try
{
OleDbCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
return cmd.ExecuteReader();
}
catch (OleDbException odbe)
{
return null;
}
}
}
The above example selects the entire Learner table from the database, and displays all
the values in the Name column in a ListBox control called TestListBox. Convenience
methods have been created which connect to the database, disconnect from it, and
execute both queries and commands.
The PhysicalApplicationPath (from the Request object) has been used to ensure
that the database will always work regardless of the location of the website as a whole.
The Request object stores information about a client request. This object will be covered
in more detail in section 5.7.2.3.
An OleDbDataReader always points to one row at a time, accessible through the index
operator. The Read() method moves the data reader to the next row and returns true if
there are any more records to read, and returns false if no more records are found.
In some situations (unlike the above example), it might be necessary to find a specific
record rather than a list. In this case, a while loop would not be necessary. All that
would need to be done is to check that a result was returned, and then the value can be
assigned or worked with as necessary.
The following example shows how data can be retrieved from an MS SQL database:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
// Import the System.Data.OleDb namespace.
using System.Data.SqlClient;
// If there is a result.
if (result != null)
{
// Read the next item.
while (result.Read())
{
// Add the current record’s name column.
TestListBox.Items.Add(result["Name"].ToString());
}
}
DisconnectDatabase();
}
sqlConn.Open();
// Method which executes a query and returns the result (if any).
private SqlDataReader ExecuteQuery(String query)
{
try
{
SqlCommand cmd = sqlConn.CreateCommand();
cmd.CommandText = query;
return cmd.ExecuteReader();
}
catch (SqlException ex)
{
return null;
}
}
}
5.6.4 Exercises
1. List two differences between the DataList control and the
Repeater control.
2. In which folder does ASP.NET look for data sources by default?
3. Give a reason why a manual connection to a database would be
used rather than using data-binding?
The new page will now be visible in the Solution Explorer. To open it for editing, double-
click on it.
When clicked, the HyperLink control should redirect the user’s Web browser to
Page2.aspx.
NOTE The Select URL dialog generates a relative path to the file (i.e. how to get to
the file from the location of the current page). This is convenient because if
the website is moved from one location to another, the links will still function
(which would not be the case if the links pointed to an absolute location).
Should the HyperLink control need to point to a location outside the current
website, then an absolute path should be specified (for example,
http://www.cti.co.za/).
As with Label controls, HyperLink controls can have their appearance changed via their
properties.
For this course, one such method will be explored, namely user control templates. This
involves creating a user (custom) Web control which contains the item required on every
page. In this case, a Header control will be created.
The following (Figure 5.93) is a sample of how the header control could look:
In this example, each of the buttons is in fact a Hyperlink control with style parameters
set to the following (i.e. a HyperLink style has been created):
.HyperLink
{
border: 1pt solid black;
background-color: #999999;
padding: 5px;
width: 100px;
text-align: center;
letter-spacing: 3px;
}
It is not necessary to provide functionality for the HyperLink controls in this example.
However, in an actual Web application, this will of course be necessary.
To add the user control to a page, simply drag the file from the Solution Explorer onto the
page. As this control is intended to be a header for every page in the website, it would
need to be added to each and every page. However, any modifications made to the
control, and which can only be made in the control file itself, will be reflected in all the
documents. This can save a lot of time and ensures that pages are consistent with one
another.
WriteFile Writes the contents of a specified file to the current Web page.
This file can contain any text, including HTML data.
Write Writes the specified String to the current Web page. This String can
contain any text, including HTML data.
Additionally, the Server class provides the MapPath() method which can be used to
convert a relative path into an absolute path at runtime. This is particularly useful for Web
services, which do not have access to the Request object, and thus cannot use the
PhysicalApplicationPath property.
An example of a login page will now be created. This page will use cookies to determine if
a user is logged in or not.
Place a Label to the left of the Login Button with no text. This Label will be used to
display any error messages.
Now create a second page, called Home.aspx. It should look like the image in Figure
5.95:
No additional content will be added for this home page as it is simply being used it to test
the login system. Now write the functionality for this system.
The database which will be used for this example is called UserDatabase.mdb, and it
contains the User table as shown in Figure 5.96:
Create the above database and table, and then import it into the project in the
App_Data directory.
Because this example will potentially be accessing the database from multiple pages, a
class will be created to handle interactions with the database. This will help to cut down
on repetitive code.
using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.OleDb;
conn.Open();
}
// Method which executes a query and returns the result (if any).
public OleDbDataReader ExecuteQuery(String query)
{
try
{
OleDbCommand cmd = conn.CreateCommand();
cmd.CommandText = query;
return cmd.ExecuteReader();
}
catch (OleDbException odbe)
{
return null;
}
}
}
// Construct a query string using the values from the text boxes.
string queryString = "SELECT * FROM [User] WHERE EmailAddress = '";
queryString += emailAddressTextBox.Text + "' AND Password = '";
queryString += passwordTextBox.Text + "';";
// Connect.
useDb.ConnectToDatabase();
// If there are rows in the result, then the check was successful.
if (dbReader != null && dbReader.HasRows)
{
// Set up the cookies.
HttpCookie loggedInCookie = new HttpCookie("LoggedIn", "true");
Response.Cookies.Add(loggedInCookie);
// Disconnect.
useDb.DisconnectDatabase();
}
If an incorrect email address or password is entered, the error message will be displayed
in the error label (ErrorLabel). However, if the user enters a valid email address and
password, then the cookies will be set and the user will be redirected to the next page.
Now that the facility to log in exists, it is necessary to create code which checks whether or
not the user is logged in and responds appropriately. A user that opens the Login page
while logged in, should be redirected to the Home page. Conversely, an attempt to access
the Home page while not logged in, should redirect the user to the Login page. Note that it
is always important to ensure that a cookie has a value before attempting to read it, in
order to prevent exceptions being thrown.
Enter the following code into the Page_Load event-handler for the Login page:
Enter the following code into the Page_Load event-handler for the Home page:
All that remains is to create the functionality for the Log out button.
Response.Redirect("Default.aspx");
}
}
The login screen should be shown again, which is not what was intended. This is because
Web browsers such as Internet Explorer cache Web pages (i.e. store them so that they do
not need to be downloaded from the Internet again). However, the browser can be forced
to refresh the page.
The browser should be redirected to the Home.aspx page because, according to the
cookies stored on the computer, the user is still logged in.
Now change the address bar so that it points to Home.aspx instead of Default.aspx
(but leaving the rest of the address intact) and press the <Enter> key.
Refresh the page by pressing the <F5> key.
The browser will be redirected to the Default.aspx page because, according to the
cookies stored on the computer, the user is not logged in.
Add the following line of code to the event-handler for the loginButton, just before
the cookie is added to the Response.Cookies collection:
loggedInCookie.Expires = System.DateTime.Now.AddDays(7);
The above code gives the cookie an expiry date of exactly one week from the time at
which it was created.
The browser will be automatically redirected to the Home.aspx, because the user is still
logged in.
One way in which this data can be stored is by using Session cookies, as shown in
section 5.7.3.1. However, cookies can only store string values. Session variables, on
the other hand, can store values of any type in the .NET Framework.
Session variables are stored in the Session object, as discussed in section 5.7.2.5.
Figure 5.97 is an example which shows how basic Session variables can be used for
Default.aspx:
The HyperLink control on Default.aspx (Figure 5.97) has its NavigateUrl property
set to Page2.aspx.
Default.aspx.cs:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
Session["anArrayList"] = stringArrayList;
}
}
Page2.aspx.cs:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
TestListBox.DataSource = Session["anArrayList"];
TestListBox.DataBind();
}
}
After the HyperLink on Default.aspx has been clicked, Page2.aspx should look like the
image in Figure 5.98:
5.7.4 Exercises
1. What syntax is used to create or modify a Session variable?
2. When will cookies be removed from the client system?
3. For what is the Application object primarily used?
1. Placing the files on a disk or other storage medium and physically taking them to the
Web server.
2. Copying the files to the Web server via HTTP (using a server management tool).
3. Copying the files to the Web server via FTP (File Transfer Protocol).
The first option is very rare; since Web servers are almost always situated external to the
premises (and often the company) using them.
The second option is more common. Many hosting providers offer tools (and these are
sometimes built using ASP.NET) which can be used to manage a Web server, up to and
including, uploading files through HTTP. Microsoft Internet Information Services (IIS) can
also transfer files through HTTP.
The third option is the most common. The files are transferred after a connection is made
to the Web server via FTP using either:
Visual Web Developer provides several built-in methods of copying a website from one
location to another. Select the Website Copy Website… option from the menu.
Selecting this menu option opens a new window, as shown in Figure 5.99:
In this window, the files and directories of the website are listed on the left-hand side.
When connected to the desired location, the files and folders of that location will be
displayed in the right. The buttons in the middle of the panel allow files to be moved
across, either individually, or all at once.
File System
o This option allows a location on the current computer to be specified.
Local IIS
o This option allows a locally-hosted IIS server to be specified. This requires
Microsoft Internet Information Services to be installed on the local computer.
FTP Site
o This option allows a remote FTP site to be specified.
Remote Site
o This option allows a remote IIS server to be specified.
All of the files in the source website have now been copied to the destination site.
5.8.2 Exercises
1. List two ways in which a website can be deployed.
2. IIS stands for what?
3. FTP stands for what?
4. Using all the knowledge covered in this unit, create a database
which stores information about learners in a tertiary college. This
database must store the learners’ names, surnames, date of birth,
and current course. A website must be created which will display
these names in a layout that is both professional and easy to read.
This information must only be accessible to users once they have
logged in via a login screen. User information (i.e. usernames and
passwords) must also be stored in the database.
The questions in this section are similar to those asked in the exam. Try these questions
and then check the answers with the instructor. The questions are taken from the study
guide and textbook and will be made up of theory and application questions in multiple
choice, multiple response, true/false, and selection formats. Allow about 25 minutes for all
the questions. Good luck!
Questions
Multiple choice
1. Which one of the following data-bound controls cannot have its templates created
visually?
a. DataList
b. Repeater
c. FormView
d. GridView
3. Which one of the following properties of a Calendar control can be used to set which
date is shown on the control when the page is loaded?
a. SelectedDate
b. SelectedDates
c. VisibleDate
d. SelectionMode
4. Which keyboard shortcut is used to stop a Visual Web Developer Express server from
running?
a. <F5>
b. <Shift> + <F5>
c. <Alt> + <F5>
d. <Ctrl> + <F5>
5. Which of the following properties is common to all controls, and should always have its
value changed from the default?
a. ID
b. Text
c. DataSource
d. Style
True/False
Multiple response
2. Which three of the following are valid options for the TextMode property of a
TextBox control?
a. Single
b. Multiple
c. SingleLine
d. Password
e. MultiLine
f. PasswordLine
This unit covers topics such as XML data manipulation, .NET Remoting, XML Web
Services, and Windows Services.
Unit 6 counts 80% towards part B (units 4, 5, and 6) of your C# mark, and there are 14
days to complete it. The time and marks are scheduled as follows:
The exams will cover units 1 to 6. Therefore, their weight will count 75% towards the C#
mark for part B. The project counts 5% towards that mark.
6.1 Introduction
It is very important to understand why XML was created. It was created so that richly
structured documents can be used over the Web. It is similar to HTML but has a different
purpose. XML describes data whereas HTML presents that data in a visual form. As
outlined in Unit 4, pieces of information are described within XML document tags. This
enables applications to interpret data accurately.
The following example demonstrates an XML document is its simplest form. Start by
creating a new XML document:
<book>
<title>Visual C# 2008</title>
<author>James Foxall</author>
<publisher>SAMS</publisher>
</book>
From the example above it is evident that James Foxall is the author of Visual C# 2008.
This data would have been quite confusing without the XML markup to make the
distinctions.
Although the example runs without errors, it is not very satisfactory as it does not do much.
XML is mainly used to transmit data from one domain to another. A program is created at
each end which is designed to interpret the XML document and to make use of the data.
The envelope
The encoding rules
The RPC representation
The SOAP message
In .NET, SOAP can be used to perform Remote Procedure Calls. As such, SOAP
contains an RPC Representation which defines a convention that can be used to represent
remote procedure calls and responses.
1 <SOAP:Envelope xmlns=http://schemas.xmlsoap.org/soap/envelope/>
2 <SOAP:Body>
3 <m:heyThere xmlns:m="http://www.osborne.com/"/>
4 </SOAP:Body>
5 </SOAP:Envelope>
The SOAP message always starts with the envelope element defined on line 1. The URL,
(xmlns=http://schemas.xmlsoap.org/soap/envelope), specifies the location for
further definitions. Line 2 is the start of the message body. Line 3 is the method call. It is
given a name and the namespace is specified. Lines 4 and 5 simply close the envelope
and body tags.
The example below shows exactly what the layout would look like if the envelope, the
header, the body, and the fault are present in a SOAP message.
<SOAP:Envelope xmlns:http://schemas.xmlsoap.org/soap/envelope/
soap:encodingStyle=http://schemas.xmlsoap.org/soap/encoding/>
<SOAP:Header>
<!--
Header information goes here, e.g.
<t:Transformation xmlns:t="URL"></t:Transformation>
-->
</SOAP:Header>
<SOAP:Body>
<!--
The body goes here, e.g.
<m:heyThere xmlns:m="URL" />
-->
<SOAP:Fault>
<!--
Fault information, e.g.
<faultcode>SOAP:Server</faultcode>
<faultstring>Server Error</faultstring>
-->
</SOAP:Fault>
</SOAP:Body>
</SOAP:Envelope>
The <SOAP:Fault> tag is used to specify details about a fault using <faultcode> and
<faultstring> tags.
HTTP acts as a transmission channel when using SOAP to send a method call within an
XML document. The steps in the process are described below:
An HTTP request is sent to the server. A SOAP request is contained within the HTTP
request.
The SOAP request is bound to HTTP.
The method that will be called from the server is specified as getItem. The SOAP
document that the data can be retrieved from would look something like this:
1 <?xml version="1.0"?>
2 <SOAP:Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
3 <SOAP:Body>
4 <m:getItem xmlns:m="namespace:IItem">
5 <name>toy car</name>
6 </m:getItem>
7 </SOAP:Body>
8 </SOAP:Envelope>
Figure 6.4 above shows how the client (consumer) makes a request to a directory service,
to find out what the location of the required Web service is. Once the location is returned,
the client proceeds to make a remote call to the server (provider). The server processes
the request and returns the result to the client.
Types: The different data types used in the Web Service are defined here.
Message: The actual message is described here.
PortType: This part defines a set of operations and their related messages.
Binding: Protocol details are described by binding elements.
Service: A set of related ports are grouped here.
UDDI white pages: This is the basic information such as the company name, address,
and phone numbers.
UDDI yellow pages: This is the detailed business data.
UDDI green pages: This is the information about the key business processes of the
company. This includes the operating platform, supported programs, purchasing
methods, shipping and billing requirements, and other high-level business protocols.
Figure 6.5 shows the process of discovering and using a Web Service as seen from the
consumer’s point of view:
6.1.6 Exercises
1. Name the three components of the UDDI Business Registry.
2. For what does XML stand?
3. Name the three components of a SOAP message.
4. What is a SOAP message wrapped with?
5. For what does WSDL stand?
6.2.1 Introduction
In .NET, XML support is contained in the System.Xml namespace and includes objects
that can be used to parse, validate, and manipulate XML. XML data can be read, written,
and validated using objects in this namespace. Additionally, the System.Xml namespace
provides access to XPath, which is used to navigate and query data contained in an XML
document.
Verify that the characters are legal XML characters, and that element and attribute
names are valid XML names.
Verify that the XML document is well formed.
Validate data against a DTD or schema.
Retrieve data from the XML stream or skip unwanted records using a pull model.
The current node refers to the node on which the reader is positioned. Any of the read
methods can be used to advance the reader. The properties are used to return the value
of the current node.
Table 31Error! Reference source not found. shows the most important properties of the
XmlReader class:
The XmlReader class cannot be instantiated and therefore the XmlTextReader class
must be used.
<Root Rating="7">
<Name>News 247</Name>
<Description>Live news</Description>
<Website>http://www.news247.nw</Website>
</Root>
</Roots>
Add a Button control with the label “Read XML” (btnReadXml) and a ListBox
control (lstNodes) to the form.
Switch to the Code window and add the following using directive:
using System.Xml;
Add the following code to the click event-handler for the Button control:
Read()
Name
HasValue
Depth
NodeType
Value
Build and run the project. Click the Read XML button.
The output should look like the one shown in Figure 6.7:
Figure 6.7 – Data read from an XML file using an XmlTextReader object
Add the following code to the click event-handler for the Button control:
while (xReader.Read())
{
if ((xReader.NodeType == XmlNodeType.Element) ||
(xReader.NodeType == XmlNodeType.Text))
{
curNode.Length = 0;
for (int i = 0; i < xReader.Depth; i++)
{
curNode.Append(" ");
}
if (xReader.HasValue)
{
curNode.Append(": " + xReader.Value);
}
lstNodes.Items.Add(curNode.ToString());
if (xReader.HasValue)
{
curNode.Append(": " + xReader.Value);
}
lstNodes.Items.Add(curNode.ToString());
}
}
}
}
}
When the project is run and the Read XML button is clicked, the output should look like
Figure 6.8:
Figure 6.8 – Selected data read from an XML file using an XmlTextReader object
The XmlNode class is used to access a node as a whole, instead of accessing those
nodes as part of an XML data stream. It is more efficient to access a node as a whole. In
order to make code more object-orientated and provide a better overview of object in an
XML document, properties of a whole object can be changed after instantiating the object.
It can then be written back to the original XML file.
lstNodes.Items.Add(currentNode.ToString());
XmlNode xNodeWorking;
if (xNode.HasChildNodes)
{
xNodeWorking = xNode.FirstChild;
while (xNodeWorking != null)
{
AddChildren(xNodeWorking, iDepth + 1);
xNodeWorking = xNodeWorking.NextSibling;
}
}
}
}
When all the code is entered the entire source code file should look like this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace XmlNodeEx1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
if (xRootNode.HasChildNodes)
{
xNodeWorking = xRootNode.FirstChild;
while (xNodeWorking != null)
{
AddChildren(xNodeWorking, 0);
xNodeWorking = xNodeWorking.NextSibling;
}
}
xTReader.Close();
}
}
}
The output is very similar to the previous example. It should look like Figure 6.9:
The difference between the output in this example and the previous example is that the
program uses the XmlDocument class to navigate through the nodes. It also uses
recursion to visit the nodes right down to the last child.
The specified information is displayed for each child and then each child of that node is
visited. The process is repeated until all nodes have been visited.
6.2.3 XPath
XPath (XML Path Language) is described as “a language for addressing parts of an XML
document”. It can be thought of as a query language, similar to SQL. A set of nodes can
be selected from the DOM representation of an XML document.
A specific path down the tree structure is used to find a set of items. The items are
separated using forward slashes. This concept is shown in Figure 6.10:
In figure 6.10, the Name element is selected. It can also be selected without being explicit,
as follows:
//Name
As in SQL statements, an asterisk (*) can be used as a wildcard. It has basically the
same function as in SQL. All names that are grandchildren of the Files node can be
selected as follows:
/Files/*/Name
A set of attributes can be selected instead of just a single element. To do this, simply add
the @ character in front of the attribute name. All Name attributes can be selected with the
following XPath expression:
//Files/File/@Name
Although the attribute can be specified without the path, it is recommended that all
expressions be presented explicitly.
The wildcard can once again be used to select multiple attributes but with a slight
difference. If the @ character is not included, the XPath expression looks for an element
instead. To select all the attributes of File, the following XPath expression can be used:
//File/@*
Specific nodes can also be extracted from XML using XPath expressions. Use the
following expression to find all Name elements in File with the value of Bill:
/Files/File/Name[.="Bill"]
Notice the dot operator. It represents the current node and the square brackets specify
the filter pattern. It is also possible to find all the Files with the name “Bill” with the
following expression:
/Files/File[./Name="Bill"]
Different patterns can be specified within the filtering specifications. These patterns
include attributes and Boolean expressions as shown in the next example:
/Files/File[./@Rating<10]
Apart from filtering patterns, different filtering functions, which form part of the filtering
patterns, can also be used in expressions. The example below selects all names that start
with B:
/Files/File[starts-with(Name, "B")]
There are a number of filtering functions that can be used and they are listed in Table 40:
Square brackets and indexing can be used in conjunction with XPath. Indicating the
square brackets after a particular element makes it possible to select a certain element by
an index (numerical) value placed in the square brackets.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace XPathEx1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Run the project and enter the following expression into the TextBox control:
//Files/File/Name
Click on the Search button and the names of all the files in the XML file will be shown
as seen in Figure 6.11:
The XPathNavigator class is an abstract class that defines a cursor model for
navigating and editing XML information items.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.XPath;
namespace XPathEx2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Run the project and enter the following expression in the TextBox control:
//Files/File/Name
Click the Search button and the names of all the roots in the XML file will be shown.
Add the following code to the class definition just below the public partial class
Form1 : Form definition:
if (xpNav.MoveToParent())
{
ListNode();
}
else
{
lstResults.Items.Add("No parent node");
}
if (xpNav.MoveToFirstChild())
{
ListNode();
}
else
{
lstResults.Items.Add("No child node");
}
if (xpNav.MoveToPrevious())
{
ListNode();
}
else
{
lstResults.Items.Add("No previous node");
}
if (xpNav.MoveToNext())
{
ListNode();
else
{
lstResults.Items.Add("No next node");
}
When all the pieces of code have been added, the source file should contain the
following:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.XPath;
namespace XPathEx3
{
public partial class Form1 : Form
{
private XPathDocument xpDoc;
private XPathNavigator xpNav;
public Form1()
{
InitializeComponent();
}
{
ListNode();
}
else
{
lstResults.Items.Add("No child node");
}
}
6.2.4 Exercises
1. What does DOM stand for?
2. In which namespace is all XML support contained?
3. Which property of the XmlReader class is used to determine
whether or not the node can have a text value?
4. Which method of the XmlReader class is used to jump over children
of the current element?
5. For what is the XmlNode class used?
6.3.1 Introduction
.NET Remoting enables applications to communicate with each other. The .NET objects
are exposed to remote processes which allow inter-process communication. This is all
made possible by the .NET Framework which provides a platform for distributed
applications. The two most prevalent means are .NET Remoting and Web Services.
Now that Remoting handles these tasks automatically, socket programming is performed
in the background and management responsibilities are something of the past.
Programmers need no longer to concern themselves with how a program will connect to a
remote server, but only with the design of a program and making sure the logic is correct.
In the end it makes development of distributed applications efficient and cost-effective.
Windows then creates boundaries between these documents so that they do not affect
each other. These process boundaries ensure that:
Processes have to be created, monitored constantly, and terminated when a failure occurs
or each time a different application is run, and they are therefore resource-intense.
The application domain is considered the base of process isolation and is represented by
the System.AppDomain class. It is possible to run multiple application domains within a
single Windows process. This results in the reduction of the overhead because there is
less switching of processes.
One application domain cannot gain access to code or data of another domain.
Every application domain has its own code, data, and configuration.
The code running within an application domain cannot affect code running within
another application domain.
An application domain can be terminated by the CLR without affecting or terminating
other applications in the same process.
The functionality of Remoting and Web Services is very similar because Web Services
were built on the Remoting infrastructure. It is sometimes difficult to decide whether to
make use of Web Services or Remoting. Follow these tips to make a choice:
An application designed for a corporate network, for example, needs to have both
ends of communication (namely the client and the server) under control and therefore
.NET Remoting will be better suited to this application.
When only one end point needs to be under control, ASP.NET Web Services will
suffice. This might be used when a business partners’ application needs to be
interoperable.
It was previously stated that applications have boundaries and the question of how
domains communicate across a network might arise. There is a solution! These tasks are
performed indirectly by using a proxy object as illustrated in Figure 6.14:
1. When the client requests information from the server, the Remoting system on the
client application creates a proxy object, which behaves like the actual server object,
but resides in the same application as the client. The server objects now appear to be
in the same process.
2. When a method on the server object is called by the client object, the proxy
object passes information to the client’s Remoting system, which sends it to the
server’s Remoting system through a transmission channel.
3. The server’s Remoting system receives the information and calls the method in the
server object.
4. The server’s Remoting system receives the result of the method and sends the
information back to the client’s Remoting system, through the transmission
channel.
5. The client’s Remoting system then receives the result and passes it back to the
client object via the proxy object.
Serialisation is the process of encoding an object or data into a form that can be sent
safely across a communication channel. De-serialization is the exact opposite of
serialisation. It is invoked once information arrives.
[Serializable()]
public class MBVObject
{
// Methods to be called.
}
6.3.5.2 Channels
Channels are very handy objects. They are used to transport information or data across
application boundaries. Each call from a client is sent from the client’s Remoting system
to the server’s Remoting system through a channel object. This is also known as the
transmission channel as shown in figure 6.14. Any results will be returned to the client via
the same channel.
Each channel consists of two endpoints: one at the server’s side and one at the client’s
side. The end at the server’s side listens for any information or data on a specific protocol
and port number. The end at the client’s side receives the information or data sent across
the channel using the same specific protocol and port number. There are two channel
implementations provided with .NET. One is based on HTTP and the other on TCP.
The code below registers an HTTP channel on port 1248 and is able to send and
receive:
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
// Preceding code.
HttpChannel channel = new HttpChannel(1248);
ChannelServices.RegisterChannel(channel);
The code below registers a TCP channel on port 1248 and is able to send and receive:
using System;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
// Preceding code.
TcpChannel channel = new TcpChannel(1248);
ChannelServices.RegisterChannel(channel);
6.3.5.4 Formatters
Formatters play a very important role in sending messages across a channel. The data
contained within a message first needs to be serialised and encoded. When it reaches the
receiving end, the data is decoded and de-serialised. This is all done by Formatters. Two
formatters are commonly used: Soap and Binary.
Server-activated objects
Client-activated objects
1. A request is sent to the server to activate the object when a client wants to create an
instance of the remote object.
2. The object is instantiated with the constructor parameters provided by the client’s
request. This object is instantiated by the server. An ObjRef object is returned,
which contains information to generate a proxy to the remote object on the client that
can communicate with the remote object.
3. A proxy object is created by the client. It is based on the ObjRef object it received
from the server.
Alter the code in the source code file to look like the code below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
namespace UseDatabase
{
public class UseDatabase : MarshalByRefObject
{
OleDbConnection conn = new OleDbConnection();
// Default constructor.
public UseDatabase() : this("CollegeDatabase.accdb")
{
Make sure to build the project by going to Build > Build Solution.
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Runtime.Remoting;
10 using System.Runtime.Remoting.Channels;
11 using System.Runtime.Remoting.Channels.Tcp;
12
13 namespace DatabaseServer
14 {
15 public partial class Form1 : Form
16 {
17 public Form1()
18 {
19 InitializeComponent();
20 }
21
22 private void Form1_Load(object sender, EventArgs e)
23 {
24 RunServer();
25 }
26
27 public void RunServer()
28 {
29 try
30 {
31 // Create and register the channel using TCP and port 1902.
32 TcpChannel channel = new TcpChannel(1902);
33 ChannelServices.RegisterChannel(channel, true);
34
35 // Register the UseDabase class.
36 RemotingConfiguration.RegisterWellKnownServiceType
37 (typeof(UseDatabase.UseDatabase), "UseDatabase",
38 WellKnownObjectMode.SingleCall);
39
40 lblMessage.Text = "Server running...";
41 }
42 catch (Exception e)
43 {
44 lblMessage.Text = "An error has ocurred...";
45 MessageBox.Show(e.Message);
46 }
47 }
48
49 private void btnClose_Click(object sender, EventArgs e)
50 {
51 Application.Exit();
52 }
53 }
54 }
On line 33, the RegisterChannel() method takes two parameters. The first parameter
specifies the name of the TcpServerChannel object and the second parameter indicates
whether security must be activated on this channel.
Modify the code in the source code file to look like the following code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using UseDatabase;
namespace DatabaseClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
try
{
// Get the object from the server.
useDb = (UseDatabase.UseDatabase)Activator.GetObject
(typeof(UseDatabase.UseDatabase),
"tcp://localhost:8085/UseDatabase");
}
catch (Exception ex)
{
MessageBox.Show("An error has ocurred." + ex.Message);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Counter
{
public class Counter : MarshalByRefObject
{
private int count = 0;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CountServer
{
public partial class CountServer : Form
{
public CountServer()
{
InitializeComponent();
}
// (A)
RemotingConfiguration.RegisterWellKnownServiceType
(typeof(Counter.Counter), "Counter",
WellKnownObjectMode.SingleCall);
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Runtime.Remoting;
10 using System.Runtime.Remoting.Channels;
11 using System.Runtime.Remoting.Channels.Tcp;
12
13 namespace CountClient
14 {
15 public partial class CountClient : Form
16 {
17 public CountClient()
18 {
19 InitializeComponent();
20 }
21
22 private void btnCount_Click(object sender, EventArgs e)
23 {
24 try
25 {
26 // Get the object from the server.
27 Counter.Counter c = (Counter.Counter)Activator.GetObject
28 (typeof(Counter.Counter), "tcp://localhost:1902/Counter");
29
30 // Call the method.
31 lblMessage.Text = "Count Value: " + c.CountUp();
32 }
33 catch (Exception ex)
34 {
35 MessageBox.Show("An error has ocurred." + ex.Message);
36 }
37 }
38
39 private void CountClient_Load(object sender, EventArgs e)
40 {
41 // The channel needs to be registerd or
42 // the application will not work correctly.
43 TcpChannel channel = new TcpChannel();
44 ChannelServices.RegisterChannel(channel, true);
45 }
46 }
47 }
Observe how the value returned by the Counter is always 1. This is because a new object
is instantiated (line 27) every time the method is called.
// (A)
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Counter.Counter),
"Counter", WellKnownObjectMode.Singleton);
With the server running in Singleton mode, a new object will be instantiated the first
time the CountUp() method is called. From there on, the same object will be used for
each method call. As such, the value returned from the Counter object will increase by
one every time the CountUp() method is called, and this value will be maintained in
between method calls. Even if the client is closed and reopened, this value will not be lost.
1. Channels are registered as separate server and client channels, and not as a
combined channel.
2. The RegisterWellKnownServiceType method is changed to
RegisterActivatedServiceType and RegisterActivatedClientType
respectively.
Modify point (A) in the server of the previous example so that it appears as follows:
// (A)
RemotingConfiguration.RegisterActivatedServiceType(typeof(Counter.Counter));
Modify the client code of the previous example so that it appears as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace CountClient
{
public partial class CountClient : Form
{
public CountClient()
{
InitializeComponent();
}
Counter.Counter c;
// Instantiate.
c = new Counter.Counter();
}
}
}
When the Count! Button control is clicked; it will maintain its value for as long as the
client is running. If the client is closed and then run again, a new instance of the Counter
object will be created; thus the count value will be reset. If another client was to connect to
the server at the same time, it would also receive its own unique Counter object which
will be maintained until the client is closed (or the client disposes of the object explicitly).
The CAO is a simple one and could be duplicated without using remoting. It can be
duplicated simply by storing a value in the client itself. However, this does not mean that
client-activated objects have no use. After all, they still reside on the server. One way of
testing this is to have the Counter object write its count value to the console whenever
the CountUp() method is called. As the server is a Windows Forms Application, it will
not display a console by default. The console can be enabled in a Windows Forms
Application by following these steps:
This can be very useful for debugging. When debugging is complete, the Application
type field should be set back to Windows Forms Application.
NOTE Always remember that remotable applications consist of at least three parts,
i.e. the client, the server, and the remotable object(s). All of these must be
handed in for projects and examinations.
6.3.7 Exercises
1. Which parts of network programming are handled by .NET Remoting to
make the developer’s work easier?
2. Henry wants to write an application that must interface with the systems
of his suppliers for automatic ordering of stock. He is not sure what kind
of systems his future suppliers might be using, but knows that they will
provide functionality for placing orders. Which approach should Henry
take when designing this application, and why?
a. He should use .NET Remoting, since he wants to design his
software for a corporate network.
b. He should use .NET Remoting, since both end points of
communication are known and under his control.
c. He should use Web Services, since only one end point is under his
control.
d. He should use socket programming, since he needs to connect to
5. Which one of the following methods would set a server to listen for client
connections using a server-activated object, and creating and destroying
the object for each client call?
a. RemotingConfiguration.RegisterWellKnownServiceType
(typeof(RemotingExample.DbConnect), "DbConnect",
WellKnownObjectMode.SingleCall);
b. RemotingConfiguration.RegisterWellKnownServiceType
(typeof(RemotingExample.DbConnect), "DbConnect",
WellKnownObjectMode.Singleton);
c. RemotingConfiguration.RegisterActivatedServiceType
(typeof(RemotingExample.DbConnect));
d. RemotingConfiguration.RegisterActivatedClientType
(typeof(RemotingExample.DbConnect), "tcp://localhost:1248");
6.4.1 Introduction
The concept of Web Services might seem complicated and difficult, but the idea is quite
simple. A Web Service is a device used to interact with objects over the Internet as shown
in Figure 6.19. Web Services are also known as public methods that can be called over
the Internet.
www.mydomain.com
Client Program
Web Service
Internet
Web Application
(as Client) Application or
Web Application
Web Services are the basic fundamental building blocks of invoking features that can be
accessed by an application. The accessibility to provide the features across different
platforms that are developed using different languages can be used by any remote
application over the Internet. At times, the Web Services may prove more useful as a
means of providing the user with only the specified or relevant information without the
need for accessibility to resources that have to be securely maintained.
Look at this simple example. An internet ordering system might expose a Web service for
automated ordering purposes. It does not make a difference whether the Web Service’s
client is a standalone application or a Web application as shown in Figure 6.20.
Figure 6.21 shows the basic objects involved in the Web Services architecture:
.NET Web Services will normally be hosted using Microsoft Internet Information Services
(IIS). During testing, however, they can be hosted using Visual Web Developer.
1 using System;
2 using System.Linq;
3 using System.Web;
4 using System.Web.Services;
5 using System.Web.Services.Protocols;
6 using System.Xml.Linq;
7
8 [WebService(Namespace = "http://tempuri.org/")]
9 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
10 // To allow this Web Service to be called from script, using ASP.NET AJAX,
11 // uncomment the following line.
12 // [System.Web.Script.Services.ScriptService]
13 public class Service : System.Web.Services.WebService
14 {
15 public Service ()
16 {
17 //Uncomment the following line if using designed components
18 //InitializeComponent();
19 }
20
21 [WebMethod]
22 public string HelloWorld()
23 {
24 return "Hello World";
25 }
26 }
Lines 1 – 6:
o Include the namespaces necessary to create a Web Service.
Line 8:
o This attribute specifies that this class is a Web Service. It also specifies the
namespace in which the Web Service resides. This is not the .NET namespace,
but the website on which this Web Service will be hosted. This is used to
differentiate between different Web Services which share the same name and
http://tempuri.org/ is generally used during development.
Line 9:
o This attribute specifies that the Web Service conforms to the WS-I (Web Services
Interoperability Organization) Basic Profile. This profile is primarily used to ensure
that multiple Web Services can be used in a client without interfering with one
another. This line may safely be deleted.
Line 13:
o Declares a class called Service. This is the Web Service itself. It is not
necessary for the class to be called Service; and can be renamed if desired. All
Web Services are derived from System.Web.Services.WebService.
Line 21:
o This attribute specifies that the method is a WebMethod. This attribute needs to
be specified for any method which must be accessible remotely.
Lines 22 – 25:
o This is a WebMethod which returns the string “Hello World”.
[WebMethod]
public int Add(int a, int b)
{
return a + b;
}
To set a specific port number for use by a project in Visual Web Developer:
An additional property here is Virtual path. This property specifies which virtual directory
the development server should use. This property can be cleared, in which case no virtual
directory will be used (i.e. the server will run on http://localhost:8081/ instead of
http://localhost:8081/VirtualPath/, where 8081 is the port number). It is recommended, but
not vital, that this is done for any projects or exams. No virtual directories will be used for
further examples in this guide.
Select Start Debugging from the Debug menu, or press the <F5> key.
This page describes the various WebMethods which are available from this Web Service.
These methods can be tested by clicking on their names, entering any necessary
parameters, and viewing the result (which will be returned in an .xml format).
The Web Service will continue to be available for client applications so long as the
development server is running. If stopped, this server will need to be run again before
client applications can access any exposed methods.
NOTE Always remember that the Web Service is separate to the rest of the
application and must also be handed in for any projects or exams.
NOTE Make sure that the Web Service is running in Visual Web Developer while
adding the Web reference.
The Add Web Reference dialog will now be visible (Figure 6.24):
The Web service description page should now be visible, and the Web Service should be
visible on the right-hand side of the screen.
Enter the name of the Web Service in the Web reference name textbox.
Click Add Reference.
Modify the code for the main form so that it looks as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WebServiceClient.AddService.Service;
namespace WebServiceClient
{
public partial class Form1 : Form
{
int a;
int b;
public Form1()
{
InitializeComponent();
}
try
{
Service s = new Service();
txtResult.Text = s.Add(a, b).ToString();
}
catch (Exception ex)
{
MessageBox.Show("An error has occurred..." + ex.Message);
}
}
}
}
Follow the same procedure as before to add the Web reference to the project.
Modify the code so that it looks as follows:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using AddService.Service;
try
{
Service s = new Service();
txtResult.Text = s.Add(a, b).ToString();
}
catch (Exception ex)
{
lblMessage.Text = "An error has occurred..." + ex.Message;
}
}
}
As with the Windows Forms application, the answer will be displayed in the third TextBox.
6.4.6 Exercises
1. How is a method within a WebService identified as one which is
accessible through the WebService?
2. How is a Web Service accessed from a client application?
6.5 Project
Have completed one of the three projects listed below. Ask your
instructor which project you should complete.
Be able to explain and implement all the concepts presented in the
project you have done.
The following steps should be followed after the project folder has been copied to another
computer:
Also refer to the section on Required Documentation in the Introduction to this guide.
Website
This must be written in Visual Web Developer 2008 Express Edition using C# only, and
should present the buyer with interfaces to satisfy the following needs:
Buyers must be able to register by providing some personal details such as their email
address and a password. An additional question and answer must also be specified
and this will be asked should the password be forgotten.
A logon facility is required. In case the user has forgotten the password, there must be
an option to change it, as long as the user-specified question is correctly answered.
Once the user has logged on, a facility to view the cars must be provided. If a car is
selected, its relevant details must be displayed, including the highest bid made so far,
and the closing date for the bidding.
The user must be able to bid on a specific car. Once a bid has been made, it cannot
be changed or retracted.
Users must be able to add cars that they want to sell to the system. A facility to enter
all the relevant data must be available.
The user must be able to change personal information.
When the user has not logged in successfully and tries to view pages which require a
successful logon, he/she should be redirected to the start page to log in.
A logoff facility is required for the user to end the session.
Database
The database may be created in Microsoft Access. The following information must be
stored for use in the Web Service and website:
Buyer information provided when a user registers, e.g. UserID, email address,
password, etc.
Car information, e.g. carID, description, starting bid, etc.
Bid information, e.g. carID, userID, bid, value, etc.
Web Service
The Web Service must be created in Visual Web Developer 2008 Express Edition (as
described in the study guide). The following functionality must be made available through
the Web Service:
Each time a bid is made, the application information is written to a log file.
NOTE It is a good idea to do some research to get idea feel for how auction sites
work. Use as much creativity as possible, but strive for an overall look that is
both professional and straightforward. The layout of each interface should be
clear enough to follow without any problems, yet include all the required
functionality.
Subtotal: 10
Penalties
Program does not compile -5
Program causes unhandled error during execution or user input -5
Program documentation not handed in -10
Source code listing not handed in -5
Program documentation does not adequately describe
Program setup (2 marks)
Database setup/permissions (1 mark)
-5
Program operation (2 marks)
General comments
Total: 100
Website
This must be written in Visual Web Developer 2008 Express Edition using C# only, and
should present the user with interfaces to satisfy the following needs:
Users must be able to register by providing some personal details such as their email
address and a password. An additional question and answer must also be specified
and this will be asked should the password be forgotten.
A logon facility is required. In case the user has forgotten the password, there must be
an option to change it, as long as the user-specified question is correctly answered.
Once the user has logged on, a facility to view the posted books must be provided. If
a book is selected, its relevant details must be displayed, including the book name, the
author, and the average rating given so far.
The user must be able to rate a book on a scale of 1 to 5, with 5 being the highest
rating. Once a rating has been submitted, it cannot be changed or retracted.
Users must be able to submit books that they want rated. A facility to enter all the
relevant data must be available.
The user must be able to change personal information.
If the user has not successfully logged in and tries to view pages which require a
successful logon, he/she should be redirected to the start page to log in.
A logoff facility is required for the user to end the session.
Database
The database may be created in Microsoft Access. The following information is required
to be stored for use in the Web Service and Website:
User information provided when a user registers, e.g. emailAddress, password, etc.
Book information, e.g. bookID, bookName, author, etc.
Rating information, e.g. bookID, userID, rating, etc.
Web Service
The Web Service must be created using Visual Web Developer 2008 Express Edition (as
described in the study guide). The following functionality must be made available through
the Web Service:
Each time a book is rated, write the application information to a log file. E.g. User E-mail:
someone@onlinebookclub.com, Book: The Secret, Author: Rhonda Byrne
NOTE It is a good idea to do some research to get an idea of how rating sites work.
Use as much creativity as possible, but strive for an overall look that is both
professional and straightforward. The layout of each interface should be clear
enough to follow without any problems, yet include all the required
functionality.
Penalties
Program does not compile -5
Program causes unhandled error during execution or user input -5
Program documentation not handed in -10
Source code listing not handed in -5
Program documentation does not adequately describe
Program setup (2 marks)
Database setup/permissions (1 mark)
-5
Program operation (2 marks)
General comments
Total: 100
Website
This must be written in Visual Web Developer 2008 Express Edition using C# only, and
should present the customer with interfaces to satisfy the following needs:
The potential buyer must be able to sign up by providing an email address and a
password plus other personal information needed for verification: full name, ID
number, address, and contact details. An additional question and answer must also
be specified and this will be asked should the password be forgotten.
A logon facility is required. In case the user has forgotten the password, there must be
an option to change it, as long as the user-specified question is correctly answered.
Once the user has logged on, a facility to view items must be provided. When an item
is selected, the relevant details must be displayed, including the price, highest bid
made so far, and the closing date of the bid.
The user must be able to either buy the item or bid on it. Once the bid has been
made, it cannot be changed or retracted.
Users must be able to add items that they want to sell to the system. A facility to add
all the relevant details must be available.
The user must be able to change personal information.
If the user has not successfully logged in and tries to view pages which require a
successful logon, then he/she should be redirected to the start page to log in.
A logoff facility is required for the user to end the session.
Database
The database may be created in Microsoft Access. The following information must be
stored for use in the Web Service and website:
Buyer information provided when a user registers, e.g. emailAddress, password, etc.
Item information, e.g. itemID, description, price, startingBid, etc.
Bid information, e.g. itemID, userID, bid, etc.
Purchase information, e.g. itemID, userID, price, etc.
Web Service
The Web Service must be created using Visual Web Developer 2008 Express Edition (as
described in the study guide). The Web Service must provide the following functionality:
Each time a bid is made, the application information must be written to a log file.
NOTE It is a good idea to do some research to get an idea of how Internet auction
sites work. Use as much creativity as possible, but strive for an overall look
that is both professional and straightforward. The layout of each interface
should be clear enough to follow without any problems, yet include all the
required functionality.
Penalties
Program does not compile -5
Program causes unhandled error during execution or user input -5
Program documentation not handed in -10
Source code listing not handed in -5
Program documentation does not adequately describe
Program setup (2 marks)
Database setup/permissions (1 mark)
-5
Program operation (2 marks)
General comments
Total: 100
The questions in this section are similar to those asked in the exam. Try these questions
and then check the answers with the instructor. The questions are taken from the study
guide and textbook. The questions comprise theory and application questions which will
be in multiple choice, multiple response, true/false, and selection formats. Allow about 15
minutes for all the questions. Good luck!
Questions
True/False
Multiple choice
2. Which one of the following properties would be adjusted to increase the lifetime of an
object every time one of its methods is executed?
a. CurrentLeaseTime
b. InitialLeaseTime
c. SponsorshipTimeout
d. RenewOnCallTime
while (xReader.Read())
{
curNode.Length = 0;
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
a. This code represents a client that connects to a server on port 1248, and creates a
proxy object of the object located on the server.
b. This code represents a server that registers the port 1248 for clients wanting to
connect. Upon a request it would create a remotable object, but destroy it after
the call has finished.
c. This code represents a client that connects to a server on port 1248, and requests
that the server register it for communication.
d. This code represents a server that registers the port 1248 for clients wanting to
connect. Upon a request it would create a remotable object, which keeps state
information stored through the session.
5. When working with Remoting, what can be said about the following piece of code?
[Serializable()]
public class SomeObject
{
// Methods to be called
}
a. This object is located on the server. When a request comes in, the whole object is
serialized and then sent to the client.
b. This object is located on the client. When a request is made, the relevant
information is serialized and sent to the server.
c. This object is located on the server. When a request comes in, only the relevant
information is sent back.
d. This object is located on the client. When a request is made, the object is
serialized and sent to the server.
Language Comparison
C#, VB.NET, and Java
Based on the work of Frank McCown, available online at: http://www.harding.edu/fmccown/resources.html
This work is licensed under a Creative Commons license, available online at: http://creativecommons.org/licenses/by-sa/2.0/
// See if an argument was passed from ' See if an argument was passed from the // See if an argument was passed from the
the ' command line // command line
// command line If args.Length = 1 Then name = args(0) if (args.length == 1)
if (args.Length == 1) name = args[0];
name = args[0]; Console.WriteLine("Hello, " & name & System.out.println("Hello, " + name
"!") +
Console.WriteLine("Hello, " + name + End Sub "!");
"!"); End Class }
} End Namespace }
}
}
COMMENTS
// Single line Single line only // Single line
/* Multiple ''' <summary>XML comments</summary> /* Multiple
line */ line */
/// <summary>XML comments on single /** Javadoc documentation comments */
line</summary>
/** <summary>XML comments on multiple
lines</summary> */
CONSTANTS
const double PI = 3.14; Const MAX_STUDENTS As Integer = 25 // May be initialized in a constructor
// Can be set to a const or a variable. May be ’ Can set to a const or variable; may be final double PI = 3.14;
// initialized in a constructor. initialized
readonly int MAX_HEIGHT = 9; ’ in a constructor
ReadOnly MIN_DIAMETER As Single = 4.93
CHOICES
greeting = age < 20 ? "What's up?" : "Hello"; greeting = IIf(age < 20, "What's up?", "Hello") greeting = age < 20 ? "What's up?" : "Hello";
if (x < y) If(x < y) Then if (x < y) {
{ Console.WriteLine(“greater”) System.out.println("greater");
Console.WriteLine("greater"); EndIf }
}
if (x != 100) If(Not(X = 100)) Then if (x != 100) {
{ X *= 2 x *= 5;
x *= 5; y *= 2 y *= 2;
y *= 2; Else }
} Z *= 6 else
else EndIf z *= 6;
z *= 6; int selection = 2;
string colour = "red"; Dim colour As String = “red” // Must be byte, short, int, char, or enum
switch (colour) Select (colour) switch (selection) {
{ Case “red”: // Falls through to next case if no break
// break is mandatory; no fall-through r++ case 1: x++;
case "red": r++; break; Case “green”: case 2: y++; break;
case "blue": b++; break; g++ case 3: z++; break;
case "green": g++; break; Case Else: default: other++;
// break necessary on default other++ }
default: other++; break; End Select
}
ARRAYS
int[] nums = {1, 2, 3}; Dim nums As Integer() = {1, 2, 3} int nums[] = {1, 2, 3}; or int[] nums = {1,
for (int i = 0; i < nums.Length; i++) Dim i As Integer 2, 3};
Console.WriteLine(nums[i]); For i = 0 To Nums.Length for (int i = 0; i < nums.length; i++)
Console.WriteLine(nums[i]) System.out.println(nums[i]);
string[] names = new string[5]; Next String names[] = new String[5];
names[0] = "David"; Dim names(5) As String names[0] = "David";
names(0) = "David" float twoD[][] = new float[rows][cols];
float[,] twoD = new float[rows, cols]; Dim twoD(rows-1, cols-1) As Single twoD[2][0] = 4.5;
twoD[2,0] = 4.5f; twoD(2, 0) = 4.5 int[][] jagged = new int[5][];
int[][] jagged = new int[3][] { Dim jagged()() As Integer = { _ jagged[0] = new int[5];
new int[5], new int[2], new int[3] }; New Integer(4) {}, New Integer(1) {}, _ jagged[1] = new int[2];
jagged[0][4] = 5; New Integer(2) {} } jagged[2] = new int[3];
jagged(0)(4) = 5 jagged[0][4] = 5;
LOOPS
while (i < 10) While (i < 10) while (i < 10)
{ i = i + 1 {
i++; End While i++;
} }
For i = 2 To 10 Step 2
for (i = 2; i <= 10; i += 2) Console.WriteLine(i) for (i = 2; i <= 10; i += 2)
{ Next {
Console.WriteLine(i); Console.WriteLine(i);
} Do While(i < 10) }
i = i + 1
do Loop do
{ {
i++; i++;
} }
while (i < 10); while (i < 10);
// foreach can be used to iterate through any ’ For Each can be used to iterate through any // foreach can be used to iterate through any
collection ’ collection collection
foreach (int i in numArray) For Each i As Integer in numArray foreach (int i in numArray)
{ sum += i {
sum += i; Next sum += i;
} }
FUNCTIONS
// Return single value ’ Return single value // Return single value
int Add(int x, int y) Function Add(ByVal x As Integer, _ int Add(int x, int y) {
{ ByVal y As Integer) As Integer return x + y;
return x + y; return x + y }
} End Function int sum = Add(2, 3);
int sum = Add(2, 3); Dim sum As Integer = Add(2, 3)
EXCEPTION HANDLING
’ Throw an exception // Must be in a method that is declared to
Exception up = new Exception("Something is really Dim ex As New _ throw
wrong."); Exception("Something is really wrong.") // this exception
throw ex; Throw ex Exception ex = new Exception("Something is
' Catch an exception really
try Try wrong.");
{ y = 0 throw ex;
y = 0; x = 10 / y try {
x = 10 / y; ' Argument and When is optional y = 0;
} Catch ex As Exception When y = 0 x = 10 / y;
catch (Exception ex) // Variable "ex" is } catch (Exception ex) {
{ // optional Console.WriteLine(ex.Message) System.out.println(ex.getMessage());
Console.WriteLine(ex.Message); Finally } finally {
} Beep() // Code that always gets executed
finally End Try }
{
// Code that always gets executed
}
STRINGS
// String concatenation ’ String concatenation // String concatenation
string school = "Harding "; Dim school As String = "Harding " String school = "Harding ";
NAMESPACES
namespace CTIGroup.CTI.HO Namespace CTIGroup.Cti.HO package CTIGroup.CTI.HO;
{ ...
... End Namespace
} ' or
or Namespace Harding
namespace CTIGroup Namespace Compsci
{ Namespace Graphics
namespace CTI ... // Import single class
{ End Namespace import CTIGroup.CTI.HO.Table;
namespace HO End Namespace // Import all classes
{ End Namespace import CTIGroup.CTI.HO.*;
... Imports CTIGroup.CTI.HO
}
}
// Import all class. Can't import single class.
using CTIGroup.CTI.HO;
CLASSES / INTERFACES
Accessibility keywords Accessibility keywords Accessibility keywords
public Public public
private Private private
internal Friend protected
protected Protected static
protected internal Protected Friend
static Shared
CONSTRUCTORS / DESTRUCTORS
class SuperHero Class SuperHero class SuperHero {
{ Private _powerLevel As Integer private int mPowerLevel;
private int mPowerLevel; public SuperHero() {
Public Sub New() mPowerLevel = 0;
public SuperHero() _powerLevel = 0 }
{ End Sub
mPowerLevel = 0;
}
public SuperHero(int powerLevel) Public Sub New(ByVal powerLevel As Integer) public SuperHero(int powerLevel) {
{ Me._powerLevel = powerLevel this.mPowerLevel= powerLevel;
this.mPowerLevel= powerLevel; End Sub }
} // No destructors, just override the finalize
Protected Overrides Sub Finalize() // method
~SuperHero() ' Destructor code to free unmanaged resources protected void finalize() throws Throwable {
{ MyBase.Finalize() // Always call parent's finalizer
// Destructor code to free unmanaged End Sub super.finalize();
resources. End Class }
// Implicitly creates a Finalize method. }
}
CONSOLE I/O
Console.Write("What's your name? "); Console.Write("What's your name? ") System.out.print("What's your name? ");
string name = Console.ReadLine(); Dim name As String = Console.ReadLine() string name = in.readline();
Console.Write("How old are you? "); Console.Write("How old are you? ") System.out.print("How old are you? ");
int age = Convert.ToInt32(Console.ReadLine()); Dim age As Integer = Val(Console.ReadLine()) int age = Integer.parseInt(in.readline());
Console.WriteLine(name + " is " + age + Console.WriteLine("{0} is {1} years old.", name, System.out.println(name + “ is “ + age + “
" years old."); _ years
age) old”);
int c = Console.Read(); // Read single char ' or
Console.WriteLine(c); // Prints 65 if user Console.WriteLine(name & " is " & age & _ int c;
// enters "A" " years old.") c = in.read();
System.out.println(in);
Dim c As Integer
c = Console.Read() ' Read single char
Console.WriteLine(c) ' Prints 65 if user enters
"A"
USING OBJECTS
Dim hero As SuperHero = New SuperHero
' or
SuperHero hero = new SuperHero(); Dim hero As New SuperHero
With hero SuperHero hero = new SuperHero();
hero.Name = "SpamMan"; .Name = "SpamMan" hero.setName("SpamMan");
hero.PowerLevel = 3; .PowerLevel = 3 hero.setPowerLevel(3);
hero.Defend("Laura Jones"); End With
SuperHero.Rest(); // Calling static method hero.Defend("Laura Jones") hero.Defend("Laura Jones");
hero.Rest() ' Calling Shared method SuperHero.Rest(); // Calling static method
// Both refer to same object ' or
SuperHero hero2 = hero; SuperHero.Rest() // Both refer to same object
' Both reference the same object SuperHero hero2 = hero;
hero2.Name = "WormWoman"; Dim hero2 As SuperHero = hero hero2.setName("WormWoman");
hero2.Name = "WormWoman"
// Prints WormWoman ' Prints WormWoman // Prints WormWoman
Console.WriteLine(hero.Name); Console.WriteLine(hero.Name) System.out.println(hero.getName());
// Free the object ' Free the object // Free the object
hero = null ; hero = Nothing hero = null;
If hero Is Nothing Then _ if (hero == null)
if (hero == null) hero = New SuperHero {
{ Dim obj As Object = New SuperHero hero = new SuperHero();
hero = new SuperHero(); If TypeOf obj Is SuperHero Then _ }
} Console.WriteLine("Is a SuperHero object.")
Object obj = new SuperHero();
Object obj = new SuperHero(); Using reader As StreamReader = _ System.out.println("object's type: " +
Console.WriteLine("object's type: " + File.OpenText("test.txt") obj.getClass().toString());
obj.GetType().ToString());
Dim line As String = reader.ReadLine() if (obj instanceof SuperHero)
if (obj is SuperHero) While Not line Is Nothing {
{ Console.WriteLine(line) System.out.println("Is a SuperHero object.");
line = reader.ReadLine() }
Console.WriteLine("Is a SuperHero object."); End While
} End Using
PROPERTIES
private int mSize; Private mSize As Integer private int mSize;
public int Size { Public Property Size() As Integer public int getSize() { return mSize; }
get Get public void setSize(int value) {
{ Return mSize if (value < 0)
return mSize; End Get mSize = 0;
} else
set Set mSize = value;
{ If (value < 0) Then }
if (value < 0) mSize = 0
{ Else int s = shoe.getSize();
mSize = 0; mSize = value shoe.setSize(s+1);
} End If
else End Set
{ End Property
mSize = value;
} shoe.Size = shoe.Size + 1;
}
}
shoe.Size++;
STRUCTS
No structs in Java.
struct StudentRecord Structure StudentRecord
{ Public name As String
public string name; Public gpa As Single
public float gpa;
Public Sub New(ByVal name As String, _
public StudentRecord(string name, float gpa) ByVal gpa As Single)
{ Me.name = name
this.name = name; Me.gpa = gpa
this.gpa = gpa; End Sub
} End Structure
} Dim stu As StudentRecord = _
New StudentRecord("Bob", 3.5)
StudentRecord stu = new StudentRecord("Bob",
3.5f); Dim stu2 As StudentRecord = stu
StudentRecord stu2 = stu;
stu2.name = "Sue"
stu2.name = "Sue"; Console.WriteLine(stu.name) ' Prints Bob
Console.WriteLine(stu.name); // Prints Bob Console.WriteLine(stu2.name) ' Prints Sue
Console.WriteLine(stu2.name); // Prints Sue
FILE I/O
using System.IO; Imports System.IO import java.io.*;
// Character stream writing ' Write out to text file // Character stream writing
StreamWriter writer = Dim writer As StreamWriter = FileWriter writer = new
File.CreateText("myfile.txt"); File.CreateText("myfile.txt") FileWriter("myfile.txt");
writer.WriteLine("Out to file."); writer.WriteLine("Out to file.") writer.write("Out to file.\n");
writer.Close(); writer.Close() writer.close();
Bibliography
Books
1. Michaelis, M., Essential C# 3.0: For .NET Framework 3.5. ISBN: 978-0-321-53392-0
4. Deitel, PJ, Deitel, HM., C# 2008 Programmers Third Edition. ISBN: 978-0-13-714415-0
Websites
2. http://www.blackwasp.co.uk : Blackwasp
3. http://www.akadia.com/ : Akadia
5. http://www.ondotnet.com/ : OnDotNet
4.1.2 Windows User Control Exercises 4.3.3 Deploying a Windows Application 4.5.7 Attributes Revision questions
(Page 18) Revision questions (Page 34) continue… (Page 45)
(Complete exercise on paper) (Complete exercise on paper) (Complete exercise on paper)
2 _________ ________
2 _________ ________ 1 _________ ________
4.6.5 Reflection Revision questions (Page
3 _________ ________ 2 _________ ________ 50)
(Complete exercise on paper)
4 _________ ________ 3 _________ ________
1 _________ ________
4.2.6 DateTime data type Exercises (Page 4.4.3 Maintaining and Supporting a
24) Windows Application Revision questions 2 _________ ________
(Complete exercise on paper) (Page 39)
(Complete exercise on paper)
4.7.7 File I/O Exercises (Page 61)
1 _________ ________ (Complete exercise on paper)
1 _________ ________
2 _________ ________ 1 _________ ________
2 _________ ________
4.2.6 DateTime data type Revision 2 _________ ________
questions (Page 24) 3 _________ ________
(Complete exercise on paper)
4.5.6 Attributes Exercises (Page 45)
3 _________ ________
1 _________ ________ (Complete exercise on paper)
4 _________ ________
2 _________ ________ 1 _________ ________
5 _________ ________
3 _________ ________ 2 _________ ________
4.7.8 File I/O Revision questions (Page 62)
(Complete exercise on paper)
4.3.2 Deploying a Windows Application 3 _________ ________
Exercises (Page 34)
(Complete exercise on paper)
4.5.7 Attributes Revision questions (Page
1 _________ ________
45)
1 _________ ________ (Complete exercise on paper) 2 _________ ________
4.7.8 File I/O Revision questions Unit 4 – Test your knowledge Multiple 5.2.3 Microsoft Visual Web Developer
continue… (Page 62) choice continue… (Page 88) Express Edition IDE Exercises continue…
(Complete exercise on paper) (Complete exercise on paper) (Page 105)
(Complete exercise on paper)
4 _________ ________ 1 _________ ________
3 _________ ________
4.8.13 ADO.NET Exercises (Page 88) 2 _________ ________
(Complete exercise on paper) 5.2.8 Microsoft Visual Web Developer
Express Edition IDE Revision questions
3 _________ ________ (Page 105)
1 _________ ________ (Complete exercise on paper)
4 _________ ________
2 _________ ________ 1 _________ ________
5 _________ ________
3 _________ ________ 2 _________ ________
Unit 4 – Test your knowledge Multiple
4 _________ ________ response (Page 90) 3 _________ ________
(Complete exercise on paper)
5 _________ ________ 5.3.5 ASP.NET: Events and controls
1 _________ ________ Exercises (Page 125)
(Complete exercise on paper)
6 _________ ________
2 _________ ________
1 _________ ________
7 _________ ________
3 _________ ________
4.8.14 ADO.NET Exercises (Page 88)
2 _________ ________
(Complete exercise on paper) 4 _________ ________
3 _________ ________
1 _________ ________ 5 _________ ________
5.3.6 ASP.NET: Events and controls
Revision questions (Page 125)
2 _________ ________ 5.1.3 ASP.NET Fundamentals Exercises (Complete exercise on paper)
(Page 95)
(Complete exercise on paper)
3 _________ ________ 1 _________ ________
1 _________ ________
4 _________ ________ 2 _________ ________
2 _________ ________
5 _________ ________ 3 _________ ________
Unit 4 – Test your knowledge True/False
3 _________ ________
5.4.4 Validating data: Validation Controls
(Page 88) Exercises (Page 137)
(Complete exercise on paper) 5.1.4 ASP.NET Fundamentals Revision (Complete exercise on paper)
questions (Page 96
(Complete exercise on paper)
1 _________ ________ 1 _________ ________
1 _________ ________
2 _________ ________ 2 _________ ________
2 _________ ________
3 _________ ________ 3 _________ ________
3 _________ ________
4 _________ ________ 5.4.5 Validating data: Validation Controls
Revision questions (Page 137)
5.2.7 Microsoft Visual Web Developer (Complete exercise on paper)
5 _________ ________ Express Edition IDE Exercises (Page 105)
(Complete exercise on paper)
1 _________ ________
Unit 4 – Test your knowledge Multiple
choice (Page 88) 1 _________ ________
(Complete exercise on paper) 2 _________ ________
2 _________ ________
1 _________ ________ 3 _________ ________
5.5.5 Data-binding Exercises (Page 148) 5.7.5 ASP.NET Objects Exercises 6.1.6 Introduction Exercises (Page 194)
(Complete exercise on paper) continue… (Page 178) (Complete exercise on paper)
(Complete exercise on paper)
1 _________ ________ 1 _________ ________
3 _________ ________
2 _________ ________ 2 _________ ________
5.8.2 Distributing ASP.NET applications
Exercises (Page 182)
3 _________ ________ (Complete exercise on paper) 3 _________ ________
6.3.7 .NET Remoting Exercises continue… 6.4.6 Web Services Exercises (Page 252) Unit 6 – Test your knowledge Multiple
(Page 238) (Complete exercise on paper) choice (Page 261)
(Complete exercise on paper) (Complete exercise on paper)
1 _________ ________
2 _________ ________ 1 _________ ________
2 _________ ________
3 _________ ________ 2 _________ ________
6.4.7 Web Services Revision questions
4 _________ ________ (Page 252) 3 _________ ________
(Complete exercise on paper)
3 _________ ________
4 _________ ________
5 _________ ________
How would you evaluate the C# study guide? Place a or in one of the five squares
that best indicates your choice. Your response will help us to improve the quality of the
study guides and courses, and will be much appreciated.
Very
Poor Fair Good Excellent
poor
The study guide is clear and understandable.
The text material is clear and understandable.
The exercises help you grasp the course material.
The projects help you understand the course material.
You know what to expect in the exam.
The practical exercises test your knowledge and ability.
Your instructor was able to help you.
________________________________________________________________________
________________________________________________________________________
Please note any errors that you found in the study guide.
Thank you for completing the evaluation form. Please remove this evaluation form and
return it to your instructor.