example, in the case of the RenderText method, the URL to the image is
required before the page can be rendered properly, so the code could be set up
to wait for a returned value at the last possible moment, which would be in the
PreRender method of the Web page. This allows the rest of the page processing
to be accomplished while the BeginRenderText Web method is being executed.
When calling the Begin method, the return value will be a WebClientAsync-
Result data type that implements the IAsyncResult interface. To get the origi-
nal return value from the Web method, the End method can be used.
The IAsyncResult contains the following members:
AsyncState. The object that was provided in the last parameter to the
Begin method call. This is useful for passing an object from the Begin to
the End method. This object is not required.
AsyncWaitHandle. This WaitHandle type can be used to wait for an
asynchronous operation to complete. The WaitAll, WaitAny, or WaitOne
methods of the WaitHandle may be executed to block the current thread
until this method has completed.
CompletedSynchronously. This value indicates whether the Begin call
completed synchronously or not.
IsCompleted. This value indicates whether the asynchronous method
has completed.
Abort. In addition to the members that IAsyncResult provides, the Web-
ClientAsyncResult also contains the Abort method. The return value
must cast as a WebClientAsyncResult using the CType command to exe-
cute this method. The Abort method cancels an asynchronous XML Web
service request.
The following code is an example of asynchronously executing the Render-
Text method:
Dim RenderResult As IAsyncResult
RenderResult = ti.BeginRenderText( _
“Regular”, “36”, “Impact”, “My Home Page”, “LightBlue”, “Blue”, _
Nothing, Nothing)
‘Do some work
.RenderResult.AsyncWaitHandle.WaitOne()
Image1.ImageUrl = ti.EndRenderText(RenderResult)
In this example, the BeginRenderText method requires the same parameters
as the RenderText method plus an additional parameter for a callback function
and another parameter for the AsynchState object. These added parameters
are not used with this approach, but are used in the following callback func-
tion approach.
After the BeginRenderText method has been executed, the code continues to
execute without waiting for the return value. Additional work can be done,
688 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:06 AM Page 688
and when the additional work has been completed, the thread can be paused
to wait for the asynchronous method to complete by executing the WaitOne
method of the AsyncWaitHandle. Once the asynchronous method has com-
pleted, a call to the EndRenderText method retrieves the return value.
Asynchronous Execution Using a Callback Function
The use of the callback function is best suited for situations in which the exe-
cuting code never needs to pause to wait for a result, but some processing may
need to be executed upon return. For example, when printing a document,
there is no need to wait for the document to print before continuing the code
execution, but if the printing fails, a code in the callback can be used to notify
the user of the failure.
When calling the Begin method, two addition parameters must be included;
the callback and the AsyncState. In the previous example, these were set to
nothing. In this example, a callback function will be supplied to handle the
return value, and the AsyncState will be supplied to pass an object from the
Begin method to the End method. The AsyncState object can be any object
type, although it is usually the original object that called the Begin method.
The return value will be a WebClientAsyncResult data type that implements
the IAsyncResult interface, which, optionally, may be used. To get the original
return value from the Web method, the End method can be used. The End
method should be executed within the callback function.
The following code can be used to execute a Web method asynchronously
using a callback function to handle the returned value:
Dim ti As TextImaging.TextToImage
Public Sub RenderTextCallback(ByVal resAr As IAsyncResult)
Dim i As System.Web.UI.WebControls.Image = _
CType(resAr.AsyncState, System.Web.UI.WebControls.Image)
i.ImageUrl = ti.EndRenderText(resAr)
End Sub
Private Sub Page_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
ti = New TextImaging.TextToImage()
Dim callback As New AsyncCallback(AddressOf RenderTextCallback)
ti.BeginRenderText( _
“Regular”, “36”, “Impact”, _
“My Home Page”, “LightBlue”, “Blue”, _
callback, Image1)
End Sub
In this example, a method called RenderTextCallback has been created to
handle the assignment of the return value to the Image control’s ImageURL
property. The BeginRenderText method requires the same parameters as the
Creating Web Services 689
r 430234 Ch16.qxd 7/1/03 9:06 AM Page 689
RenderText method plus an additional parameter for a callback function and
another parameter for the AsynchState object. The callback parameter is
assigned an instance of AsyncCallback, which is a reference to the Render-
TextCallback method. The AsynchState parameter can contain a reference to
any object and is used to pass an object from the Begin to the End method. In
this case, the Image1 control was passed to the End method, which allows the
End method to populate the ImageURL of Image1.
Building a Visual Studio .NET Web Service
The balance of this chapter is devoted to building a Web service and register-
ing the Web service with the Microsoft UDDI provider.
Create the Project
A Web service can be created by starting Visual Studio .NET and creating an
ASP.NET Web service Application, as shown in Figure 16.12. This example cre-
ates the Web service that was consumed in the previous session.
Create the TextToImage Class
A new class file, called TextToImage.asmx, has been added to the project. The
TextToImage class contains the following code at the top of the file:
Imports System.Web.Services
Imports System.Drawing
<WebService(Namespace:=” _
Description:=”<table border=’0’><tr><td>
<img src=’ />Figure 16.12 Create the Web service by selecting the ASP.NET Web service.
690 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:06 AM Page 690
border=’0’></td><td><font size=’4’>
Glenn Johnson Technical Training<br>
Text to Image Web Service.</font></td></tr><tr><td colspan=’2’>
Be sure to visit <a href=’’>GJTT.com</a>
for additional .NET support. If any questions, feel free to
<a href=’mailto:?subject=Zip Code Web Service’>
email me.</a></td></tr></table>”)> _
Public Class TextToImage
Inherits System.Web.Services.WebService
In this code, the System.Drawing namespace is used. This also requires a
reference to the System.Drawing.dll file.
The attribute that is called WebService has been placed before the TextToIm-
age class. This attribute offers the ability to set the Web service namespace and
assign a description to the Web service. The namespace assignment is a
requirement for public Web services, but the Web service will still operate even
if the WebService attribute does not exist.
The Description property of the attribute displays on the Web page that is
automatically created when this .asmx page is displayed. Notice that the
description may contain HTML tags.
The following methods are helper methods for the RenderText method,
which performs the real work. Each method that contains a WebMethod
attribute will automatically be exposed as a Web method. This is the required
attribute to enable Web services:
<WebMethod(Description:=”Returns a DataSet containing all “ + _
“of the settings that can be used”)> _
Public Function LoadSettings() As DataSet
Dim ds As New DataSet(“TextSettings”)
‘Create the Color table.
ds.Tables.Add(MakeTable(“Colors”, “ColorName”, LoadColors()))
‘Create the Font Family table.
ds.Tables.Add(MakeTable(“FontFamily”, “FontName”, _
LoadFontFamily()))
‘Create the Font Styles table.
ds.Tables.Add(MakeTable(“FontStyles”, “StyleName”, _
LoadFontStyles()))
‘Create the Font Sizes table.
ds.Tables.Add(MakeTable(“FontSizes”, “Size”, LoadFontSizes()))
Return ds
End Function
Private Function MakeTable(ByVal TableName As String, _
ByVal ColumnName As String, _
ByVal StringArray As String()) As DataTable
Dim dt As New DataTable(TableName)
Dim dc As New DataColumn(ColumnName, GetType(String))
dt.Columns.Add(dc)
Dim stringValue As String
For Each stringValue In StringArray
Creating Web Services 691
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 691
Dim dr As DataRow = dt.NewRow()
dr.Item(0) = stringValue
dt.Rows.Add(dr)
Next
Return dt
End Function
<WebMethod(Description:= _
“Returns an string array of colors that can be used”)> _
Public Function LoadColors() As String()
Return System.Enum.GetNames(GetType(KnownColor))
End Function
<WebMethod(Description:= _
“Returns an string array of fonts that can be used”)> _
Public Function LoadFontFamily() As String()
Dim b As New Bitmap(1, 1)
Dim g As Graphics = Graphics.FromImage(b)
Dim a As New ArrayList()
Dim arFamily() As FontFamily = FontFamily.GetFamilies(g)
Dim x As Integer
Dim FontFamilyList(arFamily.Length - 1) As String
For x = 0 To arFamily.Length - 1
FontFamilyList(x) = arFamily(x).Name
Next
Return FontFamilyList
End Function
<WebMethod(Description:= _
“Returns an string array of font styles that can be used”)> _
Public Function LoadFontStyles() As String()
Return System.Enum.GetNames(GetType(FontStyle))
End Function
<WebMethod(Description:= _
“Returns an string array of font sizes that can be used”)> _
Public Function LoadFontSizes() As String()
Dim startSize As Integer = 6
Dim endSize As Integer = 100
Dim FontSizeList(endSize - startSize) As String
Dim X As Integer
For X = 0 To endSize - startSize
FontSizeList(X) = (startSize + X).ToString()
Next
Return FontSizeList
End Function
Each helper method is exposed as a Web method, which simplifies the task
of populating drop-down boxes with valid data. Most of these methods return
an array of strings, except the LoadSettings method. The LoadSettings method
will execute each of the other load methods and populate a dataset with this
information, which can be returned to the client as a single call. The MakeTable
method is a helper method for the LoadSettings method and does not need to
be exposed as a Web method.
692 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 692
The last Web method is the RenderText method. This method requires para-
meters for the font, background and foreground color, font size, font style, and
the text to render. In the following code, this method creates a bitmap and
returns a string containing the URL to the bitmap. This bitmap will be cached
for 10 minutes.
<WebMethod(Description:=”<font color=’#FF0000’><b>” + _
“This is the main function.</b></font><br>” + _
“This returns an string containing the URL of the “ + _
“image that has been rendered. The image URL is “ + _
“cached for 10 minutes.”)> _
Public Function RenderText(ByVal FontStyle As String, _
ByVal FontSize As String, _
ByVal FontFamily As String, _
ByVal ImageText As String, _
ByVal BackgroundColor As String, _
ByVal ForegroundColor As String) As String
Dim imgBitmap As New Bitmap(1, 1)
Dim fStyle As FontStyle
fStyle = System.Enum.Parse(GetType(FontStyle), FontStyle)
Dim fSize As Single
fSize = Single.Parse(FontSize)
Dim strFont As Font
strFont = New Font(FontFamily, fSize, fStyle)
Dim str As String = ImageText
Dim cBackground As Color
cBackground = Color.FromName(BackgroundColor)
Dim cForeground As Color
cForeground = Color.FromName(ForegroundColor)
‘Get the size of the text string.
If str = “” Then str = “No text defined.”
Dim g As Graphics = Graphics.FromImage(imgBitmap)
Dim strSize As Size
strSize = g.MeasureString(str, strFont).ToSize()
‘Create the bitmap.
imgBitmap = New Bitmap(strSize.Width, strSize.Height)
g = Graphics.FromImage(imgBitmap)
g.Clear(cBackground)
g.DrawString(str, strFont, New SolidBrush(cForeground), 0, 0)
Dim imgGuid As String
imgGuid = GUID.NewGuid().ToString()
imgGuid = imgGuid.Replace(“-”, “”)
Context.Cache.Insert(imgGuid, imgBitmap, Nothing, _
DateTime.Now.AddMinutes(10), Nothing)
Dim url As String
If Context.Request.ServerVariables(“https”) = “off” Then
url = “http://”
Else
url = “https://”
End If
Creating Web Services 693
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 693
url &= Context.Request.ServerVariables(“HTTP_HOST”)
url &= Context.Request.ApplicationPath()
url &= “/ImageURL.aspx”
Return url & “?ImageID=” & imgGuid
End Function
End Class
The RenderText method creates the image based on the parameters that
have been passed into the method. Chapter 11, “Working with GDI+ and
Images,” contains a more detailed explanation of the rendering process. Once
the bitmap has been created, a Globally Unique ID (GUID) is created to repre-
sent this image. The dashes were removed from the GUID since they only add
more length to the URL. The image is cached for 10 minutes. The last section of
this method creates the URL to the cached bitmap.
Creating the ImageURL Page
The previous code was responsible for creating an image from the parameters
supplied to the RenderText method. Because HTML image tags require a URL
to the image, the RenderText creates the URL. The URL points to the
ImageURL.aspx page, which expects to receive an ImageID GUID. This page
will extract the image from the cache and deliver it to the client.
Imports System.Drawing
Imports System.Drawing.Imaging
Public Class ImageURL
Inherits System.Web.UI.Page
Private Sub Page_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
If Not Request(“ImageID”) Is Nothing Then
If Not Cache(Request(“ImageID”)) Is Nothing Then
Dim b As Bitmap
b = CType(Cache(Request(“ImageID”)), Bitmap)
Response.Clear()
Response.ContentType = “image/jpeg”
b.Save(Response.OutputStream, _
ImageFormat.Jpeg)
Response.End()
Return
End If
End If
End Sub
End Class
If the image is not in the cache, a Not Found image could be created. Also, an
image could be generated with any exception message as well. It’s important to
694 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 694
call Response.End after saving the image to the response stream, because this
command will end the page’s processing to ensure that none of the .aspx page
is mistakenly sent to the client.
Registering the Web Service with a UDDI Registry
Registering a Web service with a UDDI business registry (UBR) requires a bit
of work, but once the Web service is registered, users can locate and use the
Web service. This section covers the registration process at Microsoft’s UDDI
site. Before starting the registration process, the Web service should be created
and deployed on a server that is accessible from the Internet.
Visual Studio .NET makes it easy for developers to find Web services using
UDDI, and then add the Web service into a project through the Add Web Ref-
erence feature. For a Web service to be visible via this feature, the Web service
must be properly registered in the UDDI registry. The WSDL file must be reg-
istered as a tModel, and the Web service itself must be registered as a binding
that refers to your tModel.
To follow the best practice and correctly register a Web service using the
Microsoft Web interface at , a UDDI account must
be obtained at the site. After an
account has been registered, the following steps must be followed.
Create the Technology Model (tModel)
The term tModel is short for technology model. A tModel is typically used to pro-
vide technical information about a programmatic interface, such as a Web Ser-
vice Description Language (WSDL) file, which describes the conventions that
are supported by an interface.
Figure 16.13 shows the tModel screen, which contains several tabs. The
Details tab contains the tModel name and description.
The Identifiers tab contains a list of Identifiers, which are optional descrip-
tions intended to enhance the discovery of tModels and providers in Search.
The Categories tab contains categorization schemes, which are predefined sets
of categories that are represented in a hierarchical fashion. Searches for tMod-
els may be performed by drilling the hierarchy. Add one or more categories by
selecting from available schemes.
To ensure Web service visibility when using Visual Studio .NET to search for
a Web service, be sure the following category is added to the tModel:
Categorization Scheme: uddi-org:types.
Key Name: Specification for a Web service described in WSDL.
Key Value: wsdlSpec.
Creating Web Services 695
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 695
Figure 16.13 The tModel screen showing two tModels. The Details tab contains the
tModel name and description.
The Document Overview tab is an HTTP-accessible resource, such as a
WSDL file or specification document, that usually contains technical informa-
tion for implementing or interacting with an interface. For Visual Studio .NET
Web services, this should be the URL to the Web service. The following URL
points to a Visual Studio .NET Web service:
/>This URL will be displayed as a hyperlink that the prospective user will
select to view the Web service information. This tab also includes the ability to
add Descriptions of the Web service, each in a different language. The descrip-
tion will be displayed with the URL to the Web service.
Add the Service Information
After the tModel has been defined, the service must be defined and bound to
the tModel. Figure 16.14 shows the services screen, which is available under
the provider’s node. Clicking the Add Service button displays the Details tab
window, which allows the service name to be entered in any languages. Ser-
vice descriptions may also be entered.
696 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 696
Figure 16.14 The Services tab. Services must be defined here and bound to the tModel.
The Bindings tab is used to bind, or connect, to a tModel. The Bindings sec-
tion has three tabs: Details, Bindings, and Categories.
The Details tab holds the name and description of the service. The Bindings
tab holds information that represents an access point for this service. A bind-
ing must be created to reference the tModel that has been created. The tModel
is referenced in the Instance Info tab of the Binding. Figure 16.15 shows the
link to the tModel. The Web service will not be found in a search from Visual
Studio .NET until the reference to the tModel has been set.
Figure 16.15 The reference from the service to the tModel must be set before the Web
service will be located in a Visual Studio .NET search.
Creating Web Services 697
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 697
Figure 16.16 The registration properties must be set up first.
Understanding the UDDI Menu Hierarchy
The UDDI menu hierarchy can be confusing, especially when it shows more
information than required. To help simplify this process, Figure 16.16, Figure
16.17, and Figure 16.18 show the menu hierarchy of the required elements.
Figure 16.17 Second, the tModel properties must be set up.
uuid:4d21fe73-c9d1-4b7b-a696-cdd30c44dde3
Name: Text To Image
tModel
Categorization Scheme: uddi-org:types
Key Name: Specification for a web service described in WSDL
Key Value: wsdlSpec
Instance Info - to a tModel
Categories
Overview Document
1
/>Overview URL
Overview Descriptions
(per Language)
Description - en
This is a Text to Image Conversion
3
tModels
Provider
Provider Key: 58eaf9c1-31dd-4803-8c67-ffe440cba519
Name: Glenn Johnson Technical Training
Contacts
Providers
My UDDI
Services
Contact
Glenn Johnson
2
1
tModels
698 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 698
The registration items are set up first, as shown in Figure 16.16. (Descrip-
tions that contain the en label denote English.) This simply involves the cre-
ation of a provider and a contact.
A tModel must be set up next, as shown in Figure 16.17. This involves creat-
ing a tModel, assigning a name, a category, and an overview document. Be
sure to assign the category called uddi-org:types as shown. This will expose
the Web service to Visual Studio .NET users. The overview document must be
set to the .asmx file of the Web service.
The Service properties must be set up last, as shown in Figure 16.18. The ser-
vice requires a name to be assigned, a description for the service, and a bind-
ing to be created. The names and descriptions must exist in English, and
optionally may exist in other languages. Notice that the binding will reference
the tModel that was defined in Figure 16.16.
Figure 16.18 The Service properties must be set up last.
Service Key: 6ef14a96-7a65-41c7-8cf8-521f97acec3b
Service
Binding Key: 8c19ee3a-1e5e-4147-85bf-92df58d2e738
Binding
/>Access Point
Names (per Language)
Name - en
Text To Image
2
3
Descriptions (per Language)
Description - en
This is a Text to Image Service
Descriptions (per Language)
Instance Info - to a tModel
Description - en
This is a Text to Image Service
Bindings
Services
Creating Web Services 699
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 699
Lab 16.1: Creating a Web Service
In this lab, you will create a Visual Basic .NET Web service that can be
used to return the orders that a customer has placed. This Web service
will use the DataComponent from Lab 15.1 to access SQL Server.
Add the Web Service File to the Orders Project
Although a new Web service can be created by creating a Web service
project, a Web service can be simply added to an existing Web applica-
tion. In this section, you will add a new Web service file to the existing
Order solution.
1. To start this lab, open the OrderEntrySystemSolution from Lab 15.1.
Right-click the OrderEntrySystemSolution in the Solution Explorer,
and click Check Out.
2. Right-click the Order project and click Add, Add Web service. For
the Web service name, type CustomersOrders.asmx.
3. In the Order project, assign a reference to the DataComponent
project.
4. Add the following Imports statement to the top of the Web service
file:
Imports System.Data.SqlClient
Imports DataComponent
5. Add a Web method called GetOrders, which will accept the Cus-
tomerID as a parameter.
6. Add code to the Web method to create a SQL Server connection.
7. Add code to replace any single quote characters in the CustomerID
with two single-quote characters.
8. Add code to create a SQL string containing the query.
9. Add code to execute the Db.ExecuteDataSet to return a DataSet to
the user. Your code should look like this:
Imports System.Web.Services
Imports System.Data.SqlClient
Imports DataComponent
<WebService(Namespace := “ _
Public Class CustomersOrders
Inherits System.Web.Services.WebService
<WebMethod()> Public Function GetOrders( _
ByVal CustomerID As String) As DataSet
700 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 700
Dim cn As New SqlConnection( _
“server=.;database=northwind;trusted_connection=true”)
CustomerID = CustomerID.Replace(“‘“, “‘’”)
Dim Sql As String
Sql = String.Format( _
“Select * from Orders where CustomerID=’{0}’”,
CustomerID)
Return Db.ExecuteDataSet(cn, Sql)
End Function
End Class
10. Build the project and save your work.
Testing the Web Service
In this section, you will test the Web service to verify that it operates as
expected prior to implementing this service in your application.
1. Right-click the Order project in the Solution Explorer and click Set
As StartUp project.
2. Right-click the CustomersOrders.asmx page and click Set As
Start Page.
3. Run the Web Application. The Web service page should be dis-
played, as shown in Figure 16.19. Although the page appears to be
functioning, a message is displayed that states that the namespace
needs to be changed from tempura.org to a custom namespace.
Figure 16.19 The Web service page. This page is functioning but displays a message to
change the namespace from tempura.org to a custom namespace.
Creating Web Services 701
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 701
4. Click the GetOrders hyperlink. A test page will be displayed with a
TextBox that allows a CustomerID to be entered. Enter a Cus-
tomerID, such as ALFKI, and click Invoke.
5. A new browser window will open. This window contains an XML
document that represents a DataSet called NewDataSet, and contains
a DataTable called Table (see Figure 16.20).
Figure 16.20 When GetOrders is invoked, the Web service returns a DataSet that is
represented as XML.
6. Close the browser windows to end the Web service application.
Implementing the Web Service
In this section, you will implement the Web service in the Customers Web
application. The CustomerList.aspx page will be modified by adding an
Orders button for each customer. Clicking the Orders button will cause
the page to change to a new page that will display the orders belonging
to the customer. Note that this page already has code to retrieve the
orders and order details tables, but that code will be ignored for the pur-
pose of demonstrating the Web service implementation.
1. Right-click the Customer project, and click Set As StartUp Project.
2. Right-click the CustomerList.aspx page, and click Set As Start Page.
3. Open the CustomerList.aspx.vb code-behind page.
702 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 702
4. Add a public variable to the top of the CustomerList class that will
expose the current customer ID. The code should look like this:
Public CurrentCustomerID As String
5. Locate the dgCustomers_Init method. This method is currently used
to add the Save button. Add code after the first button’s code to add
another button to display the orders. Your code should look like
this:
colButton = New ButtonColumn()
With colButton
.ButtonType = ButtonColumnType.PushButton
.CommandName = “ViewOrders”
.ItemStyle.Width = New Unit(100, UnitType.Pixel)
.ItemStyle.HorizontalAlign = HorizontalAlign.Center
.HeaderStyle.HorizontalAlign = HorizontalAlign.Center
.HeaderText = “View<br>Orders”
.Text = “Orders”
End With
dgCustomers.Columns.Add(colButton)
6. When a DataGrid button is clicked, it executes the
dgCustomers_ItemCommand method. Add code to transfer to the
ShowOrders.aspx page after setting the CurrentCustomerID vari-
able. Your code should look like this:
If e.CommandName = “ViewOrders” Then
‘Get Customer Key
Dim CustomerKey As String
CurrentCustomerID = dgCustomers.DataKeys(e.Item.ItemIndex)
Server.Transfer(“ShowOrders.aspx”)
End If
7. Add a new Web Form to the Customer project, called
ShowOrders.aspx. This page will display the orders in a DataGrid.
8. Add a DataGrid to the Web page.
9. Add a Web Reference to the Customer project. This is done by right-
clicking the References node of the Customer project in the Solution
Explorer and clicking Add Web Reference. In the Address box, type
the following URL to the CustomersOrders.asmx page:
http://localhost/Order/CustomersOrders.asmx
10. When the Web service’s test page is displayed, click the Add Refer-
ence button. A new node will be displayed, called Web References,
and the Web service will be displayed as a localhost sub node.
Rename the localhost to OrderInfo. This will display a Visual
SourceSafe message stating that renaming a file will cause problems
with the change history of the file. Click the Continue button.
Creating Web Services 703
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 703
11. Add code into the page’s load event method to retrieve the current
customer ID and call the Web method. Your code should look like
the following:
Private Sub Page_Load( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
‘Put user code to initialize the page here
Dim ws As New OrderInfo.CustomersOrders()
Dim custPage As CustomerList
custPage = CType(Context.Current.Handler, CustomerList)
Dim CurrentCustomerID As String
CurrentCustomerID = custPage.CurrentCustomerID
Dim ds As DataSet = ws.GetOrders(CurrentCustomerID)
DataGrid1.DataSource = ds
DataBind()
End Sub
12. Save your work.
13. Run the Web application. You may need to log into the Web site if
you did not click the Remember check box previously. The Cus-
tomerList.aspx page should be displayed, which contains an Orders
button for each customer.
14. Click the Orders button for one of the customers. This should cause
the ShowOrders.aspx page to be displayed, as shown in Figure 16.21.
Figure 16.21 The ShowOrders.aspx page made the call to the Web service and returned
a DataSet that only contained the orders for the current customer.
15. Save your changes and check the final solution back into Visual
SourceSafe.
704 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 704
Summary
■■
Web services provide a method for one application to communicate
with another application.
■■
Web services can be used in a departmental fashion in the corporate
intranet. Different departments may expose data via a Web service, and
complete applications may be built by simply gluing the Web service
pieces together.
■■
Simple Object Access Protocol (SOAP) is the protocol used to transfer
data to and from the Web service.
■■
Web Service Description Language (WSDL) is used to describe the Web
service’s interface.
■■
The Universal Description, Discovery, and Integration (UDDI) project
creates a platform-independent, open framework for describing ser-
vices, discovering businesses, and integrating business services using
the Internet.
■■
Disco is a mechanism that allows the discovery of the Web services
available to a server. Disco is not a W3C standard, but is a Microsoft-
driven initiative to enable the location of Web services on a computer.
This differs from UDDI, which enables the location of Web services on
the Internet.
■■
The proxy class is responsible for encapsulating Web service code into a
class that exposes the Web service data types and methods and transpar-
ently performs the assembly and disassembly of the SOAP messages.
■■
The term tModel is short for technology model. A tModel is typically
used to provide technical information about a programmatic interface,
such as a WSDL file that describes the conventions supported by an
interface.
Creating Web Services 705
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 705
Review Questions
1. What are two methods that create a Web service proxy class?
2. Name three methods of calling a Visual Studio .NET Web service.
3. How is an asynchronous method identifiable?
4. What technology can be used to advertise your Web service on the Web?
5. What technology can be used to locate a Web service on a user’s machine?
706 Chapter 16
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 706
Answers to Review Questions
1. Use the WSDL.exe utility or simply add a Web reference from Visual Studio .NET.
2. POST, GET, and SOAP Message.
3. By the Begin and End prefixes.
4. UDDI.
5. Discovery with disco or vsdisco files.
Creating Web Services 707
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 707
r 430234 Ch16.qxd 7/1/03 9:07 AM Page 708
709
Complex software systems usually involve many applications communicating
with each other and with databases. In the past, deploying large software sys-
tems required copying files to the destination location, because the COM com-
ponents required Registry entries to operate.
It’s not always possible to jump over to the .NET Framework, abandoning
the hundreds of COM components that have been developed over the past
several years. A phased approach can limit the risk involved.
Migrating to the .NET Framework usually means that a development team
must decide which COM components will be migrated to .NET and which
COM components will be used with COM interoperability. This comes with its
own set of challenges.
The first part of this chapter explores some methods for migrating from ASP
code to ASP.NET. Later, chapter examines early and late binding techniques
for using COM components. Finally, the chapter covers some methods for
deploying ASP.NET Web applications.
Deployment and Migration
CHAPTER
17
s 430234 Ch17.qxd 7/1/03 9:07 AM Page 709
Classroom Q & A
Q: We currently have a Web application that was developed using
Visual InterDev 6, and it contains several COM components. After
making changes to a COM component and compiling it, we try to
copy the COM component over the existing component that is on
the production server, but we constantly get an Access Denied
message. We usually have to either restart the WWW service or
reboot the machine to be able to overwrite the file. Has anything
been done to correct this problem with ASP.NET?
A: Yes. ASP.NET caches .NET components into memory when they
are loaded. A new .NET component can be simply copied over the
existing .NET component. ASP.NET will detect the new component
and start using it without requiring a reboot or restart of Internet
Information Server.
Q: Can Include files still be used with ASP.NET?
A: Yes. ASP.NET still allows Include files, but they are not recom-
mended. You can achieve better performance, maintainability, and
design by deriving your Web pages from a custom base class for
your common routines.
Q: Can existing COM components be utilized with ASP.NET, and can
they be early bound?
A: Absolutely. In this chapter we explore some methods for using
COM components.
Migration
This section examines ASP to ASP.NET migration, Visual Basic to Visual Basic
.NET language differences, COM to .NET migration, and COM interoperability.
ASP and ASP.NET Coexistence
Situations may exist where the size or complexity of the Web site dictates that
an ASP.NET application run alongside the ASP application. Internet Informa-
tion Server knows how to direct a request for an .asp or .aspx file to the correct
processing engine, primarily because the ASP.NET file extensions are different
from the ASP file extensions.
Being able to run ASP and ASP.NET pages in the same Web site does not
mean that ASP and ASP.NET will share Application and Session variables.
710 Chapter 17
s 430234 Ch17.qxd 7/1/03 9:07 AM Page 710
These technologies reside in different processes and can coexist in a rather iso-
lated fashion. Making ASP data available to the ASP.NET application is typi-
cally done by passing data in the QueryString or posting form data from an
ASP page to an ASP.NET page.
In many cases, it may be desirable to make architectural changes to the
application to take advantage of the ASP.NET or Visual Basic .NET features.
This may require sections of an ASP Web application to be migrated to
ASP.NET, rather than moving a page at a time.
ASP to ASP.NET Changes
One of the original design goals for ASP.NET was to be completely backward
compatible. However, changes were needed to achieve the desired platform
improvements and be compatible with the .NET Framework. This section
examines these differences. The code block in Listing 17.1 will be used for sev-
eral of the migration examples in this section.
<%@ Language=VBScript %>
<HTML>
<HEAD>
<META NAME=”GENERATOR” Content=”Microsoft Visual Studio 6.0”>
</HEAD>
<BODY>
<%
if request(“posted”)=”true” then
Dim lineCount
lineCount=1
printList “mycar”,lineCount
printList “mytruck”,lineCount
Response.Write(lineCount & “<br>”)
end if
sub printList(item,counter)
Dim r
set r = Response
r.Write( “<u>First list for “ & item & “</u><br>”)
counter=counter + 1
r.Write( request(item) & “<br>”)
counter=counter + 1
r.Write(“<u>Next list for “ & item & “</u><br>”)
counter=counter + 1
Dim x
for x=1 to request(item).Count
r.Write(request(item)(x) & “<br>”)
counter=counter + 1
next
end sub
Listing 17.1 Sample ASP code that needs to be migrated to ASP.NET. (continued)
Deployment and Migration 711
s 430234 Ch17.qxd 7/1/03 9:07 AM Page 711
%>
<form name=”frm” action=”” method=”get”>
Cars<br>
<INPUT type=”text” id=”text1” name=”mycar” value=”vw”>
<INPUT type=”text” id=”text2” name=”mycar” value=”audi”>
<INPUT type=”text” id=”text3” name=”mycar” value=”bmw”>
<br>
Trucks<br>
<INPUT type=”text” id=”text4” name=”mytruck” value=”ford”>
<br>
<INPUT type=”submit” value=”Submit” id=submit1 name=submit1>
<INPUT type=”hidden” id=”text5” name=”posted” value=”true”>
</form>
<%for each i in Request(“mycar”)%>
Car: <%=i%><br>
<%Next%>
</BODY>
</HTML>
Listing 17.1 (continued)
The code in Listing 17.1 contains a form with several text boxes. Values were
placed into the text boxes to eliminate the need to retype the values every time
that page is run. One of the input tags is a hidden field. This field is used to
indicate that the form has been submitted to the server. A server-side script
block checks to see if the page has been submitted and if it has, processes the
submitted data. A call is made to the printList subroutine for the cars and
again for the trucks. After the calls are made, the total line count is output to
the page. The printList subroutine first prints the Requested item and then
enumerates the list to print it.
At the bottom of the ASP code, another set of server-side scripts is included
to print a formatted list of all the cars. This routine uses a for-next loop to
accomplish its work.
Figure 17.1 shows the browser output when this page is run in Visual Inter-
Dev. To see this page, the Submit button must be clicked. The total line count
is eleven.
This page can be included in a Visual Studio .NET by right-clicking the proj-
ect, clicking Add, Add Existing Item, then clicking Files of Type *.* and navi-
gate to the .asp page. After the page is added, rename it with an .aspx
extension. When the page is renamed, a message box is displayed that states,
“There is no class file in the project associated with the Web Form ‘Inter-
DevTest.aspx’. Create class file now?” The choice depends primarily on the
amount of changes that are going to be made to the page when it is migrated
to ASP.NET. In this case, the minimum amount of changes will be made, and
the only goal in these samples will be to get the code to work with ASP.NET.
712 Chapter 17
s 430234 Ch17.qxd 7/1/03 9:07 AM Page 712