Web Service Specification
This application will perform two basic functions:
- Return a list of customers from a database
- Add customers to a database
Database Specification
The database for this application can be created with the following script:
Create Database SpelunkingSilverlight
GO
Use SpelunkingSilverlight
GO
Create Table Customer
(CustomerID INTPrimary Key Identity,
CustomerName varchar(100))
Go
Insert Into Customer (CustomerName)Values ('Dash Point Software, Inc.')
Insert Into Customer (CustomerName) Values('Takenote Technologies')
Creating the Web Service
With your specification in hand, you can go to work creating your web service. To create your web service, do the following:
- Right-click your solution and select Add > New Project from the pop-up menu.
- From the New Project dialog box, choose Visual Basic > Web > ASP.NET Web Service Application.
- Change the framework to .NET Framework 2.0.
- Choose your folder and name your solution “SpelunkingSilverlightWebServices”. Your New Project dialog box should look like Figure 1:
.png)
Figure 1. The New Project dialog box
NOTE: Don’t forget to change the framework version to 2.0 for this application. If you do not your web services call will not work.
Once your project has been created, you need to make some changes. The first step is to rename the default Service1.ASMX file to SilverlightServices.asmx. Remember to change the name of the web service class to SilverlightServices in both the SilverlightServices.asmx.vb and SilverlightServices.asmx files. Finally, right-click the SilverlightServices.asmx file and click “Set as Default Page”.
After changing the default class to a class with a more meaningful name, you can go about the work of creating the actual service code.
Add the following import to your web service class:
Imports System.Data.SqlClient
After adding the proper imports statement, you can add the actual code that integrates with the database. This code is included below:
<WebMethod()> _
Public Function GetCustomers() As String
Dim cRetVal AsString = ""
Try
Dim oConn As New SqlConnection
oConn.ConnectionString = _
"<<Data Source=(local);Initial Catalog=SpelunkingSilverlight;User Id=<<LALA>>;Password=<<LALA>>;"
oConn.Open()
Dim oCmd AsNew SqlCommand
oCmd.Connection = oConn
oCmd.CommandText = "select * from customer"
Dim oda As New SqlDataAdapter
oda.SelectCommand = oCmd
Dim ODS AsNew DataSet
oda.Fill(ODS, "customers")
oConn.Close()
cRetVal = "<CUSTOMERS>"
For Each oRow As DataRow In ODS.Tables(0).Rows
cRetVal += "<CUSTOMER>" + oRow.Item("customername") + "</CUSTOMER>"
Next
cRetVal += "</CUSTOMERS>"
Catch ex As Exception
cRetVal = ex.ToString
End Try
Return cRetVal
End Function
<WebMethod()> _
Public Function AddCustomer(ByVal CustomerName As String) As String
Dim cRetVal AsString = ""
Try
Dim oConn AsNew SqlConnection
oConn.ConnectionString = _
"<<Data Source=(local);Initial Catalog=SpelunkingSilverlight;User Id=<<LALA>>;Password=<<LALA>>;"
oConn.Open()
Dim oCmd AsNew SqlCommand
oCmd.Connection = oConn
oCmd.CommandText = "Insert Into Customer (CustomerName) Values (@customername)"
oCmd.Parameters.Add("@customername", SqlDbType.VarChar, 50)
oCmd.Parameters("@customername").Value = CustomerName
oCmd.ExecuteNonQuery()
Catch ex As Exception
cRetVal = ex.ToString
End Try
Return cRetVal
End Function
NOTE: Before you e-mail me, this code could be much more robust. This is just a simple demonstration of how to interact with web services.
You can now test and debug your web service methods by right-clicking your web service project and selecting Debug > Start New Instance from the popup menu. Figures 2 and 3 show the test page for your web service and the output of the GetCustomers method, respectively.
.png)
Figure 2. The test page for your web service
.png)
Figure 3. The output of the GetCustomers method
Silverlight 1.1 Web Service Requirements
The current incarnation of Silverlight has a security requirement when it comes to calling services. The 1.1 Alpha prevents cross-domain scripting attacks by requiring that web services run in the same folder structure as your front-end application. This will be fixed in the release version, but for now there are work-arounds. The first part of the work-around is the structure you use to create your web applications. The solution and project structure of this application was deliberate. All of these applications will run under the default localhost web site. Before continuing, you need to make changes to two projects. Do the following to your “SpelunkingSilverlightWebServices” and “SpelunkDomTester” projects:
- Right-click the project.
- Select Properties from the pop-up menu.
- Select the Web tab.
- Change the servers option to "Use IIS Web server".
- Click the Create Virtual Directory button.
- Save your project changes.
Figure 4 shows what your property page should look like.
.png)
Figure 4. The Web property page for your projects
This set of steps ensures your application will run under a nonchanging web structure; i.e., the ASP.NET Development Web Server will not assign a new port every time your application is launched.
Once you have created your web service application, you need to link your web service application and your Silverlight 1.1 application. This is the exact same set of steps you performed in Part 1.
- Drag and drop the following files from your SpelunkingSilverlightUI project:
- TestPage.html
- TestPage.html.js
- Silverlight.js
- Right-click the SpelunkingSilverlightWebServices project and select “Add Silverlight Link”
- From the provided dialog box, select the SpelinkingSilverlightUI project.
- Answer in the affirmative when asked about debugging Silverlight applications.
Once you have integrated these two projects, you can now go to work integrating the web service code into your Silverlight application.
Calling the Web Service
After creating the proxy, you are ready to begin calling your web services. Talking to web services manually is done via the BrowserHttpWebRequest object. This process of calling a web service is as follows:
- Create an HTTPWebRequest for your web service method.
- Set the ContentType property to: “application/json”
- Set the Method property to: POST
- Create an HTTPResponse object to open a stream to the web method call.
- Attach a reader to the HTTPResponse Object.
The following code is used to call the GetCustomers method.
Dim oReq As New Browser.Net.BrowserHttpWebRequest( New _
Uri("http://localhost/SpelunkingSilverlightWebServices/SilverlightServices.asmx/GetCustomers", _
UriKind.Absolute))
oReq.ContentType = "application/json"
oReq.Method = "POST"
Dim oResp As HttpWebResponse = oReq.GetResponse()
Dim oStreamReader As New System.IO.StreamReader(oResp.GetResponseStream())
Dim cCustomers As String = oStreamReader.ReadToEnd()
Once you have called your web service, you need to do something with the return value. As you have seen, the GetCustomers web service returns an XML string representing all of the customers in the database. Now it’s time to process the results of that query.
Silverlight 1.1 and XML Content
Silverlight 1.1 has a limited set of XML functionality. Basically, it has an XMLReader class that will allow you to iterate through an XML string in a rather primitive way. The following code uses the XMLReader to search for the customer XML collection returned from GetCustomers. After retrieving the customer list, some VB code is used to parse the customers and put them into an array. Finally, the code takes the customers added and adds them to the cboCustomers combo box.
Dim oStreamReader As New System.IO.StreamReader(oResp.GetResponseStream())
Dim oXMLReader As XmlReader = XmlReader.Create(oStreamReader)
Dim cResult AsString = ""
While oXMLReader.Read
If oXMLReader.NodeType = XmlNodeType.Text Then
cResult = oXMLReader.ReadContentAsString
End If
End While
'-- clean up the text
cResult = cResult.Replace("<CUSTOMERS>", "")
cResult = cResult.Replace("</CUSTOMERS>", "")
cResult = cResult.Replace("<CUSTOMER>", "~")
cResult = cResult.Replace("</CUSTOMER>", "")
'-- split the customer list here.
Dim aCustomers As String() = cResult.Split("~")
'-- add new OPTION to SELECT
Dim oSelectObject As HtmlElement = oDocument.GetElementByID("cboCustomerList")
For lnKount AsInteger = 1 To aCustomers.Count - 1
Dim oNewOption As HtmlElement = Me.oDocument.CreateElement("option")
oNewOption.SetAttribute("innerHTML", aCustomers(lnKount))
oNewOption.ID = System.Guid.NewGuid.ToString
oSelectObject.AppendChild(oNewOption)
Next
Sending Data to a Web Service
Sending data to a web service is a little different than the retrieval of data. The steps are:
- Create an HTTPWebRequest for your web service method.
- Set the ContentType property to " application/x-www-form-urlencoded"
- Set the Method property to POST.
- Create a URL-based set of data to post to your function call.
- Attach a StreamWriter to your request object.
- Write data to the request stream using the StreamWriter.
- Flush the streamwriter.
- Send the data by calling the request object’s GetResponse() method.
- Close the StreamWriter.
The following code takes the data entered into the txtCustomerInput and sends it to the AddCustomer method.
Dim oTextBox As HtmlElement = oDocument.GetElementByID("txtCustomerInput")
Dim cCustomerName As String = oTextBox.GetProperty(OfString)("Value")
Dim oReq AsNew Browser.Net.BrowserHttpWebRequest(New Uri("http://localhost/SpelunkingSilverlightWebServices/SilverlightServices.asmx/AddCustomer"))
Dim postData AsString = "CustomerName=" + cCustomerName
oReq.Method = "POST"
oReq.ContentLength = postData.Length
oReq.ContentType = "application/x-www-form-urlencoded"
Dim oStreamWriter As StreamWriter = Nothing
Dim oResp As HttpWebResponse = Nothing
oStreamWriter = New StreamWriter(oReq.GetRequestStream)
oStreamWriter.Write(postData)
oStreamWriter.Flush()
oResp = oReq.GetResponse()
oStreamWriter.Close()
Conclusion
As you can see, you can build some fairly powerful applications using Silverlight and web services. At this stage, Silverlight 1.1 is fairly picky, but usable for simple applications. Hopefully, this article helped you get started on your way to using Silverlight 1.1.
About Rod Paddock
Rod is a Microsoft MVP and owner of Dash Point Software, Inc. and co-owner of Red Matrix Technologies. Rod is a long-time software developer helping companies implement software-based solutions. Rod has worked for such companies as First Premier Bank, Six Flags, Microsoft, Intel, System Improvements, and many others. Rod has been a featured speaker at a number of conferences in the US, Canada, and Europe. Rod is a member of both the INETA and MSDN Canada speaker bureaus. Rod is also editor in chief of CoDe Magazine. Rod's blog is found at http://blog.dashpoint.com. Rod's web site is http://www.dashpoint.com.