Building the ProductService Web Service
In this chapter, you will create the ProductService Web service. This Web service will
expose two Web methods. The first method will allow the user to calculate the cost of
buying a specified quantity of a particular product in the Northwind Traders database,
and the second method will take the name of a product and return all the details for that
product.
Creating the ProductService Web Service
In the first exercise, you will create the ProductService Web service and implement the
HowMuchWillItCost Web method. You will then test the Web method to ensure that it
works as expected.
Create the Web service
1. In the Microsoft Visual Studio 2005 programming environment, create a new Web
site using the ASP.NET Web Service template. Make sure you specify File System
as the Location, and Visual C# for the Language. Create the Web site in the
\Microsoft Press\Visual CSharp Step by Step\Chapter 28\NorthwindServices
folder in your My Documents folder.
IMPORTANT
Ensure you select the ASP.NET Web Service template and not the ASP.NET Web
Site template.
Visual Studio 2005 generates a Web site containing folders called App_Code and
App_Data, and a file called Service.asmx. The .asmx file contains the Web service
definition. The code for the Web service is defined in the Service class, stored in
the file Service.cs in the App_Code folder, and displayed in the Code and Text
Editor window.
2. In the Solution Explorer, click the NorthwindServices project. In the Properties
window, set the Use dynamic ports property to False, and set the Port number
property to 4500.
By default, the Development Web server provided with Visual Studio 2005 picks
a port at random to reduce the chances of clashing with any other ports used by
other network services running on your computer. This feature is useful if you are
building and testing ASP.NET Web sites in a development prior to copying them
to a production server such as IIS. However, when building a Web service it is
more useful to use a fixed port number as client applications need to be able to
connect to it.
3. In the Service.cs file in the Code and Text Editor window, examine the Service
class; it is descended from System.Web.Services.WebService. Scroll to the bottom
of the class. A sample Web service method called HelloWorld is provided by the
Visual Studio 2005 template. This method simply returns the string, “Hello
World.” Notice that all methods that a client can call must be tagged with the
[WebMethod] attribute. Comment out the HelloWorld method and the
[WebMethod] attribute; you will not need this method in this exercise.
4. Above the Service class you can see two more attributes: [WebService] and
[WebServiceBinding]. The [WebServiceBinding] attribute identifies the level of
the Web services interoperability specification that the Web service conforms to.
You can ignore this attribute in this chapter and leave it set to its default value.
The [WebService] attribute indicates the namespace used to identify the Web
service. Change the value of this attribute, as shown below:
5. [WebService(Namespace="http://www.contentmaster.com/NorthwindServices")]
6. [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
7. public class Service : System.Web.Services.WebService
8. {
9.
}
10. Right-click the NorthwindServices project in the Solution Explorer, and then click
Add New Item. In the Add New Item dialog box, click the Web Configuration File
template. Make sure the name of the file is set to Web.config and then click Add.
This action adds a Web configuration file to your project, containing default
settings. The Web.config file appears in the Code and Text Editor window.
11. Modify the <connectionStrings/> element in the Web.config file. Add the
following <add> sub element that defines a new connection string that you will
use for connecting to the Northwind database. Replace YourServer with the name
of your computer. Make sure you add a </connectionStrings> element:
12. <connectionStrings>
13. <add name="NorthwindConnectionString"
14. connectionString="Data Source=YourServer\SQLExpress; Initial
Catalog=Northwind;
15. Integrated Security=True"
16. providerName="System.Data.SqlClient"/>
</connectionStrings>
17. Display the Service.cs file in the Code and Text Editor window. Add the following
method to the Service class, underneath the commented-out HelloWorld method:
18. [WebMethod]
19. public decimal HowMuchWillItCost(string productName, int howMany)
20. {
}
This method expects the client to pass in the name of a product found in the
Products table in the Northwind Traders database, and a quantity of that product.
The method will use the information in the database to calculate the cost of
supplying this quantity of the product and pass this cost back as the return value of
the method.
21. Add the following using statements to the top of the file:
22. using System.Configuration;
using System.Data.SqlClient;
This System.Configuration namespace contains classes that you can use for
reading configuration settings from the Web.config file. The
System.Data.SqlClient namespace contains the Microsoft ADO.NET classes for
accessing Microsoft SQL Server.
23. In the HowMuchWillItCost Web method, type the following statements:
SqlConnection sqlConn = null;
try
{
ConnectionStringSettings cs =
ConfigurationManager.ConnectionStrings["NorthwindConnectionString"];
string connString = cs.ConnectionString;
sqlConn = new SqlConnection(connString);
SqlCommand sqlCmd = new SqlCommand();
sqlCmd.CommandText = "SELECT UnitPrice FROM Products " +
"WHERE ProductName = '" + productName + "'";
sqlCmd.Connection = sqlConn;
sqlConn.Open();
decimal price = (decimal)sqlCmd.ExecuteScalar();
return price * howMany;
}
catch(Exception e)
{
// Handle the exception
}
finally
{
if (sqlConn != null)
sqlConn.Close();
}
This code the connection string called NorthwindConnectionString from the
Web.config file by using the static ConnectionStrings property of the
ConfigurationManager class. This property returns the corresponding entry from
the Web.config file. The entry contains information such as the name of the
connection string, the provider, and the connection string itself. You can extract
the connection string from this entry by using the ConnectionString property.
The code then connects to the Northwind Traders database and runs a SQL
SELECT statement to retrieve the UnitPrice column for the selected product in the
Products table. The ExecuteScalar method is the most efficient way of running a
SELECT statement that returns a single value. The UnitPrice column is stored in
the price variable, which is then multiplied by the howMany parameter that is
passed in to calculate the cost.
NOTE
Refer back to the section “Using ADO.NET Programmatically” in Chapter 23,
“Using a Database,” if you need to refresh your memory on using ADO.NET to
access a SQL Server database.
The Web service uses a try...catch block to trap any runtime errors, although it
does not validate the parameters passed in (for example, the client might supply a
negative value for the howMany parameter). You can add the necessary code to
validate the parameters yourself.
It is important to make sure you close the connection to the database, even after an
exception. That is the purpose of the finally block.
If an exception occurs, you should capture the details somewhere. It is usually not
advisable to send the details of the exception back to the user as it might not mean
much to them, and there can also be security concerns if too much information
about the internal workings of your Web service is reported back to the user
(details such as the names and addresses of databases are just the sort of things
that hackers trying to break into your system will find useful). However, the
administrator for the Web site should be very interested in this information. The
ideal place to capture details of Web service exceptions is the Windows Event
Log.
24. Add the following using statement to the top of the file:
using System.Diagnostics;
This is the namespace that contains the classes for interacting with the event logs.
25. Add the following method to the Service class. Notice that this is a local, private
method and is not tagged with the [WebMethod] attribute:
26. private void handleWebException(Exception e)
27. {
28. EventLog log = new EventLog("Application");
29. log.Source = "NorthwindServices";
30. log.WriteEntry(e.Message, EventLogEntryType.Error);
}
These statements add an entry to the Windows Application event log containing
the details of the exception passed in as the parameter, flagging it as an error (you
can also store warnings and informational messages in the event log).
However, writing to any Windows event log is a privileged operation, and requires
that the Administrator for your computer has granted you the appropriate access
rights. You will see how to grant these rights in the next exercise.
31. In the catch block for the HowMuchWillItCost Web method, remove the comment
and type the following statements. The first statement calls the
handleWebException method, passing it the exception that occurred as its
parameter. The throw statement throws an empty exception, which simply causes
an “HTTP 500 – Internal server error” page to be displayed in the user's browser:
32. catch(Exception e)
33. {
34. handleWebException(e);
35. throw new Exception();
36. }
37. On the Build menu, click Build Web Site to compile the Web service.
The Structure of a Web Service
Web services in the .NET Framework are similar to ASP.NET Web applications
inasmuch as they consist of two parts: the .asmx file which defines the Web service, and
a C# code file with the suffix .cs. The.cs file actually contains the C# code for the
methods that you add to the Web service, and is the file displayed in the Code and Text