1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional ASP.NET 2.0 XML phần 10 pptx

54 284 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 54
Dung lượng 1,63 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Figure 15-7 displays the products that belong to the category that was selected in the categories listing page.Product Details Listing Process When the user selects a particular product

Trang 1

For the ShoppingAssistantWeb site, the CommonMaster.masterpage provides the standard headingand left navigation for all the pages The code of the CommonMaster.masteris shown in Listing 15-7.Listing 15-7: CommonMaster.master Page for Consistent Look and Feel

<asp:Table BorderStyle=Double id=”bodyTable” runat=”server”

Width=”100%” Height=”100%” ForeColor=”Black”>

ID=”categoriesListingLink” Text=”Categories Listing”>

</asp:HyperLink>

<br/><br/><br/>

What Is a Master Page?

As you learned in a previous chapter, ASP.NET 2.0 introduced a new concept known

as Master Pages, in which a common base master file is created to provide a

consis-tent layout for all the pages in a Web site Master Pages allow you to isolate the look

and feel and standard behavior for all the pages in your application to a centralized

Master Page In that page, you add placeholders (known as ContentPlaceHolder)

for the content (or child pages) to add their custom content When users request a

content page, the output of the content pages is merged with the output of the

Master Page, resulting in an output that combines the layout of the Master Page

with the output of the content page.

Trang 2

<asp:HyperLink Font-Bold=true NavigateUrl=”~/CreateUser.aspx” runat=”server” ID=”createNewLink” Text=”Create New User”>

</asp:HyperLink><br/><br/><br/>

<asp:HyperLink Font-Bold=true NavigateUrl=”~/Login.aspx”

runat=”server” ID=”loginLink” Text=”Login”>

</asp:HyperLink><br/><br/><br/>

<asp:HyperLink Font-Bold=true NavigateUrl=”~/Logout.aspx”

runat=”server” ID=”logoutLink” Text=”Logout”>

con-Login Process

In the ShoppingAssistantWeb site, the user must be logged in to browse through the different pages

of the site To this end, create a new ASP.NET page named Login.aspxthat allows the user to log intothe site The login page authenticates the user’s username and password against the Membershipstoreprovided by ASP.NET Before looking at the code of the Login.aspxpage, it is useful to briefly examinethe underlying authentication technology used by the ShoppingAssistant

How Master Pages Work?

The Master Page defines content areas using the ContentPlaceHolder control, and the content pages place their content in the areas identified by the

ContentPlaceHoldercontrol in the Master Page Pages that use a Master Page to define the layout can place content only in the areas defined by the

ContentPlaceHolder, thus enabling a consistent site design Master Pages are

saved with the file extension master and they contain the Master directive at the top of the page instead of the Page directive that is used by the traditional ASP.NET pages In addition to hosting all the contents that are required for defining the stan- dard look and feel of the application, the Master Pages also contain all the top-level HTML elements for a page, such as <html>, <head>, and <form> The Master Pages also contain one or more content placeholders that are used to define regions that will be rendered through the content pages.

Trang 3

The login feature of the Web site is implemented using forms-based authentication mechanism Theforms-based authentication technology depends on cookies to store the authentication information forthe currently logged in user After the user is authenticated, cookies are used to store and maintain ses-sion information enabling the users to identify themselves to the Web site To enable forms-basedauthentication for the ShoppingAssistantWeb site, add the following entry in the web.configfiledirectly under the <system.web>element.

<configuration>element of the web.configfile

ProductDetail.aspxpages also using similar entries in the web.configfile

Now that you have a general understanding of the forms-based authentication, you are ready to ine the Login.aspxpage The Login.aspxpage is implemented in Listing 15-8

exam-Listing 15-8: Login Page Using <asp:Login> Server Control

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master” Title=”Login” %>

<asp:Content ID=”Content1” ContentPlaceHolderID=”BodyContent” Runat=”Server”>

<asp:login ID=”Login1” runat=”server” createuserurl=”CreateUser.aspx”

con-provider When you submit your username and password by using the Logincontrol, your credentialsare automatically validated by the configured membership provider

Trang 4

In the login page, try logging in with an invalid username or password, and notice that an appropriatedefault error message appears It is all handled automatically for you Figure 15-4 shows the output ofthe Login.aspxpage.

Figure 15-4

Security Features in ASP.NET 2.0

New security features are an important improvement in ASP.NET 2.0 These features include membership services that manage a database of user accounts, hashed pass- words, a role manager for managing role membership for users, and new security- related server-side controls that make implementing forms authentication much easier ASP.NET 2.0 also offers a provider model that gives you complete control over the implementation of the Membership and Role services and cookieless forms authentication

In addition to the extensible provider model, ASP.NET 2.0 also provides a suite of server controls that interact with the membership and role stores The Login control provides a daunting list of properties The vast majority of these properties simply enable you to control different aspects of the appearance of the login interface For example, you can use the FailureText property to control the content of the text that

is displayed when a login attempt fails Additionally, you can use the CreateUserUrl and PasswordRecoveryUrl properties to create links to a registration page and pass- word recovery page.

Trang 5

Before using the login feature, you need to register some users with the membership service to getstarted, so the first page you will be writing is one that allows you to add users For this purpose, create

a new page named CreateUser.aspx If the user does not have a valid account, they can get to theCreateUser.aspxpage using the Create New Account hyperlink on the Login.aspxpage or by click-ing the Create New User hyperlink in the left navigation Performing any of these operations directs theuser to the CreateUser.aspxpage, whose implementation is shown in Listing 15-9

Listing 15-9: Creating New User using <asp:CreateUserWizard> Server Control

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master”

Title=”Create User” %>

<asp:Content ID=”Content1” ContentPlaceHolderID=”BodyContent” Runat=”Server”>

<asp:CreateUserWizard ID=”CreateUserWizard1” runat=”server”

ContinueDestinationPageUrlattribute of the <asp:CreateUserWizard>control

After you are finished adding users, take a close look at your virtual directory You should see a newsubdirectory called “App_Data” that has a SQL Server 2005 Express database named ASPNETDB.MDFinside This is where the membership and role services store their data by default, but you can also over-ride the default storage mechanism to use SQL Server database or your own custom data repository

Trang 6

Logout Process

All you need to do to log out of the site is to click the Logouthyperlink on the left navigation When youclick that link, the user is redirected to the Logout.aspxpage shown in Listing 15-10

Listing 15-10: Implementation of Logout Functionality

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master” Title=”Logout” %>

<asp:CreateUserWizard ID=”CreateUserWizard1” Runat=”server” />

The CreateUserWizard control is powerful in that you can configure the control to send email messages by assigning values to the control’s MailDefinition property.

The MailDefinition property represents an instance of the MailDefinition class that contains all of the properties required for defining an email message For exam- ple, the following CreateUserWizard control will send the contents of the

Registration.txtfile as the body of the registration email message whenever someone completes the registration wizard.

<asp:CreateUserWizard ID=”CreateUserWizard1” Runat=”server”>

CreateUserWizardcontrol’s email functionality, you can automatically send the randomly generated password to the user If the user subsequently authenticates against your Web application using the sent password, you know that the user must have supplied a valid email address.

Trang 7

As Listing 15-10 shows, the logout implementation requires just one line of code You simply call theSignOut()method of the System.Web.Security.FormsAuthenticationclass That will clear all thecookies (used for authentication purposes) in the client machine Then you simply redirect the users tothe Login.aspxpage.

Categories Listing Process

All the categories present in the site are displayed through the CategoriesListing.aspxpage In thecategories listing page, you use an <asp:GridView>Web control to display the categories You bind theGridViewcontrol directly to the List<Category>returned by the Web service in the Page_Loadevent

To add the Web reference, right-click on the project in the Solution explorer and select Add Web

Reference in the context menu In the Add Web Reference dialog box, enter the path of the asmxfile ofthe Web service When you add a Web reference of a Web service to your project, Visual Studio 2005automatically generates a proxy class that not only interfaces with the Web service but also provides alocal representation of the Web service

Listing 15-11 illustrates the code of the CategoriesListing.aspxpage

Listing 15-11: Categories Listing Page that Uses CategoriesService

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master”

<asp:Content ID=”Content1” ContentPlaceHolderID=”BodyContent” Runat=”Server”>

<asp:GridView id=”gridCategories” style=”Z-INDEX: 101; LEFT: 162px; POSITION: absolute; TOP: 147px” runat=”server” Height=”321px” width=”529px”

BorderColor=”Black” cellpadding=”4” Font-Names=”Verdana” Font-Size=”8pt”

<asp:BoundField DataField=”CategoryName” HeaderText=”Category Name”/>

<asp:HyperLinkField Text=”Show all products”

Trang 8

The GetCategories()method of the CategoriesServicereturns an array of Categoryobjects that isdirectly bound to the GridViewcontrol When called from browser, the Categorieslisting page lookslike the output shown in Figure 15-6.

Figure 15-6

Products Listing Process

As the name suggests, the ProductListing.aspxpage shows the list of products available on the siteand the list of products shown is based on the category the user has selected in the categories listingpage The Page_Loadevent handler contains the code to invoke the ProductsServiceWeb service,retrieve data from it, and then display its contents into a GridViewcontrol The code of the

ProductsListing.aspxpage is shown in Listing 15-12

Listing 15-12: Products Listing Page That Uses ProductsService

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master”

/* Synchronous Web Service Call approach */

ProductsProxy.ProductsService obj = new ProductsProxy.ProductsService();

int categoryID = Convert.ToInt32(Request.QueryString[“CategoryID”]);

//Bind the Web service return value to Products GridView

Trang 9

gridProducts.DataSource = obj.GetProductsByCategoryID(categoryID);

gridProducts.DataBind();

}

</script>

<asp:Content ID=”Content1” ContentPlaceHolderID=”BodyContent” Runat=”Server”>

<asp:GridView id=”gridProducts” style=”Z-INDEX: 101; LEFT: 162px; POSITION: absolute; TOP: 147px” runat=”server” Height=”321px” width=”529px”

BorderColor=”Black” cellpadding=”4” Font-Names=”Verdana” Font-Size=”8pt”

<asp:BoundField DataField=”ModelNo” HeaderText=”ModelNumber”/>

<asp:BoundField DataField=”ModelName” HeaderText=”ModelName”/>

<asp:BoundField DataField=”Description” HeaderText=”Description”/>

<asp:BoundField DataField=”Price” HeaderText=”Price”/>

<asp:HyperLinkField Text=”Product Details” DataNavigateUrlFields=”ProductID” DataNavigateUrlFormatString=”productdetails.aspx?ProductID={0}”

Figure 15-7

Trang 10

Figure 15-7 displays the products that belong to the category that was selected in the categories listing page.

Product Details Listing Process

When the user selects a particular product from the list of products, the user is taken to the productdetails page where details about the product are shown For showing the product details, you will create

a Web page named ProductDetails.aspxthat encapsulates all the code required for retrieving thedetails of the product from the Web service The code of the ProductDetails.aspxpage is shown inListing 15-13

Listing 15-13: Product Details Page That Uses ProductsService

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master”

/* Synchronous Web Service Call approach */

ProductsProxy.ProductsService obj = new ProductsProxy.ProductsService();

int productID = Convert.ToInt32(Request.QueryString[“ProductID”]);

formProductDetails.DataSource = obj.GetProductDetails(productID);

formProductDetails.DataBind();

}

</script>

<asp:Content ID=”Content1” ContentPlaceHolderID=”BodyContent” Runat=”Server”>

<table width=”95%” cellpadding=”0” cellspacing=”0” border=”0”>

<td height=”40” align=”center” colspan=”2”>

<asp:Label runat=”server” Font-Bold=”true” ForeColor=”Brown”

<td height=”60” width=”30%” bgcolor=”buttonface”>

<asp:label Font-Bold=true Text=”Model Number : “ runat=”server” ID=”lblModelNumber” />

<td height=”60” width=”30%” bgcolor=”buttonface”>

<asp:label Font-Bold=true Text=”Model Name : “ runat=”server”

Trang 11

<td height=”60” width=”30%” bgcolor=”buttonface”>

<asp:label Font-Bold=true Text=”Description : “ runat=”server” ID=”lblDescription” />

<td height=”60” width=”30%” bgcolor=”buttonface”>

<asp:label Font-Bold=true Text=”Price : “ runat=”server”

Trang 12

Figure 15-8

The FormView control lays out the product details page and performs data binding with the results ofthe GetProductDetails()method of the ProductsService

Testing the ShoppingAssistant Application

Now that you have constructed the different parts of the application, it is time to test it by navigating tothe login page of the Web site If you enter a valid user id and password and click login, you will bedirected to the categories listing page where all the categories in the site are displayed Clicking the Showall Products hyperlink (displayed next to the category name) takes you to the product listing page whereyou can see all the products that belong to the selected category If you click the hyperlink Product Details

in the product listing page, you should be able to see the details of the specific product

There is one disadvantage to this approach Due to the synchronous approach, every time a request ismade, you go across the Internet to retrieve the details from the Web service Obviously, the responsetime is severely impacted due to the network trip that is made Because the network loads can be unpre-dictable, systems can become backlogged or unable to process requests in a timely manner This maylead to system failure as services time out or become unavailable When this occurs, consumers of syn-chronous Web services may lock critical resources while waiting for a result that may never come

To overcome this, you implement an asynchronous approach wherein you implement a combination ofWindows service and a System.Threading.Timercomponent to asynchronously invoke the Web ser-vice The result of this asynchronous Web service execution is then saved into a local XML file, whichwill then be used by the ShoppingAssistantWeb site

Trang 13

Using Asynchronous Invocation of Web Services and

Windows Service

This section discusses how to substitute the synchronous Web service invocation approach with the chronous approach that would greatly improve the throughput of the pages The idea here is to get thedata from the remote Web services in asynchronous manner and then store that information as XML files

asyn-in a local folder After the asyn-information is available asyn-in the XML files, the ShoppingAssistantWeb pagescan retrieve the required information from local XML files for display purposes To enable this asyn-chronous invocation of Web services at periodic intervals, you use the System.Threading.Timercom-ponent running inside a Windows Service application Here is how the different pieces are tied together

❑ Windows service application that has the Timercomponent invokes the remote Web service inasynchronous fashion Although invoking the Web service, it also utilizes the new event basedasynchronous programming model of Web services to specify the name of the callback functionthat will be automatically invoked when the Web service has finished its execution This call-back function then writes the returned result into a local XML file for the ShoppingAssistantWeb application to make use of

❑ Due to the presence of the Timercomponent (that fires a specific method at periodic intervals),you execute the action defined in the previous step for every pre-determined amount of time.This ensures that you have the latest information from the Web service in the local XML file Thefrequency with which the Web service is invoked is determined by the value passed to the con-structor of the Timerobject

❑ The ShoppingAssistantWeb forms application then reads the information to be displayed onthe site from the local XML file instead of making blocking synchronous calls to the remote Webservice

Windows Service

There are times where you may want to have your code always running on your server If

you have ever done any work in MSMQ, you might have created an application that polls

the message queue for every predefined amount of time and checks for new messages In

that case, the application that checks the queue for messages should always be running as

a Windows NT Service to be able to have the ability to poll the message queue

fre-quently These windows services do not have any user interface and you can configure

windows services in such a way that they can be automatically started when the

com-puter starts or they can be paused and restarted at any time

Prior to Visual Studio.NET, if you want to write a windows service application either you

have to use the template provided by ATL (Active Template Library that exposes a set of

classes used for COM programming in the Windows environment) or if you are a VB

pro-grammer, you have to embed custom NT service controls in VB to achieve the same

func-tionality But with Visual Studio.Net, you can easily create an application that has the

capability to run as a Service Visual Studio.Net is supplied with a new project template

called Windows Service that provides all the plumbing required for creating the

applica-tion that can run as a Service When you create a Visual Studio.Net project as a Service,

you can write code to respond to the actions like what should happen when the service is

started, paused, resumed, and stopped After you create the service, it has to be installed

using either InstallUtil.exe (Command line utility) or Setup and Deployment Project

template After you install the service, you can start, stop, pause, and resume it using the

Service Control Manager.

Trang 14

To start, consider the implementation of Windows service application.

Implementation of Windows Service Application

Create Visual C# Windows Service application named WinInformationPollingService After theproject is created, rename the service class from Service1to PollingService

The PollingServiceclass inherits from the System.ServiceProcess.ServiceBaseclass TheServiceBase class exposes the following lifecycle methods that you can override to indicate what hap-pens when the state of the service is changed (such as starting, stopping, and so on) in the ServicesControl Manager The lifecycle events fired by the service are:

❑ OnStart— Invoked when the service is started

❑ OnPause— Invoked when the service is paused

❑ OnStop— Invoked when the service stops running

❑ OnContinue— To decide the behavior that should happen when the service resumes normalfunctioning after being paused for a while

❑ OnShutDown— To indicate what should happen just prior to system shutdown, if the service isrunning at that time

Because the Windows service needs to be able to invoke the methods of the ContentPublisherService

to get the information, you need to add reference the Categoriesand Productsservices that were ated in the previous step Listing 15-14 shows the complete code of the PollingService

cre-Listing 15-14: PollingService That Asynchronously Invokes ContentPublisher Web Service

Through the property pages of the PollingService, you can set properties such as

CanStopand CanShutdown to either true or false These settings determine what methods can be called on your service at runtime For example, when the CanStop property is set to true, the OnStop() method will be automatically called when the service is stopped through the Service Control Manager.

Trang 15

partial class PollingService : ServiceBase

{

private CategoriesService _categoriesService;

private ProductsService _productsService;

Timer stateTimer;

public PollingService(){

InitializeComponent();

}protected override void OnStart(string[] args){

//Create the delegate that invokes methods for the timerAutoResetEvent autoEvent = new AutoResetEvent(false);

TimerCallback timerDelegate = new TimerCallback(GetData);

//Create a timer that signals the delegate to invoke GetData method//immediately, and every 10 seconds thereafter

stateTimer = new Timer(timerDelegate, autoEvent, 0, 10000);

}private void GetData(Object stateInfo){

_categoriesService = new CategoriesService();

_categoriesService.GetCategoriesCompleted += newGetCategoriesCompletedEventHandler(this.GetCategoriesCompleted);_categoriesService.GetCategoriesAsync();

_productsService = new ProductsService();

_productsService.GetProductsCompleted += newGetProductsCompletedEventHandler(this.GetProductsCompleted);_productsService.GetProductsAsync();

}void GetCategoriesCompleted(object sender, GetCategoriesCompletedEventArgs args){

string xmlFilePath = @”C:\Projects\Wrox\Categories.xml”;

Category[] categoryArray = args.Result;

XmlSerializer serializer = new XmlSerializer(typeof(Category[]));TextWriter writer = new StreamWriter(xmlFilePath);

//Serialize the Category array and close the TextWriterserializer.Serialize(writer, categoryArray);

writer.Close();

}void GetProductsCompleted(object sender, GetProductsCompletedEventArgs args)

Trang 16

{string xmlFilePath = @”C:\Projects\Wrox\Products.xml”;

Product[] productArray = args.Result;

XmlSerializer serializer = new XmlSerializer(typeof(Product[]));

TextWriter writer = new StreamWriter(xmlFilePath);

//Serialize the Product array and close the TextWriterserializer.Serialize(writer, productArray);

writer.Close();

}}}

The OnStartevent creates a new TimerCallbackand passes that to the constructor of theSystem.Threading.Timerobject

stateTimer = new Timer(timerDelegate, autoEvent, 0, 10000);

To the constructor, you also supply the start and frequency of the timer event as arguments as 0 and

10000, respectively This will result in the immediate firing of GetData()method and after that it willfire for every 10,000 milliseconds Inside the GetData()method, you invoke the

GetCategoriesAsync()method of the CategoriesService Before invoking theGetCategoriesAsync()method, you set the GetCategoriesCompletedevent handler to a localmethod named GetCategoriesCompleted() This means after the asynchronous version of theGetCategories()method (called as GetCategoriesAsync()) is done with its execution, it will callback the GetCategoriesCompleted()method passing in the results of the Web service execution.Similar is the case with the asynchronous invocation of the ProductsServiceusing its

GetProductsAsync()method

In the GetCategoriesCompleted()method, you retrieve the results of the Web service method call,load that into an array

Category[] categoryArray = args.Result;

Serialize the contents of the Categoryarray into an XML file named Categories.xmlthroughSerialize()method of the XmlSerializerobject

serializer.Serialize(writer, categoryArray);

Similarly the GetProductsCompleted()method retrieves the results of the Web service call and izes that result into an XML file named Products.xml

Trang 17

serial-Now that you have created a fully functional Windows service application that asynchronously calls theWeb service and ensures that the latest categories and products information are available locally, you canmodify the Web forms to retrieve data from the local xml files, instead of calling out to the remote Webservice every time the Web form is drawn

Deploying the Windows Service

The next step is to add the installers that are required for installing the Windows service application ontothe target machine There are two ways you can do this

❑ Using the InstallUtilCommand line utility

❑ Using Windows installers created through the Setup and Deployment Project template

For the purposes of this case study, you use the set up and deployment project to create the Windowsinstaller Before adding the setup and deployment project, add installers to the PollingServicebyright-clicking on the design window of the PollingServiceand selecting Add Installerfrom thecontext menu This will result in an installer named ProjectInstaller.csbeing added to the project

If you open up the ProjectInstaller.csfile, there will be two components in the design surface.These components are represented by the System.ServiceProcess.ServiceProcessInstallerandSystem.ServiceProcess.ServiceInstallerclasses respectively Select the component namedserviceProcessInstaller1that represents the ServiceProcessInstallerclass and bring up itsproperties window by pressing F4 In the properties window, change the value of the Account property

to LocalSystemso that the PollingServiceruns using the credentials of the local system account

.NET Framework 2.0 provides a new event-based asynchronous programming model

for asynchronous invocation of Web services This approach greatly simplifies the

task of asynchronously invoking a Web service by introducing a new paradigm

based on event handlers and arguments that are based on the name of the Web

ser-vice method itself

With this new approach, if you have a Web service method named MethodXXX, you

call the <MethodName>Async to asynchronously invoke the Web service For

exam-ple, if you have a Web service method named GetCategories and you want to

leverage asynchronous invocation framework, you need to do two things:

1 Create an event handler for the GetCategoriesCompleted method and hook it

up to a local method that can process the results returned by the Web service One of

the arguments passed to this method is of type

GetCategoriesCompletedEventArgs, whose Result property contains the return

value of the Web service method.

2 Invoke the Web service method by calling the GetCategoriesAsync() method

through the Web service proxy.

Another important benefit of this approach is that it also takes care of thread

syn-chronization automatically so that event handlers are invoked on the same thread

that made the asynchronous call.

Trang 18

Now add a new Setup and Deployment project named WinInformationPollingServiceSetupto thesolution After the setup project is created, add the Project Output of the WinInformationPollingServiceto the setup project Right-click on the WinInformationPollingServiceSetupproject fromthe Solution Explorer and select Add->Project Output from the context menu In the Add Project OutputGroup dialog box, ensure WinInformationPollingServiceproject is selected in the Project drop-downlist, select Primary Output, and click OK Now that you have added the output of the WinInformationPollingServiceproject to the setup project, add the installer that you created earlier in the

WinInformationPollingServiceproject as a custom action To do this, select the WinInformationPollingServiceSetupproject from the Solution Explorer and select View->Editor->Custom Actions fromthe menu In the Custom Actions editor, right-click on the Custom Actions folder and select Add CustomAction from the context menu; then select the Primary Output of the WinInformationPollingServiceproject from the dialog box Now build the WinInformationPollingServiceSetupproject, and itshould result in a Windows installer named WinInformationPollingServiceSetup.msifile being cre-ated Run the installer file

Start the PollingServiceby opening up the Service Control Manager, right-clicking on thePollingService, and selecting Start from the context menu After the service is started, it will keeppolling the Web service and refresh the contents of the local XML files with the latest informationretrieved from the Web service

Modifying the ShoppingAssistant Web Pages to Consume XML Files

In the previous implementation of ShoppingAssistantWeb site, the Web pages depended on chronous Web service call to get categories and products information But now with the availability oflocal XML files, the Web pages can just read the required information from the local XML files instead

syn-of making remote Web service calls To illustrate the modification that needs to be done, consider theCategoriesListing.aspxpage Listing 15-15 shows the modified Page_Loadevent of theCategoriesListing.aspxpage

Listing 15-15: Page_Load Event of CategoriesListing.aspx Page That Uses XML File as the Data Store

void Page_Load(object sender, EventArgs e){

/* Asynchronous Web Service Call through the XML file generated

by the Windows Service */

string xmlFilePath = @”C:\Projects\Wrox\Categories.xml”;

XmlSerializer serializer = new XmlSerializer(typeof(Category[]));

TextReader reader = new StreamReader(xmlFilePath);

//Deserialize the Category and close the TextReader gridCategories.DataSource = (Category[])serializer.Deserialize(reader);

Trang 19

You need to perform the same modification to all the other Web pages as well to take advantage of theinformation that is available in the local XML files; however, with the ProductsListing.aspxandProductDetails.aspxpages, there is a challenge As you might remember, the Windows service pop-ulated all the products returned by the Web service into an XML file named Products.xml Now in theProductsListing.aspxpage, you need to be able to display only those products that belong to theselected category Listing 15-16 shows how this is implemented by looping through the Productarrayand filtering out the unwanted products.

Listing 15-16: Performing Data Binding with the Local XML File

void Page_Load(object sender, EventArgs e)

{

int categoryID = Convert.ToInt32(Request.QueryString[“CategoryID”]);

List<Product> prodList = new List<Product>();

string xmlFilePath = @”C:\Projects\Wrox\Products.xml”;

XmlSerializer serializer = new XmlSerializer(typeof(Product[]));

TextReader reader = new StreamReader(xmlFilePath);

Product[] prodArray = (Product[])serializer.Deserialize(reader);

//Loop through the array and store the products with the matching category idfor (int i = 0; i < prodArray.Length; i++)

{

Product temp = prodArray[i];

//Only add the matching products to the new collection

if (temp.CategoryID == categoryID)prodList.Add(temp);

If you go back to the ShoppingAssistantWeb site and navigate through the pages, you will find thatthe performance and throughput of the site has vastly improved due to the change in the way youobtain the data for display

Implementation of FileSystemWatcher to Facilitate

Reporting Data Collection

Now you have a working Web site that shows all the information related to categories and productsavailable in the site Imagine, for example, one of the partners of ShoppingAssistantsite wants to findout the number of times a particular product has been viewed by the users To accomplish this, you need

to be able to store the details of all the products that are displayed on the product details page If youwere to handle this process of storing data in a synchronous way (such as making a database call when-ever a product related page is requested), the user would have to wait till this information is stored inthe database because the control will not be returned to the caller application until the changes aresaved This might result in an increase in the response time for the product details page to be rendered

Trang 20

on the user’s browser It would be nice if you could perform this data collection operation in an chronous manner without impacting the throughput of the Web site To enable this approach, add somemore elements to the existing architecture Figure 15-9 shows the new architecture.

asyn-Figure 15-9

When the user navigates to the Productspage, perform a number of independently running operations

to ensure that the data relevant for reporting purposes is collected and stored in the database

❑ When the user navigates to the ASP.NET Web page that displays the product details, take theproducts information, convert that information into an XML file, and store it in a specified Dropdirectory

❑ This specified directory is already monitored for creation of new files by a FileSystemWatchercomponent, which is placed in a Windows service that always runs in the background as a service

❑ When an XML file is created in the Dropdirectory, an event is automatically raised to theWindows Service that reads the contents of the xml file into an object named ReportInfo, andpasses the ReportInfoobject to the InsertReportInfo()method of the ReportDBclass that

is present in the ShoppingAssistantLibclass library

❑ The InsertReportInfo()method simply inserts the details into a table named ReportInfothrough the InsertReportInfoprocedure

Asynchronous Data Collection Framework for Reporting

User

ShoppingAssistantLib(.NET component)

Windows Service Application with aFileSystemWatcher component

Internet

ShoppingAssistant web site

Collects the reporting data, creates anXML file and drops the file onto thespecified Windows folder

Parses the XML fileand stores that info inthe reporting database

FileSystemWatcher componentmonitors the directory and an event is fired whenever a new file is created

XML files in WindowsFile System

User registration andlogin verification

SQL ServerShoppersInfoDatabase

Trang 21

By carrying out the reporting data collection operation in an asynchronous fashion, you allow the trol to return to the application as soon as the reporting information is captured in an XML file (asopposed to storing that information in a database through an expensive network call) After that, a sepa-rate set of operations are executed in a separate thread to save the reporting details to the database Thisasynchronous approach not only helps in increasing the performance, but also provides the users withthe best possible browsing experience.

con-For reasons of manageability, this section of the implementation is split into two sections In the first tion, you modify the Products Web page to store the details of the products information into an XML filebefore displaying the details of a specific product to the user The second section discusses the steps forsetting up the FileSystemWatchercomponent on the Windows service to monitor the directory for thecreation of files

sec-Modification to the Products Page

This section focuses on the changes that need to be made to the ProductDetails.aspxpage to gatherthe product information into a local XML file for reporting purposes Because the changes are only onthe server-side code, Listing 15-17 shows the modified server-side code of the ProductDetails.aspxpage

Listing 15-17: Implementing Asynchronous Reporting Data Collection Support in

Product Details Display Page

<%@ Page Language=”C#” MasterPageFile=”~/CommonMaster.master”

string xmlFilePath = @”C:\Projects\Wrox\Products.xml”;

XmlSerializer serializer = new XmlSerializer(typeof(Product[]));

TextReader reader = new StreamReader(xmlFilePath);

Product[] prodArray = (Product[])serializer.Deserialize(reader);

//Loop through the array and retrieve products with the matching product idfor (int i = 0; i < prodArray.Length; i++)

{Product temp = prodArray[i];

//Only add the matching products to the new collection

if (temp.ProductID == productID){

prodList.Add(temp);

categoryID = temp.CategoryID;

}}reader.Close();

Trang 22

formProductDetails.DataSource = prodList;

formProductDetails.DataBind();

//Store the parameters related to the Request into local variablesstring browser = Request.UserAgent.ToString();

string requestType = Request.RequestType.ToString();

string authenticated = Request.IsAuthenticated.ToString();

CreateXMLDocument(browser, requestType, authenticated, categoryID, productID);

}public bool CreateXMLDocument(string browser, string requestType, string authenticated, int categoryID, int productID)

{ try{ XmlWriterSettings settings = new XmlWriterSettings();

settings.Indent = true;

string fileName = System.Guid.NewGuid().ToString() + “.xml”;

XmlWriter writer = XmlWriter.Create(@”C:\Projects\Wrox\Drop\” + fileName, settings);

writer.WriteStartDocument(false);

writer.WriteComment(“This file represents information collected for reporting purposes”);writer.WriteStartElement(“ReportInfo”, null);

Response.Write(ex.Message);

}return true;

}

</script>

Listing 15-17 is similar to the CategoriesListing.aspxpage in that it also relies on a local XML filenamed Products.xmlfor the data displayed through the FormViewcontrol formProductDetails Theplace where it is different is where it creates the XML file using a method named CreateXmlDocument().The CreateXmlDocument()method is invoked at the end of the Page_Loadevent Before calling theCreateXmlDocument()method, you store the parameters related to the current request into a localvariable

string browser = Request.UserAgent.ToString();

string requestType = Request.RequestType.ToString();

string authenticated = Request.IsAuthenticated.ToString();

Trang 23

Call the CreateXmlDocument()method passing in the values of the local variables.

CreateXMLDocument(browser, requestType, authenticated,

categoryID, productID);

The CreateXmlDocument()method creates an XML file in a specific directory using the WriteXXX()methods of the XmlWriterobject The name of the XML file is generated by the call to the NewGuid()method of Guidclass

A typical XML file created by the CreateXmlDocument()method looks as shown in Figure 15-10

Figure 15-10

Now that the ProductDetails.aspxpage is capable of generating the dynamic XML file, the next step

is to add the required code to the Windows service so that it can process the files generated by the uct details page

prod-Adding Monitoring Capability to Windows Service Using

FileSystemWatcher

To add monitoring capabilities, drag and drop a FileSystemWatchercomponent to the design surface

of the PollingServicethat is part of the WinInformationPollingServiceproject Now modify theOnStart()method to look as shown in Listing 15-18 Listing 15-18 also implements two additionalmethods: OnChanged()and SaveReportInfo()

Listing 15-18: Adding Asynchronous Reporting Data Collection Support to Product Details Display Page

protected override void OnStart(string[] args)

{

AutoResetEvent autoEvent = new AutoResetEvent(false);

//Create the delegate that invokes methods for the timer

Trang 24

TimerCallback timerDelegate = new TimerCallback(GetData);

//Create a timer that signals the delegate to invoke GetData method//immediately, and every 10 seconds thereafter

stateTimer = new Timer(timerDelegate, autoEvent, 0, 10000);

//Configure the FileSystemWatcher to watch for changesfileSystemWatcher1 = new FileSystemWatcher();

//Read the contents of the file and save it to the databaseSaveReportInfo(e.FullPath);

}private void SaveReportInfo(string path){

try{XmlReader reader = XmlReader.Create(path);

XmlDocument document = new XmlDocument();

document.Load(reader);

XmlNode reportInfoNode = document.DocumentElement;

ReportInfo report = new ReportInfo();

//Get all the values from the XML document into the ReportInfo objectreport.Browser = reportInfoNode.ChildNodes.Item(0).InnerText;

report.RequestType = reportInfoNode.ChildNodes.Item(1).InnerText;

report.Authenticated = reportInfoNode.ChildNodes.Item(2).InnerText;

report.CategoryID = Convert.ToInt32(reportInfoNode.ChildNodes.Item(3).InnerText);

report.ProductID = Convert.ToInt32(reportInfoNode.ChildNodes.Item(4).InnerText);

ReportDB reportDB = new ReportDB();

reportDB.InsertReportInfo(report);

reader.Close();

}catch (Exception ex){

throw ex;

}}

In the OnStart()method, you configure the relevant properties of the FileSystemWatchernent so that it can start monitoring the “C:\Projects\Wrox\Drop” for creation of new XML files

Trang 25

compo-fileSystemWatcher1 = new FileSystemWatcher();

Finally, you enable the component to begin watching for the creation of new files by setting the

EnableRaisingEventsproperty to true

fileSystemWatcher1.EnableRaisingEvents = true;

Now that you have enabled the FileSystemWatcherto watch for new files, whenever a new file is ated, the OnChanged()method will be called In the OnChanged()method, you simply invoke a helpermethod named SaveReportInfo, which reads the contents of the generated XML file and stores that inthe database

cre-As the name of the method suggests, SaveReportInfomethod reads the contents of the XML file into aReportInfoobject, and invokes the SaveReportInfomethod of the ReportDBobject passing in theReportInfoobject as an argument Now recompile the WinInformationPollingServiceand rede-ploy it using the Windows installer

Putting It All Together

Now that you have constructed the different parts of the application, it is time to exercise the ties of the application by going through the following steps

functionali-❑ If the PollingServiceis not already running, start the service through the Service ControlManager After the service is started, the service will begin monitoring the C:\Projects\Wrox\Dropdirectory for creation of new files in addition to refreshing the contents of the localXML files with the latest data retrieved from the XML Web service

❑ Now if you navigate to the ShoppingAssistantWeb site and browse through the Categoriesand Products Web pages, the latest information from the local XML files will be used to displaythe information

❑ While navigating to the product details page, you will find that all the details related to the played product are added to the ReportInfotable, which can be later used for reporting purposes.This is made possible due to the combination of the following operations The Web page that dis-plays the product details page creates an XML file and drops it on to the C:\Projects\Wrox\Dropdirectory that is being monitored by the FileSystemWatcher(that is hosted on a Windows ser-vice) Because the FileSystemWatchermonitors the directory for the creation of new files, anevent is automatically raised as soon as a new XML file is created The Windows service capturesthe event, reads the contents of the XML file, and then stores that information in the ReportInfotable in the database through the methods of the ReportDBclass

Trang 26

dis-Summar y

This case study has discussed the following features:

❑ The new event-based programming model for asynchronous invocation of Web service

❑ How to leverage the XML serialization capabilities of the XmlSerializerclass to serialize thecontents of an object into an XML file and vice versa

❑ How to effectively leverage the asynchronous Web service invocation capabilities in a Webapplication

❑ How to utilize the features of the FileSystemWatcherto asynchronously process the XML files

❑ How to use master pages to create consistent look and feel for the entire Web siteAlthough the application that was demonstrated was simple in functionality, it should provide a solidfoundation for understanding how to build high-performance, scalable, flexible, and reliable Web appli-cations using the asynchronous features of the NET framework such as XML-based Web services, andFileSystemWatcher If your application consumes a lot of external Web services and the applicationallows some tolerance in terms of the staleness of the data it gets from external services, the asyn-chronous Web service invocation capabilities could very well be an excellent feature to use

Ngày đăng: 12/08/2014, 23:22

TỪ KHÓA LIÊN QUAN