Declaring Methods The simple HelloWorld component in Listing 17.1 contains a single method named SayMessage, which returns a string value.. In other words, you must create a new instance
Trang 1</div>
</form>
</body>
</html>
In the Page_Load() event handler, an instance of the HelloWorld component is created
Next, the result returned by a call to the SayMessage() method is assigned to a Label
control When you open the page in your browser, you see the message Hello World!
This process of creating the component is simple You don’t need to perform any special
registration, and you don’t need to compile anything explicitly Everything just works
magically
Components and Dynamic Compilation
You are not required to explicitly compile (build) the component because ASP.NET
Framework automatically compiles the component for you Any component that you add
to the App_Code folder is compiled dynamically in the same way as an ASP.NET page If
you add a new component to the App_Code folder and request any page from your
website, the contents of the App_Code folder are compiled into a new assembly and saved
to the Temporary ASP.NET Files folder, located at the following path:
C:\WINDOWS\Microsoft.NET\Framework\[version]\
Temporary ASP.NET Files\[application name]
Whenever you modify the component, the existing assembly in the Temporary ASP.NET
Files folder is deleted The App_Code folder is compiled again when you make a new
page request
NOTE
An assembly is the dll file (or dll files) in which components are stored
You can add as many subfolders to the App_Code folder as you need to organize your
components The ASP.NET Framework finds your component no matter how deeply you
nest the component in a subfolder
One significant drawback of this process of dynamic compilation is that any errors in any
component contained in the App_Code folder prevent any pages from executing Even if a
page does not use a particular component, any syntax errors in the component raise an
exception when you request the page
Trang 2TIP
If a component contains an error, and you want to temporarily hide the component from
ASP.NET Framework, change the file extension to an extension that ASP.NET Framework
does not recognize, such as HelloWorld.cs.exclude Visual Web Developer uses this
method to hide a component when you right-click a component and select the menu
option Exclude From Project
Mixing Different Language Components in the App_Code Folder
You don’t have to do anything special if all the components in the App_Code folder are
written in the same language For example, if you use Visual Basic NET to create all your
components, the ASP.NET Framework automatically infers the language of your
compo-nents and everything just works
However, if you mix components written in more than one language in the App_Code
folder—for example, Visual Basic NET and C#— you must perform some extra steps
First, you need to place components written in different languages in different subfolders
You can name the subfolders anything you want The point is to not mix different
language components in the same folder
Furthermore, you need to modify your web configuration file to recognize the different
subfolders For example, if you create two subfolders in the App_Code folder named
VBCode and CSCode, you can use the web configuration file in Listing 17.3 to use
compo-nents written in both VB.NET and C#
LISTING 17.3 Web.Config
<?xml version=”1.0”?>
<configuration>
<system.web>
<compilation>
<codeSubDirectories>
<add directoryName=”VBCode” />
<add directoryName=”CSCode” />
</codeSubDirectories>
</compilation>
</system.web>
</configuration>
When the contents of the App_Code folder are compiled, two assemblies are created: one
that corresponds to the VBCode folder and one that corresponds to the CSCode folder
You don’t need to indicate the language used for each folder—ASP.NET Framework infers
the language for you
Trang 3There is nothing wrong with mixing components written in different languages in the
same ASP.NET page After a component is compiled, NET Framework treats VB.NET and
C# components in the same way
Declaring Methods
The simple HelloWorld component in Listing 17.1 contains a single method named
SayMessage(), which returns a string value When writing components with Visual Basic
.NET, you create methods by creating either a subroutine or a function Use a subroutine
when a method does not return a value, and use a function when a method does return a
value
The SayMessage() method in Listing 17.1 is an instance method In other words, you
must create a new instance of the HelloWorld class before you can call the SayMessage()
method like this:
HelloWorld objHelloWorld = new HelloWorld();
lblMessage.Text = objHelloWorld.SayMessage();
In the first line, a new instance of the HelloWorld component is created The
SayMessage() method is called from this instance For this reason, the SayMessage()
method is an instance method
As an alternative to creating an instance method, you can create a static method The
advantage of a static method is that you do not need to create an instance of a
compo-nent before calling it For example, the SayMessage() method in the modified HelloWorld
component in Listing 17.4 is a static method
NOTE
Static methods are called shared methods in Visual Basic NET.
LISTING 17.4 StaticHelloWorld.cs
public class StaticHelloWorld
{
public static string SayMessage()
{
return “Hello World!”;
}
}
The StaticHelloWorld component defined in Listing 17.3 is exactly the same as the
HelloWorld component created in Listing 17.1 with one change: The SayMessage()
method includes a static modifier
Trang 4The page in Listing 17.5 uses the StaticHelloWorld component to display the Hello
World! message
LISTING 17.5 ShowStaticHelloWorld.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
void Page_Load()
{
lblMessage.Text = StaticHelloWorld.SayMessage();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Shared Hello World</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Label
id=”lblMessage”
Runat=”server” />
</div>
</form>
</body>
</html>
The page in Listing 17.5 does not create an instance of the StaticHelloWorld component
The SayMessage() method is called directly from the StaticHelloWorld class
The advantage of using static methods is that they save you typing You don’t have to go
through the pain of instantiating a component before calling the method Many classes in
.NET Framework include static methods For example, String.Format(),Int32.Parse(),
and DateTime.DaysInMonth() methods are all static methods
There is nothing wrong with mixing both static and instance methods in the same
component For example, you might want to create a Product component that has a static
GetProducts() method and an instance SaveProduct() method
Trang 5The one significant limitation of using a static method is that a static method cannot refer
to an instance field or property In other words, static methods must be stateless
Declaring Fields and Properties
You can define a property for a component in two ways: the lazy way and the virtuous
way The lazy way to create a property is to create a public field If you declare any field
with the Public access modifier, the field can be accessed from outside the component For
example, the component in Listing 17.6 contains a public field named Message
LISTING 17.6 FieldHelloWorld.cs
public class FieldHelloWorld
{
public string Message;
public string SayMessage()
{
return Message;
}
}
The Message field is declared near the top of the FieldHelloWorld class definition The
Message field is returned by the SayMessage() method
The page in Listing 17.7 uses the FieldHelloWorld component to display a message
LISTING 17.7 ShowFieldHelloWorld.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
void Page_Load()
{
FieldHelloWorld objFieldHelloWorld = new FieldHelloWorld();
objFieldHelloWorld.Message = “Good Day!”;
lblMessage.Text = objFieldHelloWorld.SayMessage();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Field Hello World</title>
Trang 6<body>
<form id=”form1” runat=”server”>
<div>
<asp:Label
id=”lblMessage”
Runat=”server” />
</div>
</form>
</body>
</html>
In the Page_Load() event handler in Listing 17.7, an instance of the FieldHelloWorld
class is created, a value is assigned to the Message field, and the SayMessage() method is
called
There are a couple of serious disadvantages to creating properties by creating public fields
First, NET Framework recognizes properties as separate entities Several methods in NET
Framework recognize properties but not fields
For example, you can refer to component properties and not fields when using the Eval()
method in a databinding expression If you want to bind a collection of Product objects to
a GridView control, you should expose the properties of the Product component as true
properties and not as fields
The other disadvantage of fields is that they do not provide you with a chance to validate
the value assigned to the field For example, imagine that a property represents a database
column and the column accepts no more than five characters In that case, you should
check whether the value assigned to the property is less than five characters
The component in Listing 17.8 uses a property instead of a field (It does things the
virtuous way.)
LISTING 17.8 PropertyHelloWorld.cs
using System;
public class PropertyHelloWorld
{
private string _message;
public string Message
{
get
{
return _message;
Trang 7}
set
{
if (value.Length > 5)
throw new Exception(“Message too long!”);
_message = value;
}
}
public string SayMessage()
{
return _message;
}
}
The component in Listing 17.8 contains a property named Message and a private backing
field named _message The Message property contains both a getter (get) and a setter (set)
The getter is called when you read the value of the Message property, and the setter is
called when you assign a value to the Message property
The getter simply returns the value of the private _message field The setter assigns a
value to the private _message field The setter throws an exception if the length of the
value assigned to the _message field exceeds five characters
NOTE
In Listing 17.8, the private field is named _message The underscore character (_) has
no programmatic significance By convention, private members of a class are named
with a leading underscore, but there is nothing wrong with following some other
convention
NOTE
The version of C# included with NET Framework 3.5 and 4 supports the automatic
properties feature Automatic properties provide you with a shorthand syntax for
creat-ing a property with a backcreat-ing field To learn more about automatic properties, see
Chapter 20, “Data Access with LINQ to SQL.”
The page in Listing 17.9 uses the PropertyHelloWorld component
Trang 8LISTING 17.9 ShowPropertyHelloWorld.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
void Page_Load()
{
PropertyHelloWorld objPropertyHelloWorld = new PropertyHelloWorld();
objPropertyHelloWorld.Message = “Hello World!”;
lblMessage.Text = objPropertyHelloWorld.SayMessage();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Show Property Hello World</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Label
id=”lblMessage”
Runat=”server” />
</div>
</form>
</body>
</html>
If you open the page in Listing 17.9 in your web browser, you get a big, fat error message
(see Figure 17.2) Because a string longer than five characters is assigned to the Message
property in the Page_Load() method, the Message property raises an exception
You can also create read-only properties when the situation warrants it For example, the
component in Listing 17.10 returns the current server time It would not make sense to
assign a value to this property, so the property is declared as read-only
Trang 9ptg LISTING 17.10 ServerTime.cs
using System;
public class ServerTime
{
public string CurrentTime
{
get
{
return DateTime.Now.ToString();
}
}
}
FIGURE 17.2 Assigning more than five characters
Trang 10NOTE
You can create static fields and properties in the same way as you create shared
methods, by using the static keyword Any value you assign to a static field or
prop-erty is shared among all instances of a component
I recommend that you avoid using static fields and properties when building ASP.NET
applications Using static fields and properties raises nasty concurrency issues in a
multithreaded environment such as ASP.NET If you insist on creating a static field or
property, make it read-only
Declaring Constructors
A constructor is a special class method called automatically when you create a new
instance of a class Typically, you use the constructor to initialize private fields contained
in the class
When creating a constructor in C#, you create a method with the same name as the class
name For example, the class in Listing 17.11 displays a random quotation (see Figure
17.3) The collection of random quotations is created in the component’s constructor
FIGURE 17.3 Displaying a random quotation