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

Pro CSharp 2008 And The .NET 3.5 Platform [eng]

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

1182 CHAPTER 31 BUILDING ASP.NET WEB PAGES

You will dig into the full details of ASP.NET web controls later in Chapter 32. Until then, understand that web controls are objects processed on the web server that 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 mimic a desktoplike programming model, given that the names of the properties, methods, and events typically echo a Windows Forms/WPF equivalent.

Adding the Data Access Logic

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 designer 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, you receive an empty <script> block to author your server-side Click event handler. Add the following code, noticing that the incoming parameters are a dead-on match for the target of the System.EventHandler delegate:

<script runat="server">

void btnFillData_Click(object sender, EventArgs args)

{

}

</script>

The next step is to populate the GridView using the functionality of your AutoLotDAL.dll assembly. To do so, you must use the <%@ Import %> directive to specify you are using the AutoLotConnectedLayer namespace. In addition, you need to inform the ASP.NET runtime that this single-file page is referencing the AutoLotDAL.dll assembly, via the <%@ Assembly %> directive (more details on directives in just a moment). Here is the remaining relevant page logic of the Default.aspx file (modify your connection string as required):

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

<%@ Import Namespace = "AutoLotConnectedLayer" %> <%@ Assembly Name ="AutoLotDAL" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

void btnFillData_Click(object sender, EventArgs args)

{

InventoryDAL dal = new InventoryDAL(); dal.OpenConnection(@"Data Source=(local)\SQLEXPRESS;" +

"Initial Catalog=AutoLot;Integrated Security=True"); carsGridView.DataSource = dal.GetAllInventory(); carsGridView.DataBind();

dal.CloseConnection();

}

</script>

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

...

</html>

CHAPTER 31 BUILDING ASP.NET WEB PAGES

1183

Before we dive into the details behind the format of this *.aspx file, let’s try a test run. First, save your *.aspx file. If you wish to make use of WebDev.WebServer.exe manually, open a .NET command prompt and run the WebDev.WebServer.exe utility, making sure you specify the path where you saved your Default.aspx file, for example (here I specified an arbitrary port of 12345):

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.

As a shortcut, you can indirectly launch WebDev.WebServer.exe from Visual Studio 2008. Simply right-click the page you wish to browse and select the View In Browser menu option. In either case, Figure 31-11 shows the output once you click the Fill Grid button.

Figure 31-11. Web-based data access

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, beginning by examining the role of the page directive.

Understanding the Role of ASP.NET Directives

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 <%@ ... %> markers and may be qualified with various attributes to inform the ASP.NET runtime how to process the attribute in question.

1184 CHAPTER 31 BUILDING ASP.NET WEB PAGES

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 31-2 documents some of the more interesting <%@Page%>-centric attributes.

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

Attribute

Meaning in Life

CodePage

Specifies the name of the related code-behind file

CompilerOptions

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

 

passed into the compiler when this page is processed

EnableTheming

Establishes whether the controls on the *.aspx page support ASP.NET themes

EnableViewState

Indicates whether view state is maintained across page requests (more

 

details on this property in Chapter 33)

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

 

 

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 and <%@Assembly%> directives to specify the external code libraries used by the site (typically placed under the \bin folder of the website).

In this example, we specified we were making use of the types within the AutoLotConnectedLayer namespace within the AutoLotDAL.dll assembly. As you would guess, if you need to make use of additional .NET namespaces, you simply specify multiple <%@Import%>/

<%@Assembly%> directives.

Given your current knowledge of .NET, you may wonder how this *.aspx file avoided specifying additional <%@Import%> directives to gain access to the System namespace in order to gain access to the System.Object and System.EventHandler types (among others). The reason is that all *.aspx pages automatically have access to a set of key namespaces that are defined within the machine. config file under your installation path of the .NET platform. Within this XML-based file you would find a number of autoimported namespaces:

<pages>

<namespaces>

<add namespace="System"/>

<add namespace="System.Collections"/>

<add namespace="System.Collections.Specialized"/> <add namespace="System.Configuration"/>

<add namespace="System.Text"/>

<add namespace="System.Text.RegularExpressions"/> <add namespace="System.Web"/>

<add namespace="System.Web.Caching"/> <add namespace="System.Web.SessionState"/> <add namespace="System.Web.Security"/> <add namespace="System.Web.Profile"/> <add namespace="System.Web.UI"/>

<add namespace="System.Web.UI.WebControls"/>

<add namespace="System.Web.UI.WebControls.WebParts"/> <add namespace="System.Web.UI.HtmlControls"/>

...

CHAPTER 31 BUILDING ASP.NET WEB PAGES

1185

</namespaces>

</pages>

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

Analyzing 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">

void btnFillData_Click(object sender, EventArgs args)

{

InventoryDAL dal = new InventoryDAL(); dal.OpenConnection(@"Data Source=(local)\SQLEXPRESS;" +

"Initial Catalog=AutoLot;Integrated Security=True"); carsGridView.DataSource = dal.GetAllInventory(); carsGridView.DataBind();

dal.CloseConnection();

}

</script>

The signature of this helper method should look strangely familiar. Recall from our examination of Windows Forms (or WPF for that matter) that a given control 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 System.Object as the first parameter and System.EventArgs as the second.

Looking at the ASP.NET Control Declarations

The final point of interest for this first example 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"> <div>

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

</asp:Label> <br />

<br />

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

<br />

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

</form>

1186 CHAPTER 31 BUILDING ASP.NET WEB PAGES

Note that the 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 31 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 2008 Web Site template. (Do know that Visual Studio 2008 is not required to build pages using code-behind; however, this is the out-of-the-box behavior for new websites.) Activate the File New Web Site menu option, and select the ASP.NET Web Site template, as shown in Figure 31-12.

Figure 31-12. The Visual Studio 2008 ASP.NET Web Site template

Notice in Figure 31-12 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 new virtual directory maintained by IIS. For this example, it makes no difference which option you select, but for simplicity I suggest selecting the File System option and specifying a new folder named C:\CodeBehindPageModel.

CHAPTER 31 BUILDING ASP.NET WEB PAGES

1187

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.

Note When you wish to open an existing website into Visual Studio 2008, select the File Open Web Site menu option and select the folder (or IIS virtual directory) containing the web content.

Note that the <%@Page%> directive has been updated with a few 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 adding the suffix .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 31-13).

Figure 31-13. The associated code-behind file for a given *.aspx file

If you were to open your code-behind file, you would find a partial class deriving from System.Web.UI.Page with support for handling the Load event. Notice that the name of this class (_Default) is identical to the Inherits attribute within the <%@Page%> directive:

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

{

protected void Page_Load(object sender, EventArgs e)

{

}

}

Referencing the AutoLotDAL.dll Assembly

As previously mentioned, when creating web application projects using Visual Studio 2008, you do not need to manually build a \bin subdirectory and copy private assemblies by hand. For this example, activate the Add Reference dialog box using the Website menu option and reference AutoLotDAL.dll. When you do so, you will see the new \bin folder within Solution Explorer, as shown in Figure 31-14.

1188 CHAPTER 31 BUILDING ASP.NET WEB PAGES

Figure 31-14. Visual Studio typically maintains “special” ASP.NET folders

Updating the Code File

Handle the Click event for the Button type by double-clicking the Button placed on the designer. 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 AutoLotConnectedLayer inside your codebehind file and implement the handler using the previous logic:

using AutoLotConnectedLayer;

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

{

protected void Page_Load(object sender, EventArgs e)

{

}

protected void btnFillData_Click(object sender, EventArgs e)

{

InventoryDAL dal = new InventoryDAL(); dal.OpenConnection(@"Data Source=(local)\SQLEXPRESS;" +

"Initial Catalog=AutoLot;Integrated Security=True"); carsGridView.DataSource = dal.GetAllInventory(); carsGridView.DataBind();

dal.CloseConnection();

}

}

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 2008 project type. Thus, you can set breakpoints in your code-behind file (as well as embedded “script” blocks in an *.aspx file), start a debug session (via the F5 key, by default), and step through your code.

However, to debug your ASP.NET web applications, your site must contain a properly configured Web.config file. The conclusion of this chapter will introduce you to Web.config files, but in a

CHAPTER 31 BUILDING ASP.NET WEB PAGES

1189

nutshell these XML files have the same general purpose as an executable assembly’s App.config file. By default, all Visual Studio 2008 web projects will automatically have a Web.config file. However, debugging support is initially disabled (as this will degrade performance). When you start a debugging session, the IDE will prompt you for permissions to enable debugging. Once you have opted to do so, the <compilation> element of the Web.config file is updated like so:

<compilation debug="true"/>

On a related note, you are also able to enable tracing support for an *.aspx file by setting the Trace attribute to true within the <%@Page%> directive (it is also possible to enable tracing for your entire site by modifying the Web.config file):

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

Once you do, the emitted HTML 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. Anytime you wish to log a custom message (from a script block or C# source code file), simply call the Write() method:

protected void btnFillData_Click(object sender, EventArgs e)

{

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 31-15, take note of the highlighted message, which displays the trace information.

Figure 31-15. Logging custom trace messages

1190 CHAPTER 31 BUILDING ASP.NET WEB PAGES

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

Details of an ASP.NET Website Directory Structure

By default, new Visual Studio 2008 web applications will be provided with an initial web page, a Web.config file, and a particular folder named App_Data (which is empty by default). ASP.NET websites may contain any number of specifically named subdirectories, each of which has a special meaning to the ASP.NET runtime. Table 31-3 documents these “special subdirectories.”

Table 31-3. Special ASP.NET 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 Web Site 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., inserting a new class file into your project will automatically add an App_Code folder to your directory structure if one does not currently exist).

Referencing Assemblies

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, 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 2008 treats websites in a projectless manner.

Although the Web Site template does generate an *.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?

CHAPTER 31 BUILDING ASP.NET WEB PAGES

1191

As you have seen, when you reference a private assembly, Visual Studio 2008 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.

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

<assemblies>

<add assembly="System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>

</assemblies>

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

The Role of the App_Code Folder

The App_Code folder is used to store 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 (*.vb, *.cs, etc.).

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

<compilation debug="true" strict="false" explicit="true"> <codeSubDirectories>

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

</codeSubDirectories>

</compilation>

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.).

Beyond Bin and App_Code, the App_Data and App_Themes folders are two additional “special subdirectories” that you should be familiar with, both of which will be detailed in the next several chapters. As always, consult the .NET Framework 3.5 SDK documentation for full details of the remaining ASP.NET subdirectories if you require further information.