The Order Submission XML Web Service

The OrderService provides the functionality for three tasks:

  • It allows the client to download product information through its GetPricingDataSet method.

  • It allows the client to submit a new order through the SubmitOrder method.

  • It allows the internal client to register for notification through the RegisterNotifyQueue method.

The structure of the OrderService is shown here:

 Public Class OrderService     Inherits System.Web.Services.WebService     Private DB As New DBComponent.TransactTables()     <WebMethod()> _     Public Function GetPricingDataSet() As DataSet         ' (Code omitted.)     End Function     <WebMethod()> _     Public Function SubmitOrder(ByVal order As Order, _       ByVal customerCode As Guid) As OrderState         ' (Code omitted.)     End Function     <WebMethod()> _     Public Function RegisterNotifyQueue(ByVal queuePath As String)         ' (Code omitted.)     End Function End Class 

In a more elaborate setup, the RegisterNotifyQueue method would be part of a separate XML Web service and would use some sort of authentication to ensure that it is accessible only to the internal client. Alternatively, the queue information could be stored in another location (such as an XML file or a separate table in the database).

The basic code for the RegisterNotifyQueue method is shown in Listing 17-13.

Listing 17-13 Registering a notification queue
 <WebMethod()> _ Public Function RegisterNotifyQueue(ByVal queuePath As String)     ' Store the queue path in application state.    Application("NotifyQueue") = queuePath End Function 

A. Datum's product catalog changes infrequently, but remote clients might request it often. To ensure optimum performance, the OrderService uses ASP.NET's caching capabilities to store the product information for 30 minutes. In this case, data caching is used rather than output caching. This allows the same product data to be retrieved from the cache in other Web methods. For example, the SubmitOrder Web method makes use of the cached product catalog to verify pricing information.

To provide data caching, the OrderService includes a private LookupPricing method. This method checks the cache and, if it can't find the DataSet, uses the database component to retrieve the information (as shown in Listing 17-14).

Listing 17-14 Retrieving the product catalog
 <WebMethod()> _ Public Function GetPricingDataSet() As DataSet     Return LookupPricing() End Function Private Function LookupPricing() As DataSet     Dim ds As DataSet = Context.Cache("Pricing")     If ds Is Nothing Then         ds = DB.Product.GetPricingDataSet() 
         ' Add an expiration date of 30 days to the DataSet.         ds.ExtendedProperties.Add("ExpiryDate", _           DateTime.Now.AddDays(30))         ' Insert the DataSet into the cache, and keep it there         ' for 30 minutes.         Context.Cache.Insert("Pricing", ds, Nothing, _           DateTime.Now.AddMinutes(30), TimeSpan.Zero)     End If     Return ds End Function 

The LookupPricing method also inserts an additional piece of information into the DataSet: an extended property that stores the suggested expiry date. The client uses this information to determine when to query the service again for new product information. Currently, the DataSet is set to expire 30 days into the future, but you could also implement a fixed date that depends on the start of a business quarter, the first day of the month, or any other criteria.

The final part of the XML Web service is the SubmitOrder method, which adds the order information to the database. This method is the most complex part of the XML Web service, and we'll examine it piece by piece.

First of all, the XML Web service defines an enumeration that represents possible order outcomes. (There is no value for a failed order insertion because this generates an unhandled exception that propagates back to the client. The client should use error-handling code to catch this exception and inform the user.)

 Public Enum OrderState     SentToCoordinator     LoggedInDatabaseOnly End Enum 

The SentToCoordinator value indicates that the order was added and that a notification message was sent. The LoggedInDatabaseOnly value indicates that the order was added but the notification message was not sent. Possible reasons include a missing notification queue (which is possible if no order-filling client is currently running) or an error that occurred while the service was attempting to send the message.

The first task the SubmitOrder method performs is to set the price for each item in the order. The XML Web service doesn't use the pricing data set by the client. That would constitute a serious security hole, allowing the client to manually edit the client-side DataSet and insert impossibly low prices. Instead, the current pricing information is retrieved and applied to each item. This process completes quite quickly because it uses the cached pricing information from the LookupPricing function (as shown in Listing 17-15).

Listing 17-15 Updating order prices
 Dim ds As DataSet = LookupPricing() Dim Ord As OrderItem Dim Station As Station For Each Station In order.Stations     For Each Ord In Station.OrderItems          ' Retrieve the corresponding price.        Dim Product As DataRow        Product = ds.Tables(1).Select( _                  "Price")     Next Next 

The XML Web service just applies the correct prices without examining the prices that were set by the client. This is the least disruptive approach, but there are other possibilities. For example, you can modify the code so that the XML Web service looks at the client prices and throws an exception if it finds an invalid price. This prevents the problem where a client orders a product at a different price than expected, but it can also lead to annoying errors if the client-side pricing is slightly out-of-date. A third approach is to return the final adjusted order from the Web method so that the client application can display the PriceOrderedAt values that were committed to the database.

Next, the XML Web service inserts the order into the database (by using the CommitNewOrder method from the database component) and sends the notification message, provided a notification queue is registered. The message simply consists of the newly added order ID. Alternatively, you could use a custom object for the message, but in this case only one piece of information is required. Using a simple message format ensures that you do not need to distribute an assembly to the order-filling client.

The code for committing the order and sending the notification message is shown in Listing 17-16.

Listing 17-16 Committing the order and sending the notification
 ' Add the order to the database. Dim ID As Integer = DB.Order.CommitNewOrder(order) ' Notify queue. Dim QueuePath = Application("NotifyQueue") If QueuePath <> "" Then     ' User error handling here.     ' An error should be harmless, and not propagate back to the     ' caller.     Try         Dim NotifyQueue As New MessageQueue(QueuePath)         NotifyQueue.Send(ID)         Return OrderState.SentToCoordinator     Catch         Return OrderState.LoggedInDatabaseOnly     End Try Else     Return OrderState.LoggedInDatabaseOnly End If 


Microsoft. NET Distributed Applications(c) Integrating XML Web Services and. NET Remoting
MicrosoftВ® .NET Distributed Applications: Integrating XML Web Services and .NET Remoting (Pro-Developer)
ISBN: 0735619336
EAN: 2147483647
Year: 2005
Pages: 174

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net