Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Pro CSharp And The .NET 2.0 Platform (2005) [eng]

.pdf
Скачиваний:
111
Добавлен:
16.08.2013
Размер:
10.35 Mб
Скачать

844 CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

Figure 23-9. The Default.aspx UI

Now, click the Source button at the bottom of your code window and locate the <form> section of your page. Notice how each web control has been defined using an <asp:> tag. Before the closing tag, you will find a series of name/value pairs that correspond to the settings you made in the Properties window:

<form id="form1" runat="server"> <div>

<asp:Label ID="lblInfo" runat="server" Text="Click on the Button to Fill the Grid">

</asp:Label>

<asp:GridView ID="carsGridView" runat="server"> </asp:GridView>

<asp:Button ID="btnFillData" runat="server" Text="Fill Grid" /> </div>

</form>

You will dig into the full details of ASP.NET web controls later in this chapter. Until then, understand that web controls are classes processed on the web server, and they emit back their HTML representation into the outgoing HTTP response automatically (that’s right—you don’t author the HTML!).

Beyond this major benefit, ASP.NET web controls support a Windows Forms–like programming model, given that the names of the properties, methods, and events mimic their Windows Forms equivalents. To illustrate, handle the Click event for the Button type using either the Visual Studio Properties window (via the lightning-bolt icon) or using the drop-down boxes mounted at the top of the Source view window. Once you do, you will find your Button’s definition has been updated with an OnClick attribute that is assigned to the name of your Click event handler:

<asp:Button ID="btnFillData" runat="server" Text="Fill Grid" OnClick="btnFillData_Click" />

As well, your <script> block has been updated with a server-side Click event handler (notice that the incoming parameters are a dead-on match for the target of the System.EventHandler delegate):

<script runat="server">

protected void btnFillData_Click(object sender, EventArgs e)

{

}

</script>

CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

845

Implement your server-side event handler to make use of an ADO.NET data reader to fill the GridView. Also add an import directive (more details on this in just a moment) that specifies you are using the System.Data.SqlClient namespace. Here is the remaining relevant page logic of the

Default.aspx file:

<%@ Page Language="C#" %>

<%@ Import Namespace = "System.Data.SqlClient" %>

...

<script runat="server">

protected void btnFillData_Click(object sender, EventArgs e)

{

SqlConnection sqlConn =

new SqlConnection("Data Source=.;Initial Catalog=Cars;UID=sa;PWD="); sqlConn.Open();

SqlCommand cmd =

new SqlCommand("Select * From Inventory", sqlConn); carsGridView.DataSource = cmd.ExecuteReader(); carsGridView.DataBind();

sqlConn.Close();

}

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >

...

</html>

Before we dive into the details behind the format of this *.aspx file, let’s try a test run. Open a Visual Studio 2005 command prompt and run the WebDev.WebServer.exe utility, making sure you specify the path where you saved your Default.aspx file:

webdev.webserver.exe /port:12345 /path:"C:\CodeTests\SinglePageModel"

Now, using your browser of choice, enter the following URL:

http://localhost:12345/

When the page is served, you will initially see your Label and Button types. However, when you click the Button, a postback occurs to the web server, at which point the web controls render back their corresponding HTML tags. Figure 23-10 shows the page hosted within Mozilla Firefox.

Figure 23-10. Web-based data access

846 CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

That was simple, yes? Of course, as they say, the devil is in the details, so let’s dig a bit deeper into the composition of this *.aspx file.

The <%@Page%> Directive

The first thing to be aware of is that a given *.aspx file will typically open with a set of directives. ASP.NET directives are always denoted with <%@ XXX %> markers and may be qualified with various attributes to inform the ASP.NET runtime how to process the attribute in question.

Every *.aspx file must have at minimum a <%@Page%> directive that is used to define the managed language used within the page (via the language attribute). Also, the <%@Page%> directive may define the name of the related code-behind file (if any), enable tracing support, and so forth. Table 23-2 documents some of the more interesting <%@Page%>-centric attributes.

Table 23-2. Select Attributes of the <%@Page%> Directive

Attribute

Meaning in Life

CompilerOptions

Allows you to define any command-line flags (represented as a single

 

string) passed into the compiler when this page is processed.

CodePage

Specifies the name of the related code-behind file.

EnableTheming

Establishes if the controls on the *.aspx page support ASP.NET 2.0

 

themes

EnableViewState

Indicates whether view state is maintained across page requests (more

 

details on this in Chapter 24)

Inherits

Defines a class in the code-behind page the *.aspx file derives from,

 

which can be any class derived from System.Web.UI.Page

MasterPageFile

Sets the master page used in conjunction with the current *.aspx page

Trace

Indicates whether tracing is enabled

 

 

The <%Import%> Directive

In addition to the <%@Page%> directive, a given *.aspx file may specify various <%@Import%> directives to explicitly state the namespaces required by the current page. Here, you specified you were making use of the types within the System.Data.SqlClient namespace. As you would guess, if you need to make use of additional .NET namespaces, you simply specify multiple <%@Import%> directives.

Note The <%@Import%> directive is not necessary if you are making use of the code-behind page model. When you do make use of code-behind, you will specify external namespaces using the C# using keyword.

Given your current knowledge of .NET, you may wonder how this *.aspx file avoided specifying the System.Data or System namespaces. The reason is that all *.aspx pages automatically have access to a set of key namespaces, including the following:

System

System.Collections

System.Collections.Generic

System.Configuration

System.IO

CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

847

System.Text

System.Text.RegularExpressions

All of the System.Web-centric namespaces

ASP.NET does define a number of other directives that may appear in an *.aspx file above and beyond <%@Page%> and <%@Import%>; however, I’ll reserve commenting on those for the time being.

The “Script” Block

Under the single-file page model, an *.aspx file may contain server-side scripting logic that executes on the web server. Given this it is critical that all of your server-side code blocks are defined to execute at the server, using the runat="server" attribute. If the runat="server" attribute is not supplied, the runtime assumes you have authored a block of client-side script to be emitted into the outgoing HTTP response:

<script runat="server">

protected void btnFillData_Click(object sender, EventArgs e)

{

}

</script>

The signature of this helper method should look strangely familiar. Recall from our examination of Windows Forms that a given event handler must match the pattern defined by a related .NET delegate. And, just like Windows Forms, when you wish to handle a server-side button click, the delegate in question is System.EventHandler which, as you recall, can only call methods that take

a System.Object as the first parameter and a System.EventArgs as the second.

The ASP.NET Widget Declarations

The final point of interest is the declaration of the Button, Label, and GridView Web Form controls. Like classic ASP and raw HTML, ASP.NET web widgets are scoped within <form> elements. This time, however, the opening <form> element is marked with the runat="server" attribute. This again is critical, as this tag informs the ASP.NET runtime that before the HTML is emitted into the response stream, the contained ASP.NET widgets have a chance to render their HTML appearance:

<form id="form1" runat="server">

...

</form>

ASP.NET web controls are declared with <asp> and </asp> tags, and they are also marked with the runat="server" attribute. Within the opening tag, you will specify the name of the Web Form control and any number of name/value pairs that will be used at runtime to render the correct HTML.

Source Code The SinglePageModel example is included under the Chapter 23 subdirectory.

Working with the Code-behind Page Model

To illustrate the code-behind page model, let’s re-create the previous example using the Visual Studio 2005 Web Site template (do know that Visual Studio 2005 is not required to build pages using code-behind). Activate the File New Web Site menu option, and select the ASP.NET Web Site template (see Figure 23-11).

848 CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

Figure 23-11. The Visual Studio 2005 ASP.NET Web Site template

Notice in Figure 23-11 that you are able to select the location of your new site. If you select File System, your content files will be placed within a local directory and pages will be served via WebDev. WebServer.exe. If you select FTP or HTTP, your site will be hosted within a virtual directory maintained by IIS. For this example, it makes no difference which option you select, but for simplicity I’d suggest the File System option.

Note When you create an ASP.NET website, Visual Studio 2005 will place the solution file (*.sln) under the My Documents\Visual Studio 2005\Projects directory. Your site’s content files (such as the *.aspx files) will be located under the specified local directory or (if using IIS) within the physical file mapped to the virtual directory.

Once again, make use of the designer to build a UI consisting of a Label, Button, and GridView, and make use of the Properties window to build a UI of your liking. Now, click the Source button at the bottom of your code window, and you will see the expected <asp> and </asp> tags. Also note that the <%@Page%> directive has been updated with two new attributes:

<%@ Page Language="C#" AutoEventWireup="true"

CodeFile="Default.aspx.cs" Inherits="_Default" %>

The CodeFile attribute is used to specify the related external file that contains this page’s coding logic. By default, these code-behind files are named by suffixing .cs to the name of the *.aspx file (Default.aspx.cs in this example). If you examine Solution Explorer, you will see this code-behind file is visible via a subnode on the Web Form icon (see Figure 23-12).

CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

849

Figure 23-12. The associated code-behind file for a given *.aspx file

Note The ASP.NET 1.x Codebehind attribute is no longer supported within the <%@Page%> directive.

Beyond a number of using statements to specify several web-centric namespaces, your codebehind file defines a partial class deriving from System.Web.UI.Page. Notice that the name of this class (_Default) is identical to the Inherits attribute within the <%@Page%> directive (more details on Page_Load() a bit later in this chapter):

public partial class _Default : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

}

}

Handle the Click event for the Button type (again, just like you would for a Windows Forms application). As before, the Button definition has been updated with an OnClick attribute. However, the server-side event handler is no longer placed within a <script> scope of the *.aspx file, but as a method of the _Default class type. To complete this example, add a using statement for System.Data.

SqlClient inside your code-behind file and implement the handler using the previous ADO.NET logic:

protected void btnFillGrid_Click(object sender, EventArgs e)

{

SqlConnection sqlConn =

new SqlConnection("Data Source=.;Initial Catalog=Cars;UID=sa;PWD="); sqlConn.Open();

SqlCommand cmd =

new SqlCommand("Select * From Inventory", sqlConn); carsGridView.DataSource = cmd.ExecuteReader(); carsGridView.DataBind();

sqlConn.Close();

}

If you selected the File System option, WebDev.WebServer.exe starts up automatically when you run your web application (if you selected IIS, this obviously does not occur). In either case, the default browser should now display the page’s content.

Debugging and Tracing ASP.NET Pages

By and large, when you are building ASP.NET web projects, you can use the same debugging techniques as you would with any other sort of Visual Studio 2005 project type. Thus, you can set

850CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

breakpoints in your code-behind file (as well as embedded “script” blocks in an *.aspx file), start a debug session (the F5 key by default), and step through your code.

However, to debug your ASP.NET web applications, your site must contain a property-constructed Web.config file. Chapter 24 will examine various details behind Web.config files, but in a nutshell these XML files provide the same general purpose as an executable assembly’s app.config file. Visual Studio 2005 will detect if your project does not currently have a Web.config file and insert such a file into your project. The relevant element is <compilation>:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

...

<system.web>

<compilation debug="true"/>

</system.web>

</configuration>

You are also able to enable tracing support for an *.aspx file by setting the Trace attribute to true within the <%@Page%> directive:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Trace="true" %>

Once you do, the emitted HTML now contains numerous details regarding the previous HTTP request/response (server variables, session and application variables, request/response, etc.). To insert your own trace messages into the mix, you can use the Trace property of the System.Web.UI.Page type. Any time you wish to log a custom message (from a script block or C# source code file), simply call the Write() method:

protected void btnFillGrid_Click(object sender, EventArgs e)

{

// Emit a custom trace message.

Trace.Write("My Category", "Filling the grid!");

...

}

If you run your project once again and post back to the web server, you will find your custom category and custom message are present and accounted for. In Figure 23-13, take note of the final message before the “Control Tree” section.

Figure 23-13. Logging custom trace messages

CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

851

Source Code The CodeBehindPageModel example is included under the Chapter 23 subdirectory.

Details of an ASP.NET Website Directory Structure

If you have created web applications using ASP.NET 1.x, you may be quite surprised to see that many familiar files (Web.config, Global.asax, AssemblyInfo.cs, and so on) are not included when creating a new website. As well, the Web Site template contains a folder named App_Data and does not appear to have References folder within Solution Explorer.

First of all, do know that Web.config and Global.asax files are most certainly supported under ASP.NET 2.0, but you will need to explicitly add them to your project using the WebSite Add New Item menu option. Chapter 24 will examine the role of both of these file types, so don’t sweat the details for now. Next, be aware that your websites are still able to add references to any number of external .NET assemblies via the WebSite Add Reference menu option (the end result is a bit different, however, as you will soon see).

Another significant difference is that under Visual Studio 2005, websites may contain any number of specifically named subdirectories, each of which has a special meaning to the ASP.NET runtime. Table 23-3 documents these “special subdirectories.”

Table 23-3. Special ASP.NET 2.0 Subdirectories

Subfolder

Meaning in Life

App_Browsers

Folder for browser definition files that are used to identify individual

 

browsers and determine their capabilities.

App_Code

Folder for source code for components or classes that you want to

 

compile as part of your application. ASP.NET compiles the code in this

 

folder when pages are requested. Code in the App_Code folder is

 

automatically accessible by your application.

App_Data

Folder for storing Access *.mdb files, SQL Express *.mdf files, XML files,

 

or other data stores.

App_GlobalResources

Folder for *.resx files that are accessed programmatically from

 

application code.

App_LocalResources

Folder for *.resx files that are bound to a specific page.

App_Themes

Folder that contains a collection of files that define the appearance of

 

ASP.NET web pages and controls.

App_WebReferences

Folder for proxy classes, schemas, and other files associated with using

 

a web service in your application.

Bin

Folder for compiled private assemblies (*.dll files). Assemblies in the

 

Bin folder are automatically referenced by your application.

 

 

If you are interested in adding any of these known subfolders to your current web application, you may do so explicitly using the WebSite Add Folder menu option. However, in many cases, the IDE will automatically do so as you “naturally” insert related files into your site (e.g., adding a new C# file will automatically add an App_Code folder to your directory structure if one does not currently exist).

852 CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

The Role of the Bin folder

As described in a few pages, ASP.NET web pages are eventually compiled into a .NET assembly. Given this, it should come as no surprise that your websites can reference any number of private or shared assemblies. Under ASP.NET 2.0, the manner in which your site’s externally required assemblies are recorded is quite different from ASP.NET 1.x. The reason for this fundamental shift is that Visual Studio 2005 now treats websites in a projectless manner.

Although the Web Site template does generate a *.sln file to load your *.aspx files into the IDE, there is no longer a related *.csproj file. As you may know, ASP.NET 1.x Web Application projects recorded all external assemblies within *.csproj. This fact brings up the obvious question, where are the external assemblies recorded under ASP.NET 2.0?

When you reference a private assembly, Visual Studio 2005 will automatically create a Bin directory within your directory structure to store a local copy of the binary. When your code base makes use of types within these code libraries, they are automatically loaded on demand. By way of a simple test, if you activate the WebSite Add Reference menu option and select any of the previous (non–strongly named) *.dlls you created over the course of this text, you will find a Bin folder is displayed within Solution Explorer (see Figure 23-14).

Figure 23-14. The Bin folder contains copies of all referenced private assemblies.

If you reference a shared assembly, Visual Studio 2005 automatically inserts a Web.config file into your current web solution (if one is not currently in place) and records the external reference within the <assemblies> element. For example, if you again activate the WebSite Add Reference menu option and this time select a shared assembly (such as System.Drawing.dll), you will find that your Web.config file has been updated as so:

<?xml version="1.0"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <appSettings/>

<connectionStrings/>

<system.web>

<compilation debug="false">

<assemblies>

<add assembly="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>

</assemblies>

</compilation>

<authentication mode="Windows"/> </system.web>

</configuration>

As you can see, each assembly is described using the same information required for a dynamic load via the Assembly.Load() method (see Chapter 12).

CHAPTER 23 ASP. NET 2 . 0 WEB PAGES AND WEB CONTROLS

853

The Role of the App_Code Folder

The App_Code folder is used to place source code files that are not directly tied to a specific web page (such as a code-behind file) but are to be compiled for use by your website. Code within the App_Code folder will be automatically compiled on the fly on an as-needed basis. After this point, the assembly is accessible to any other code in the website. To this end, the App_Code folder is much like the Bin folder, except that you can store source code in it instead of compiled code. The major benefit of this approach is that it is possible to define custom types for your web application without having to compile them independently.

A single App_Code folder can contain code files from multiple languages. At runtime, the appropriate compiler kicks in to generate the assembly in question. If you would rather partition your code, however, you can define multiple subdirectories that are used to hold any number of managed code files (*.cs, *.vb, etc.).

For example, assume you have added an App_Code folder to the root directory of a website application that contains two subfolders (MyCSharpCode and MyVbNetCode) that contain languagespecific files. Once you do, you are able to author a Web.config file that specifies these subdirectories using a <codeSubDirectories> element:

<?xml version="1.0"?>

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <appSettings/>

<connectionStrings/>

<system.web>

<compilation debug="false"> <assemblies>

<add assembly="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>

</assemblies>

<codeSubDirectories>

<add directoryName="MyCSharpCode" /> <add directoryName="MyVbNetCode" />

</codeSubDirectories>

</compilation>

<authentication mode="Windows"/> </system.web>

</configuration>

Note The App_Code directory will also be used to contain files that are not language files, but are useful nonetheless (*.xsd files, *.wsdl files, etc.).

The ASP.NET 2.0 Page Compilation Cycle

Regardless of which page model you make use of (single-file or code-behind), your *.aspx files (and any related code-behind file) are compiled on the fly into a valid .NET assembly. This assembly is then hosted by the ASP.NET worker process (aspnet_wp.exe) within its own application domain boundary (see Chapter 13 for details on AppDomains). The manner in which your website’s assembly is compiled under ASP.NET 2.0, however, is quite different.

Compilation Cycle for Single-File Pages

If you are making use of the single-file page model, the HTML markup, <script> blocks, and web control definitions are dynamically compiled into a class type deriving from System.Web.UI.Page.