Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 84 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
84
Dung lượng
321,14 KB
Nội dung
Web Services Bridges and Transformers This chapter will first provide an overview of the Amazon E-Commerce Web service. It will then implement a script server control that uses a Web services bridge to invoke a specified Web method of this Web service and display the results to end users. Finally, I will provide an in-depth coverage of ASP.NET AJAX transformers. Amazon Web Services At the end of Chapter 14, I promised that I’d present a more complete example of Web services bridges. In this chapter you’ll learn how to develop a custom script server control that uses a bridge to enable the client code to interact with the Amazon Web services. Before diving into the implementation of this custom script server control you need to do the following things: ❑ Visit the Amazon Web service site at www.amazon.com/gp/aws/landing.html and follow the instructions on this site to create an Amazon Web service account and get an access key. As you’ll see later, you have to include this access key with every single call that you make to the Amazon Web services. This site comes with the complete documen- tation and sample code for using the Amazon Web services. ❑ Acquire a good understanding of the Amazon Web services. In particular, we’re interested in the Amazon E-Commerce Web service ( AWSE CommerceService ), a particular Web method of this Web service named ItemSearch , and a particular set of parameters of this Web method. Therefore, in this chapter we’ll focus on these items. Complete coverage of the Amazon Web services is beyond the scope of this book. The following code listing presents the declaration of the Amazon E-Commerce Web service: public class AWSECommerceService { public ItemSearchResponse ItemSearch(ItemSearch ItemSearch1); } c18.indd 773c18.indd 773 8/20/07 7:56:06 PM8/20/07 7:56:06 PM Chapter 18: Web Services Bridges and Transformers 774 As you can see, the ItemSearch method takes an argument of type ItemSearch and returns an object of type ItemSearchResponse . I’ll discuss the ItemSearch and ItemSearchResponse types in the following sections. ItemSearch The ItemSearch type or class is defined in Listing 18-1 . As you can see, this class exposes two important properties, SubscriptionId and Request . As the name suggests, the SubscriptionId property is a string that contains your Amazon access key or subscription ID. The Request property references the ItemSearchRequest object that represents a request to the Amazon service. Listing 18-1: The ItemSearch Class public class ItemSearch { public string SubscriptionId {get; set;} public ItemSearchRequest Request {get; set;} } Listing 18-2 defines the ItemSearchRequest type or class. As you can see, this class contains four properties: ❑ ItemPage , a positive integer number. This is basically the index of the page that we want to download from the Web service. Since there could be thousands of records for our query keyword, we need to specify which page of records we’re interested in. If you don’t specify the page index, the first page of records is returned by default. ❑ Keywords , a string that contains our query. ❑ ResponseGroup , a string that contains certain of our search criteria, as you’ll see in the following example. ❑ SearchIndex , a string that contains the type of the query. For example, if you pass Books as the SearchIndex parameter into the ItemSearch Web method, you’re telling this method that you’re searching for books. Listing 18-2: The ItemSearchRequest Class public class ItemSearchRequest { public int ItemPage {get; set;} public string Keywords {get; set;} public string ResponseGroup {get; set;} public string SearchIndex {get; set;} } Listing 18-3 defines the ItemSearchResponse class, which exposes an array property of type Items named Items . c18.indd 774c18.indd 774 8/20/07 7:56:07 PM8/20/07 7:56:07 PM Chapter 18: Web Services Bridges and Transformers 775 Listing 18-3: The ItemSearchResponse Class public class ItemSearchResponse { public Items[] Items { get; set;} } Listing 18-4 defines the Items type, which exposes an array property of type Item named Item . Listing 18-4: The Items Class public class Items { public Item[] Item { get; set; } } As you can see from Listing 18-5 , the Item type or class exposes four properties: ❑ DetailPageURL , a string that contains the URL of the page with more detailed information about the item. For example, if the item represents a book, this URL takes the end user to the page that provides more detailed information about the book. ❑ MediumImage , which is of type Image . ❑ ItemsAttributes and Offers , which you’ll learn about later in the chapter. Listing 18-5: The Item Class public partial class Item { public string DetailPageURL {get; set; } public Image MediumImage {get; set;} public ItemAttributes ItemAttributes {get; set;} public Offers Offers {get; set;} } As Listing 18-6 shows, the Image type or class exposes a string property named URL, which contains the URL of the image associated with the item. For example, if the item is a book, this is the URL of the image of the book. Listing 18-6: The Image Class public partial class Image { public string URL {get; set;} } As Listing 18-7 shows, the Offers type exposes an array property named Offer that contains objects of type Offer . c18.indd 775c18.indd 775 8/20/07 7:56:07 PM8/20/07 7:56:07 PM Chapter 18: Web Services Bridges and Transformers 776 Listing 18-7: The Offers Class public partial class Offers { public Offer[] Offer {get; set;} } As you can see from Listing 18-8 , the Offer type exposes an array property named OfferListing that contains an object of type OfferListing . Listing 18-8: The Offer Class public partial class Offer { public OfferListing[] OfferListing {get; set;} } As Listing 18-9 shows, the OfferListing type or class exposes a property of type Price named Price . Listing 18-9: The OfferListing Class public partial class OfferListing { public Price Price {get; set;} } As you can see from Listing 18-10 , the Price type exposes a property of type string named FormattedPrice . Listing 18-10: The Price Class public class Price { public string FormattedPrice { get; set; } } As Listing 18-11 shows, the ItemAttributes type exposes a string property named Author , a property of type Price named ListPrice , and a string property named Title . Listing 18-11: The ItemAttributes Class public class ItemAttributes { public string[] Author { get;set;} public Price ListPrice { get; set;} public string ProductGroup { get; set;} public string Title { get; set;} } c18.indd 776c18.indd 776 8/20/07 7:56:08 PM8/20/07 7:56:08 PM Chapter 18: Web Services Bridges and Transformers 777 Now that you have a good understanding of the AWSE CommerceService Web service, its ItemSearch Web method, the names and types of parameters you need to pass into this Web method, and the type of return value you should expect to receive from it, we’re ready to use this Web service. As you learned from the WSDL document, you need to make a HTTP SOAP request to the http://soap.amazon.com/onca/soap?Service=AWSECommerceService URL to invoke the ItemSearch Web method. You could go ahead and write the SOAP message yourself, but then you would have to get involved in the dirty little details of SOAP messaging. A better approach is to generate the code for a class known as proxy that hides the underlying SOAP messaging and enables you to program against the remote Web service object as if you were programming against a local object. There are different ways to create the proxy class. If you’re working in the Visual Studio environment, you have the following options: ❑ Launch the Add Web References dialog, navigate to http://webservices.amazon.com/ AWSECommerceService/AWSECommerceService.wsdl and click the Add Reference button to add a reference to the AWSE CommerceService Web service. This will automatically download the AWSECommerceService.wsdl WSDL document from the amazon.com site, create the code for the proxy class, compile the proxy class into an assembly, and add a reference to the assembly. ❑ Download the AWSECommerceService.wsdl WSDL document from http://webservices .amazon.com/AWSECommerceService/AWSECommerceService.wsdl and store the WSDL file in your favorite directory on your machine. If you’re using the built-in Web server, launch the Add Web Reference dialog and follow the same steps as in the previous item, but this time navi- gate to the directory where the WSDL file is located. The URL should look something like the following: file:///d:/download/AWSECommerceService.wsdl ❑ If you’re using IIS, you have to copy the AWSE CommerceService.wsdl document to the root directory of your application. The path to this directory should look something like C:\Inetpub\wwwroot\ApplicationRoot . Then launch the Add Web References dialog and follow the steps discussed in the previous item to navigate to the application root where the WSDL document is located. The URL for the WSDL document should look something like this: http://localhost/(ApplicationRoot)/ AWSECommerceService.wsdl ❑ If you’re using App_Code directory, copy the AWSE CommerceService.wsdl document to this directory. That’s it. The Visual Studio automatically generates the code for the proxy, compiles the proxy code into an assembly, and adds a reference to the assembly. If you’re not working in the Visual Studio environment, and you like to do things from the command line, first download the AWSE CommerceService.wsdl document from http://webservices .amazon.com/AWSECommerceService/AWSECommerceService.wsdl and store the document in a file in your favorite directory. Go to this directory and use the following command to generate the code for the proxy class and to save the code to the AWSE CommerceService.cs file (give it any name you wish): wsdl /out:AWSECommerceService.cs AWSECommerceService.wsdl c18.indd 777c18.indd 777 8/20/07 7:56:08 PM8/20/07 7:56:08 PM Chapter 18: Web Services Bridges and Transformers 778 The wsdl.exe tool comes with different options. For example, you can use /namespace: AWSECommerceService to specify your desired namespace for the proxy class. Then use the following command to compile the AWSE CommerceService.cs into the AWSE CommerceService.dll assembly and use the assembly as you would use any other: csc /t:library /out: AWSECommerceService.dll AWSECommerceService.cs Since we want to use the ASP.NET AJAX Web services bridges to enable our client-side code to invoke the ItemSearch Web method of the AWSE CommerceService Web service, first we need to create and add an .asbx file to our application. (These files were thoroughly discussed earlier in this book.) Listing 18-12 presents the content of an .asbx file named AmazonSearch.asbx that we will use in our example. This file instructs the ASP.NET AJAX framework to generate a client-side proxy class named AmazonService that belongs to a namespace named MyServices and contains a method named Search that takes two parameters, pageIndex and searchQuery . The pageIndex parameter specifies the page of records being retrieved and the searchQuery parameter specifies the search keywords. Listing 18-12: The AmazonSearch.asbx File <?xml version=”1.0” encoding=”utf-8” ?> <bridge namespace=”MyServices” className=”AmazonService”> <proxy type=”CustomComponents3.AmazonService, App_Code”/> <method name=”Search”> <input> <parameter name=”pageIndex” /> <parameter name=”searchQuery” /> </input> </method> </bridge> As Listing 18-12 shows, this bridge is a wrapper around a .NET class named AmazonService that belongs to a namespace called CustomComponents3 and is located in the App_Code directory of the current application. Listing 18-13 presents the implementation of this class. Store this code listing in a file named AmazonService.cs and add the file to the App_Code directory. Listing 18-13: The AmazonService Class using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.IO; using System.Xml; using System.Collections; using com.amazon.webservices; namespace CustomComponents3 { public class AmazonService c18.indd 778c18.indd 778 8/20/07 7:56:08 PM8/20/07 7:56:08 PM Chapter 18: Web Services Bridges and Transformers 779 { public Items Search(int pageIndex, string searchQuery) { ItemSearchRequest itemSearchRequest = new ItemSearchRequest(); itemSearchRequest.Keywords = searchQuery; itemSearchRequest.SearchIndex = “Books”; itemSearchRequest.ResponseGroup = new string[] { “Small”, “Images”, “ItemAttributes”, “OfferFull” }; itemSearchRequest.ItemPage = pageIndex.ToString(); ItemSearch itemSearch = new ItemSearch(); itemSearch.SubscriptionId = ConfigurationManager.AppSettings[“SubscriptionID”]; itemSearch.AssociateTag = “”; itemSearch.Request = new ItemSearchRequest[1] { itemSearchRequest }; ItemSearchResponse itemSearchResponse; try { AWSECommerceService amazonService = new AWSECommerceService(); itemSearchResponse = amazonService.ItemSearch(itemSearch); } catch (Exception e) { throw e; } Items[] itemsResponse = itemSearchResponse.Items; // Check for errors in the reponse if (itemsResponse == null) throw new Exception(“Response from amazon.com contains not items!”); if (itemsResponse[0].Request.Errors != null) throw new Exception( “Response from amazon.com contains this error message: “ + itemsResponse[0].Request.Errors[0].Message); Items items = itemsResponse[0]; return items; } } } As you can see from Listing 18-13 , the AmazonService class exposes a single method named Search that performs these tasks. First, it instantiates an ItemSearchRequest object: ItemSearchRequest itemSearchRequest = new ItemSearchRequest(); Next, it assigns the search query to the Keywords property of this object. For example, the search query could be the string asp.net . itemSearchRequest.Keywords = searchQuery; c18.indd 779c18.indd 779 8/20/07 7:56:09 PM8/20/07 7:56:09 PM Chapter 18: Web Services Bridges and Transformers 780 Then, it assigns the string Books to the SearchIndex property of the ItemSearchRequest object to instruct the Amazon Web service that the end user is searching for books. For example, if the search query is the string asp.net and the search index is the string Books , the Amazon Web service will return the list of books on ASP.NET: itemSearchRequest.SearchIndex = “Books”; Next, it assigns the specified array of strings to the ResponseGroup property of the ItemSearchRequest object: itemSearchRequest.ResponseGroup = new string[] { “Small”, “Images”, “ItemAttributes”, “OfferFull” }; Then it specifies the page of records that the Amazon Web service should return. For example, if the search query is the string asp.net , the search index is the string Books , and the page index is 4 , the Amazon Web service will return the fourth page of records, where each record describes an ASP.NET book: itemSearchRequest.ItemPage = pageIndex.ToString(); Next, the Search method instantiates an ItemSearch object: ItemSearch itemSearch = new ItemSearch(); Then it assigns the access key to the SubscriptionId property of this ItemSearchObject . As discussed earlier, you need to create an Amazon Web services account and get an access key. For security reasons, you may want to store your access key in the appSettings section of the web.config file. The great thing about doing this is that the ASP.NET framework enables you to encrypt selected sections of the web.config file to protect your data. You can then use your access key through the AppSettings static collection property of the ConfigurationManager class: itemSearch.SubscriptionId = ConfigurationManager.AppSettings[“SubscriptionID”]; Next, the Search method assigns an array that contains the previously instantiated and initialized ItemSearchRequest object to the Request property of the ItemSearch object: itemSearch.Request = new ItemSearchRequest[1] { itemSearchRequest }; Then it instantiates an instance of the AWSE CommerceService proxy class: AWSECommerceService amazonService = new AWSECommerceService(); Next, it invokes the ItemSearch method of the proxy class, passing in the ItemSearch object: ItemSearchResponse itemSearchResponse = amazonService.ItemSearch(itemSearch); The ItemSearch method returns an ItemSearchResponse object that contains the server response data. As discussed earlier, this object exposes an array property named Items that contains an object of type Items : Items[] itemsResponse = itemSearchResponse.Items; c18.indd 780c18.indd 780 8/20/07 7:56:09 PM8/20/07 7:56:09 PM Chapter 18: Web Services Bridges and Transformers 781 Finally, the Search method returns the first Items object in the Items collection property: Items items = itemsResponse[0]; return items; Developing Web Services Bridge-Enabled Script Server Controls Next, I’ll present and discuss the implementation of a custom ASP.NET AJAX script server control that uses the AWSE CommerceService Web service to search the amazon.com site for books that meet particular search criteria. This involves implementing the following four components: ❑ AspNetAjaxAmazonSearch : An ASP.NET AJAX client control that uses the ASP.NET AJAX Web services bridges to invoke the ItemSearch Web method of the AWSE CommerceService Web service ❑ AmazonSearchScriptControl : An ASP.NET script server control that encapsulates the logic, enabling page developers to use the same imperative and declarative ASP.NET techniques to program against the underlying AspNetAjaxAmazonSearch ASP.NET AJAX client-side control ❑ HtmlGenerator : An ASP.NET AJAX client-side component that displays the results returned from the call into the ItemSearch Web method of the AWSE CommerceService Web service ❑ HtmlGeneratorScriptControl : An ASP.NET script server control that encapsulates the logic, enabling page developers to use the same imperative and declarative ASP.NET techniques to program against the underlying HtmlGenerator ASP.NET AJAX client-side component AspNetAjaxAmazonSearch Listing 18-14 presents the implementation of the AspNetAjaxAmazonSearch client control. I’ll discuss the methods and properties of this control in the following sections. Listing 18-14: The AspNetAjaxAmazonSearch Client-side Control Type.registerNamespace(“CustomComponents3”); CustomComponents3.AspNetAjaxAmazonSearch = function CustomComponents3$AspNetAjaxAmazonSearch(associatedElement) { CustomComponents3.AspNetAjaxAmazonSearch.initializeBase(this, [associatedElement]); } function CustomComponents3$AspNetAjaxAmazonSearch$get_searchTextBox() { return this._searchTextBox; } function CustomComponents3$AspNetAjaxAmazonSearch$set_searchTextBox(value) { (continued) c18.indd 781c18.indd 781 8/20/07 7:56:09 PM8/20/07 7:56:09 PM Chapter 18: Web Services Bridges and Transformers 782 Listing 18-14 (continued) this._searchTextBox = value; } function CustomComponents3$AspNetAjaxAmazonSearch$get_searchButton() { return this._searchButton; } function CustomComponents3$AspNetAjaxAmazonSearch$set_searchButton(value) { this._searchButton = value; } function CustomComponents3$AspNetAjaxAmazonSearch$get_htmlGenerator() { return this._htmlGenerator; } function CustomComponents3$AspNetAjaxAmazonSearch$set_htmlGenerator(value) { this._htmlGenerator = value; } function CustomComponents3$AspNetAjaxAmazonSearch$get_searchResultAreaDiv() { return this._searchResultAreaDiv; } function CustomComponents3$AspNetAjaxAmazonSearch$set_searchResultAreaDiv(value) { this._searchResultAreaDiv = value; } function CustomComponents3$AspNetAjaxAmazonSearch$get_commandBarAreaDiv() { return this._commandBarAreaDiv; } function CustomComponents3$AspNetAjaxAmazonSearch$set_commandBarAreaDiv(value) { this._commandBarAreaDiv = value; } function CustomComponents3$AspNetAjaxAmazonSearch$get_nextButton() { return this._nextButton; } function CustomComponents3$AspNetAjaxAmazonSearch$set_nextButton(value) { this._nextButton = value; } c18.indd 782c18.indd 782 8/20/07 7:56:09 PM8/20/07 7:56:09 PM [...]... ScriptDescriptor[] { descriptor }; } protected override IEnumerable GetScriptReferences() { ScriptReference reference = new ScriptReference(); reference. Path = Path; return new ScriptReference[] { reference }; } (continued) 791 c18.indd 791 8/20/07 7:56:12 PM Chapter 18: Web Services Bridges and Transformers Listing 1 8-1 5 (continued) protected override void RenderContents(HtmlTextWriter... get_searchMethod: CustomComponents3$AspNetAjaxAmazonSearch$get_searchMethod, set_searchMethod: CustomComponents3$AspNetAjaxAmazonSearch$set_searchMethod, initialize: CustomComponents3$AspNetAjaxAmazonSearch$initialize, (continued) 785 c18.indd 785 8/20/07 7:56:10 PM Chapter 18: Web Services Bridges and Transformers Listing 1 8-1 4 (continued) _onSearchButtonClick: CustomComponents3$AspNetAjaxAmazonSearch$_onSearchButtonClick,... 805 c18.indd 805 8/20/07 7:56:16 PM Chapter 18: Web Services Bridges and Transformers Listing 1 8-1 7 (continued) if (this.alternatingRowStyle != null) { col = alternatingRowStyle.GetStyleAttributes(this); descriptor.AddProperty(“alternatingRowStyle”, col.Value); } return new ScriptDescriptor[] { descriptor }; } protected override IEnumerable GetScriptReferences() { ScriptReference reference. .. bar set_commandBarAreaDiv Sets a reference to the div DOM element that displays the command bar 786 c18.indd 786 8/20/07 7:56:11 PM Chapter 18: Web Services Bridges and Transformers Getter or Setter Method Description get_nextButton Gets a reference to the next button DOM element set_nextButton Sets a reference to the next button DOM element get_previousButton Gets a reference to the previous button... caller: return new ScriptDescriptor[] { descriptor }; GetScriptReferences AmazonSearchScriptControl, like any other script server control, overrides the GetScriptReferences method of its base class, where it instantiates a ScriptReference object: ScriptReference reference = new ScriptReference(); Next, it assigns to the Path property of this ScriptReference object the virtual path of the JavaScript file... this._searchResultAreaDiv.style.display = “block”; AmazonSearchScriptControl Listing 1 8-1 5 presents the implementation of the AmazonSearchScriptControl script server control As I mentioned earlier, this script server control enables page developers to use familiar imperative and declarative ASP.NET techniques to program against the underlying AspNetAjaxAmazonSearch ASP.NET AJAX client-side control I’ll discuss the methods and properties... properties of the AspNetAjaxAmazonSearch client control: Getter or Setter Method Description get_searchTextBox Gets a reference to the search text box DOM element set_searchTextBox Sets a reference to the search text box DOM element get_searchButton Gets a reference to the search button DOM element set_searchButton Sets a reference to the search button DOM element get_htmlGenerator Gets a reference to the... this._onSuccess); this._onFailureHandler = Function.createDelegate(this, this._onFailure); } function CustomComponents3$AspNetAjaxAmazonSearch$_onSearchButtonClick(evt) { (continued) 783 c18.indd 783 8/20/07 7:56:10 PM Chapter 18: Web Services Bridges and Transformers Listing 1 8-1 4 (continued) this._pageIndex = 1; this._searchQuery = this._searchTextBox.value; this._searchMethod( {“pageIndex”: this._pageIndex,... previous button DOM element set_previousButton Sets a reference to the previous button DOM element get_pageIndex Gets the current page index set_pageIndex Sets the current page index get_searchMethod Gets a reference to the search method set_searchMethod Sets the reference to the search method initialize As you can see from Listing 1 8-1 4, the AspNetAjaxAmazonSearch client control overrides the initialize... CustomComponents3.AspNetAjaxAmazonSearch.prototype = { get_searchTextBox: CustomComponents3$AspNetAjaxAmazonSearch$get_searchTextBox, set_searchTextBox: CustomComponents3$AspNetAjaxAmazonSearch$set_searchTextBox, get_searchButton: CustomComponents3$AspNetAjaxAmazonSearch$get_searchButton, set_searchButton: CustomComponents3$AspNetAjaxAmazonSearch$set_searchButton, get_searchResultAreaDiv: CustomComponents3$AspNetAjaxAmazonSearch$get_searchResultAreaDiv, . against the underlying HtmlGenerator ASP. NET AJAX client-side component AspNetAjaxAmazonSearch Listing 1 8-1 4 presents the implementation of the AspNetAjaxAmazonSearch client control. I’ll. Listing 1 8-1 4: The AspNetAjaxAmazonSearch Client-side Control Type.registerNamespace(“CustomComponents3”); CustomComponents3.AspNetAjaxAmazonSearch = function CustomComponents3$AspNetAjaxAmazonSearch(associatedElement) { . CustomComponents3$AspNetAjaxAmazonSearch$set_searchMethod, initialize: CustomComponents3$AspNetAjaxAmazonSearch$initialize, (continued) c18.indd 785c18.indd 785 8/20/07 7:56:10 PM8/20/07 7:56:10 PM Chapter 18: