Adding References to the Web Service to Your Client

 <  Day Day Up  >  

Right-click on the UseWS project's References section and select Add Web Reference. You'll see the Start Browsing for Web Services screen shown in Figure 5.5.

Figure 5.5. Browse for Web Services.
graphics/05fig05.jpg

This lets you pick a Web service from your development machine or from any computer on the Internet. Select the first link, Web Services on the Local Machine, and you'll be able to pick your new Web service from the Web services that you've built on your development computer, as shown in Figure 5.6. This screen is a welcome addition to Visual Studio 2003. The first release of Visual Studio required you to remember the name of your WSDL file, and it's easy to forget when you're building half a dozen of them a day.

Figure 5.6. Web Services on the local machine.
graphics/05fig06.jpg

Select Chapter5WebService and you'll see the screen shown in Figure 5.7, which confirms that the functions and subs that we added are indeed available.

Figure 5.7. Add Reference confirmation dialog.
graphics/05fig07.jpg

Finally, you'll need to add a dataset to hold the customer records returned from the Web service. Drag a Dataset from the Data tab of the toolbox and drop it on the form. The dialog that appears will offer to base the dataset, not on a DataAdapter as in our previous examples, but rather on the Web Reference that we added. Select it and name it dsAllCustomers . This creates a typed dataset that's added to the project. You'll still need to fill it, but the code will be a little different.

Code for the Windows Application to Use the Web Service

The code to perform the functions represented by the buttons on the main application form is shown in Listing 5.21.

Listing 5.21. Code to Interact with the Web Service Functions
 Private Sub frmAllCustomers_Load( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles MyBase.Load     LoadData() End Sub Public Sub LoadData()     SuspendLayout()     Dim ws As New UseWS.localhost.Chapter5WebService     ws.Credentials = System.Net.CredentialCache.DefaultCredentials     DsAllCustomers1.Clear()     DsAllCustomers1.Merge(ws.GetAllCustomers())     DataGrid1.DataSource = DsAllCustomers1     DataGrid1.DataMember = "Customers"     ResumeLayout(False) End Sub Private Sub cmdAdd_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles cmdAdd.Click     Dim frm As New frmEditOneCustomer     frm.RecordKey = "Add"     frm.ShowDialog()     LoadData() End Sub Private Sub cmdEdit_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles cmdEdit.Click     Dim Recordkey As String = _      DsAllCustomers1.Tables(0).Rows(DataGrid1.CurrentRowIndex)(0)     Dim frm As New frmEditOneCustomer     frm.RecordKey = Recordkey     frm.ShowDialog()     LoadData() End Sub Private Sub cmdDelete_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles cmdDelete.Click     Dim Recordkey As String = _      DsAllCustomers1.Tables(0).Rows(DataGrid1.CurrentRowIndex)(0)     Dim ws As New UseWS.localhost.Chapter5WebService     ws.Credentials = System.Net.CredentialCache.DefaultCredentials     ws.DeleteOneCustomer(Recordkey)     LoadData() End Sub Private Sub cmdClose_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles cmdClose.Click     End End Sub 

How It Works

The form's Load event calls the LoadData method to get the entire Customers table, which is returned as an XML dataset. I call this routine after any sort of change (add, edit, or delete) to the source table, so the routine clears the dataset, creates a proxy to host the Web service's methods , authenticates the proxy (that's what that modification to config.web was for), calls the GetAllCustomers method, and uses the Merge method of the proxy to dump the records into the dataset.

Because an XML dataset is the native data source for a DataGrid , we set the data grid's DataSource to the dataset. We also have to set the DataMember to the precise table name; if we don't, a little "+" appears in the grid for us to expand and pick a table ”never mind that there's only one. You can also use DataMember = dsAllCustomers.Tables(0) , but any time you can spell out what's happening in .NET you're better off. It's arcane enough as it is.

When the user clicks on either Add or Edit, we create an instance of the frmEditCustomer form class, which you'll see in the next section. In the case of an Edit, we pass the value of the key for the currently selected record in the grid, which is returned by the expression

 

 DsAllCustomers1.Tables(0).Rows(DataGrid1.CurrentRowIndex)(0) 

That (0) out at the end means "column 1", for reasons that were the subject of at least one rant in an earlier chapter. This is perhaps the oddest syntax that I've come across in .NET. But it returns the key of the record to edit. Passing the string "Add" instead will be handled by code in the Customer Edit form, which you'll see at the end of this section. In both cases, we use the instance's ShowDialog() method, which is like setting a FoxPro form's WindowType = 1 “ Modal and activating the form. The next line, LoadData() , executes when control returns from the modal form.

Delete is accomplished simply by using the value of the key field from the current record to call the Web service proxy's DeleteOneRecord() method. I did it a little differently just to demonstrate how Web service functions act almost exactly like methods on local classes. They can't operate on global variables , but they can pass parameters back and forth; and the parameters can be tables, in the form of datasets.

The EditCustomer Form

Figure 5.8 shows the EditCustomer form.

Figure 5.8. The Customer Add/Edit form ( frmEditCustomer.vb ).
graphics/05fig08.jpg

The form consists of labels and text boxes for each of the fields in the Customer Record. I also included a text box for the record key at the upper-right corner of the screen so that you can see what's happening, although it wouldn't be necessary or desirable in a production environment. In each text box, I set the Databinding for the Text property to the corresponding field in the dsOneCustomer dataset.

The code shown in Listing 5.22 either finds the record to edit and displays it on the screen, or adds a blank record and inserts the first five characters of a GUID (pronounced as two syllables, GOO-id) converted to uppercase.

The approach to passing a parameter is quite different in Visual Basic than in FoxPro. In FoxPro, you include a PARAMETERS statement as the first line in the INIT event code, and you've got parms . In Visual Basic, the easiest way is to create a property procedure and do the record lookup in its Set method, which is just like a FoxPro property's Assign method. The code that triggers this event is the statement frm.RecordKey = RecordKey in cmdEdit_Click method in Listing 5.21, and the statement frm.RecordKey="Add" in the cmdAdd_Click method in the same listing.

Listing 5.22. Code for the frmEditCustomer Form
 Public Property RecordKey() As String    Get        Return _RecordKey    End Get    Set(ByVal Value As String)        _RecordKey = Value        If _RecordKey = "Add" Then            DsOneCustomer1.Clear()            Dim dr As DataRow            dr = DsOneCustomer1.Tables(0).NewRow            Dim I As Integer            For I = 0 To dr.ItemArray.Length - 1                dr(I) = ""            Next            dr(0) = Guid.NewGuid.ToString.Substring(0, 5).ToUpper            DsOneCustomer1.Tables(0).Rows.Add(dr)        Else            Dim ws As New UseWS.localhost.Chapter5WebService            ws.Credentials = System.Net.CredentialCache.DefaultCredentials            DsOneCustomer1.Merge(ws.GetOneCustomer(_RecordKey))        End If    End Set End Property Private Sub cmdSave_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles cmdSave.Click     BindingContext(DsOneCustomer1, "Customers").EndCurrentEdit()     If DsOneCustomer1.HasChanges Then         Dim ws As New UseWS.localhost.Chapter5WebService         ws.Credentials = System.Net.CredentialCache.DefaultCredentials         Dim diffCustomers As New UseWS.localhost.dsOneCustomer         diffCustomers.Merge(DsOneCustomer1.GetChanges())         diffCustomers = ws.UpdateCustomers(diffCustomers)         DsOneCustomer1.Merge(diffCustomers)         DsOneCustomer1.AcceptChanges()         Close()     End If End Sub Private Sub cmdCancel_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) _  Handles cmdCancel.Click     Close() End Sub 

How It Works

If the record key is Add , it means that the user clicked on the Add button. What follows looks like a lot of code, and compared to FoxPro, it is. But you can't just APPEND BLANK and REFRESH in Visual Basic .NET. You have to Clear the dataset, create a DataRow object based on one of the dataset's rows using the NewRow() method, assign a blank string to all of the fields (that was easy because all of the fields in this table are of type character) so that they won't be DBNulls, and finally add the data row to the empty dataset. If they passed a valid record key, we instead call the Web server proxy's GetOneCustomer method and use the resulting returned XML string to fill the dataset. Databinding takes care of the rest.

The RecordKey property procedure is invoked back in the AllCustomers form in the frm.RecordKey = String statement. The Set method for a property procedure is just like a FoxPro property's Assign method. When you assign the value, the procedure executes. It looks complicated, but it works.

The cmdSave_Click code is also a little more complicated than FoxPro's TableUpdate() function, but not much more involved than the equivalent FoxPro Web Service proxy code generated by dragging your Web service name from the FoxPro toolbox to your code window. You have to end the current edit using the EndCurrentEdit() method, and then call the proxy Web service UpdateCustomers method passing it the changes in the record in the form of a DiffGram created using the GetChanges() method of the dataset. Finally, you have to call the dataset's AcceptChanges() method and close the form. The cmdCancel Click event just closes the form without doing anything.

Using Remoting Instead of Web Services

You should be aware that there is another technology for using remote data services with smart client applications. It's called remoting . Remoting sends data in a more compact format, and has many more options, than Web services. It's more complicated than XML Web Services, although I've seen examples that are only 30 or 40 lines of code.

Nonetheless, even the simplest implementation of remoting borders on a level of complexity that stretches the limits of the typical FoxPro developer's skill. .NET is simply a lot harder than FoxPro, and remoting is a pretty good example of that inherently greater complexity. For that reason, it's beyond the scope of this book. However, if you're intent on building a major smart client application and suspect that minimizing data traffic might become important, you should take a look at remoting.

 <  Day Day Up  >  


Visual Fox Pro to Visual Basic.NET
Visual FoxPro to Visual Basic .NET
ISBN: 0672326493
EAN: 2147483647
Year: 2004
Pages: 130
Authors: Les Pinter

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