Microsoft.NET

……………………………………………….Expertise in .NET Technologies

Introduction to Web Services

Posted by Ravi Varma Thumati on October 21, 2009

The term “web service” has been used quite frequently lately: you hear people saying how good web services are and how they will dominate the future of software development, but what exactly are web services and how can we create them?

In this article we will explore the features of Microsoft ASP.NET Web Services, more specifically how to build web services. A real world example extending what I discuss in this article will be shown at the end of this article. It will utilize many things that you will learn throughout this article.

To understand this article fully, you are required to have some previous knowledge of C#, ASP.NET and ADO.NET. To try the examples shown in this article for yourself, you will need the .NET Framework and Internet Information Server 5 or higher installed on your Windows NT/XP/2000 PC.

What is a web service?

The term “web service” refers to a form of a component that can be used remotely. Microsoft offers two types of web services in their .NET framework: XML web services and .NET remoting. When developers refer to web services they usually mean XML web services, and in this article I will also refer to XML web services as just web services.

Web services are invoked remotely using SOAP or HTTP-GET and HTTP-POST protocols. Web services are based on XML and return an “answer” to the client in XML format. Web services have all the advantages of components plus many more. The most significant benefits include:

  • Language and platform independence: Web services can be built and consumed on any operating system just as long as that operating system supports the SOAP protocol and XML.
  • Automatic upgrade: Unlike components, if a web service requires an update, that update is propagated to all applications consuming that web service immediately. This is because the actual methods and properties for the web service are invoked from the web server remotely, meaning that each function contained within a web service appears as a “black box” to a client: they aren’t concerned with the way the function does its job, just as long as it returns the expected result.

Commonly Used Jargon
As with all new technologies, web services come with a lot of associated jargon. Here’s a list of some terms that you’ll come across as you begin your journey down the web services highway:

UDDI
Well, this isn’t the case at the moment, but I’m pretty sure that in the future there will be thousands of web services on the Internet. The question is how are we going to find the web services we are looking for? UDDI (Universal Description, Discovery and Integration) is the answer to that question. UDDI is a registry that provides a place for a company to register its business and the services that it offers. People or businesses that need a service can use this registry to find a business that provides the service.

When you search for a web service using UDDI’s web service or web browser, UDDI returns a listing of web services that matched your criteria. This list is returned in the form of a DISCO or WSDL document.

WSDL
WSDL (Web Services Description Language) is a language that describes a web service. It contains information such as where you can find the web service, methods and properties that it supports, its data types, and the protocol used to communicate with the web service. WSDL is based on the XML format and it’s used to create proxy objects. Basically, without a WSDL document, developers wouldn’t be able to use web services simply because they wouldn’t know which methods and properties they support and also which communication method any particular web service supports.

DISCO
DISCO (Abbreviated from discovery) is a list of WSDL documents. DISCO is used to group common web services together. DISCO documents are also in XML format.

SOAP
SOAP (Simple Object Access Protocol) is a protocol to transport data to and from the web server. It is in XML format and allows you to transport a variety of data types used in .NET. As an alternative to SOAP, we can use HTTP-GET and HTTP-POST, which will be covered later in the article. These protocols return the output in a non-SOAP format, however this output is still in XML format.
Web Services1

Simple web service

In this section we’ll build a simple web service to demonstrate the fundamentals of web service building. Our web service will contain just one method called HelloWorldMethod. HelloWorldMethod returns a string, “Hello World”. We’ll add modifications to this web service as we learn more about the available features of web services.

Before building a web service, a virtual directory or web application must be created using IIS. You can do this by loading the IIS snap-in with MMC (start -> run -> “mmc” -> console -> open -> c:\winnt\system32\inetsrv\iis.mmc), right clicking on your web site and choosing new -> virtual directory. Call the virtual directory “HelloWorld”.

The following code shows the most basic web service:

<%@ WebService%>

using System.Web.Services;

public class HelloWorld : WebService
{
[WebMethod]
public string HelloWorldMethod()
{
return "Hello World";
}
}

Copy the code above into your favourite text editor and save the file into the virtual directory we created above as HelloWorld.asmx.

[Note] The file extension for a web service is .asmx. [End Note]

You can now access our HelloWorld web service in your browser by visiting http://localhost/HelloWorld/HelloWorld.asmx.

You should see a page that looks like this:

Web Services2

This web page is automatically built by IIS using the WSDL of our web service. You can change how this page looks but that’s out of the scope for this article. You can view the raw WSDL by clicking on the link to “Service Description”, which will forward you to the WSDL for our web service, which looks something like this:

Web Services3

As you can see, the WSDL shows where you can find the web service (URI) and other useful information including the methods that we have created in our web service.

Now that we’ve built the web service, we need to be able to use it. On the main web service page, you can see the method that we’ve created. If you click on the method, it will forward you to this page:

Web Services4

If our method actually took a parameter, we would be given a text box for us to enter its value into. However, because our method doesn’t take any parameters only the invoke button is provided, which will run the method and display the returned output as XML. This page is especially useful for testing purposes during the development and also to allow consumers to check if the web service is what they expected it to be.

When you click on the invoke button, you’ll get the following result:

Web Services5

If you examine the XML then you will see that “Hello World” was returned between a <string> tag. As you’ve probably guessed by now, the tags name specifies the data type of the returned value. Another thing to note is “http://tempuri.org/&#8221;. This the default namespace assigned to our web service, and unless we change the attribute using the web service attribute, it will display this URI as the namespace of our future web services as well.

Let’s now look at the code that made our web service:

<%@ WebService%>

Like any other ASP.NET page, web services also support directives. This just tells the compiler that the C# language is used and that the HelloWorld class contains methods and properties which should be exposed.

public class HelloWorld : WebService

This line is very important. It tells the .NET compiler that our HelloWorld class inherits from the WebService base class, which contains everything that’s required to make our class a web service.

[WebMethod]

This line is written just before the method, and it’s a C# attribute that indicates to IIS and the .NET compiler that the following method is to be exposed and web callable. The rest of the code is simple C#, so you shouldn’t have any trouble with it.

Other web service features

Web Service Attribute
Almost all the time when you’re developing for the “real” world, you’ll want to provide a description for your web services. You might also want to change the default namespace and give your web service a different name. All of these can be changed using WebService attributes. You can add an attribute and its appropriate properties just before the class declaration, like this:

[WebService(Name="Hello World", Description="Hello World Application developed by James Yang", Namespace="devArticles")]

public class HelloWorld : WebService

When you view the web service page now, it will look like this:

Web Services6
Notice how the name has changed from HelloWorld to Hello World? The description attribute that we specified is also shown. The instructions on how to change the namespace attribute are gone as well, and the namespace is also changed.

The biggest change however, is on the deletion of all of the instructions and template descriptions for the web service. IIS and the compiler assume that by specifying a namespace, our web service is no longer in the development stages and therefore removes unnecessary developer information for us.

Web Method Attribute
Attributes can also be added to each method individually. The available properties are:

  • Description
  • EnableSession
  • MessageName
  • TransactionOption
  • CacheDuration
  • BufferResponse

If you change the line

[WebMethod]
to
[WebMethod(Description ="Hello World Method")]

… then you will see the following change on our web service page:

Web Services7

Back to the web method attributes, MessageName is simply an alias for the method. This is particularly useful for parameter-overloaded methods, as requests through a browser cannot display two methods with the same name. The CacheDuration property sets the amount of time that the data will be cached for. This property is an integer and therefore it must contain a whole numeric value. The BufferResponse property is a Boolean property. If set to true, output is buffered and only transmitted once.

The TransactionOption property allows us to specify how transactions will be supported in this method. The available options are:

  • Disabled
  • Notsupported
  • Supported
  • Required
  • RequiredNew

The EnableSession property is a Boolean property and allows us to enable sessions (this requires the use of the proxy object, which will be discussed in another article). Without the proxy object, this web property cannot be implemented as the property is discarded as soon as the value is assigned to it. Without a proxy object, only one request is allowed per session, and assigning a value to the property itself is a request and therefore the session is ended just after.

Web Properties
A web property can be created like this:

string _property;

public string HelloWorldProperty
{
[WebMethod(EnableSession=true)]
get
{
return _property;
}
[WebMethod(EnableSession=true)]
set
{
_property = value;
}
}

Notice how the EnableSession property of our WebMethod attribute is set to true? If you open up your web service page again, then you will see that get and set have been implemented as two separate methods:

Web Services8

Protocols
ASP.NET supports three different protocol types:

  • HTTP-GET
  • HTTP-POST
  • SOAP

When we pass a parameter on the web services page that we looked at earlier, we’re actually passing the value using the HTTP-GET protocol. You can see this from the URL of the returned page, for example:  http://ws1/helloworld/helloworld.asmx/HelloWorldMethod?

“?” is used to pass values with the HTTP_GET protocol. We can pass parameters on the web service web page if we modify the showPost flag of defaultwsdlhelppagegenerator.aspx to true, which located in the c:\winnt\system32\Microsoft.NET\Framework\[Version] directory.

One important thing to notice here is that the two methods shown above return the result in XML format and not SOAP. Results returned as XML can be used in an application by treating the data as an XML document, but there is a better way to use web services.. it’s called SOAP.

SOAP is a 3 rd generation protocol that can be used to communicate with web services. It’s actually composed of lightweight XML that’s dedicated to the transportation of data structures information and the actual data itself. SOAP is sent using the HTTP-POST protocol:

POST /helloworld/helloworld.asmx HTTP/1.1
Host: ws1
Content-Type: text/xml; charset=utf-8
Content-Length: length goes here
SOAPAction: "devArticles/HelloWorldMethod"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<HelloWorldMethod xmlns="devArticles" />
</soap:Body>
</soap:Envelope>

.NET understands SOAP and behind the scenes it organizes the resultant data into the right type of application defined data for us. For example, if we use a proxy object to invoke our web service then SOAP is automatically used. If the web service returns a string, then .NET extracts this value and assigns it to a new string object. This string object can then be used in our applications, without even knowing that SOAP was handling the web service request for us!

SOAP and the web service session actually allow us to create an instance of our web service and it automatically calls the appropriate methods for us behind the scenes. This process is called XML Serialization.

For example, if we setup a proxy object for the HelloWorld web service that we created earlier, we could use the following code to invoke it:

HelloWorld hw = new HelloWorld
hw.HelloWorldProperty = "Property Value";
Console.WriteLine (hw.HelloWorldProperty);
hw.HelloWorldMethod();

For the example above to work we would need to use a proxy object, which I will cover in another article.

Real world application

Well, we’ve learnt all of the fundamentals for building web services. It’s time to put what we’ve learnt into practice by designing a real world example. The example application we’re about to create will not contain properties, because Microsoft recommends a web service be stateless whenever possible.

We are going to make a stripped-down version of Passport. Our version will contain seven methods:

  • bool Authenticate (string username, string password): This method will authenticate a user and return true if authenticated and false if not.
  • bool AddUser (string username, string password, string name, string email): This method will add a user to the database. If successful, the method will return true, if not the method will return false.
  • bool DeleteUser (string username): Will delete a user from the database. If successful the method will return true, if not the method will return false.
  • bool EditUser (string username, string name, string email): This method will edit the user information. If successful the method will return true, if not the method will return false.
  • bool ChangePassword (string username, string password): This method will change a user’s password. If successful the method will return true, if not the method will return false.
  • string ReturnName (string username): this method returns a users name.
  • string ReturnEmail (string username): this method returns a users email.

Our example makes use of an SQL server database. Use the following TSQL in query analyzer to create our database (In our example I will assume that SQL Server is installed on the same machine as where the web service will reside):

CREATE DATABASE minipassport
GO

CREATE TABLE Users (
UserName varchar (10) Primary Key NOT NULL ,
Name varchar (50) NOT NULL ,
EMail varchar (100) NOT NULL ,
Password varchar (10) NOT NULL
) ON PRIMARY
GO

The code for our web service looks like this:

<%@ WebService class = "miniPassport" Language="C#" Debug = "true"%>

using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Services;

[WebService(Name ="Mini Passport", Description="Web Service to Authenticate and Manage Users", Namespace = "devArticles")]
public class miniPassport
{
const string connStr = "server=127.0.0.1;uid=sa;pwd=;database=minipassport";

[WebMethod(Description = "Method to Authenticate Users")]
public bool Authenticate(string username, string password)
{
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "Select password from users where username = '" + username + "';";
dbConn.Open();
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
SqlDataReader dbReader = dbCommand.ExecuteReader();

bool returnBool;
if (dbReader.Read())
{
if (dbReader[0].ToString()==password)
{
returnBool = true;
}
else
{
returnBool = false;
}
}
else
{
returnBool=false;
}
dbReader.Close();
dbConn.Close();
return returnBool;
}

[WebMethod(Description = "Method to Add User")]
public bool AddUser(string username, string password, string name, string email)
{
bool returnBool = false;
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "INSERT INTO users(username,password,name,email) values('" + username + "', '" + password + "', '" + name + "', '" + email + "');";
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
try
{
dbConn.Open();
if (dbCommand.ExecuteNonQuery()!=0)
{
returnBool=true;
}
returnBool=true;
}
catch
{
returnBool=false;
}
dbConn.Close();
return returnBool;
}

[WebMethod(Description = "Method to Delete User")]
public bool DeleteUser(string username)
{
bool returnBool = false;
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "DELETE FROM users where username = '" + username +"';";
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
try
{
dbConn.Open();
if (dbCommand.ExecuteNonQuery()!=0)
{
returnBool=true;
}
}
catch
{
returnBool=false;
}
dbConn.Close();
return returnBool;
}

[WebMethod(Description = "Method to Edit User Information")]
public bool EditUser(string username, string name, string email)
{
bool returnBool = false;
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "UPDATE users SET username = '" + username +"',name = '"+name+"',email= '"+email+"';";
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
try
{
dbConn.Open();
if (dbCommand.ExecuteNonQuery()!=0)
{
returnBool=true;
}
}
catch
{
returnBool=false;
}
dbConn.Close();
return returnBool;
}

[WebMethod(Description = "Method to Change User Password")]
public bool ChangePassword(string username, string password)
{
bool returnBool = false;
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "UPDATE users SET password = '"+password+"';";
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
try
{
dbConn.Open();
if (dbCommand.ExecuteNonQuery()!=0)
{
returnBool=true;
}
}
catch
{
returnBool=false;
}
dbConn.Close();
return returnBool;
}

[WebMethod(Description = "Method to Obtain User Name")]
public string ReturnName(string username)
{
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "Select Name from users where username = '" + username + "';";
dbConn.Open();
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
SqlDataReader dbReader = dbCommand.ExecuteReader();
dbReader.Read();
string _name = dbReader[0].ToString();
dbReader.Close();
dbConn.Close();
return _name;
}

[WebMethod(Description = "Method to obtain User Email Address")]
public string ReturnEmail(string username)
{
SqlConnection dbConn = new SqlConnection(connStr);
string sqlStr = "Select email from users where username = '" + username + "';";
dbConn.Open();
SqlCommand dbCommand = new SqlCommand(sqlStr,dbConn);
SqlDataReader dbReader = dbCommand.ExecuteReader();
dbReader.Read();
string _name = dbReader[0].ToString();
dbReader.Close();
dbConn.Close();
return _name;
}
}

As you can see, there’s nothing difficult about our code. It’s composed from what we’ve covered throughout this article. If you add your own functionality and make it available on the web (or even register it on UDDI), then it’s a complete authentication web service. This will allow other sites to incorporate our demo login system and centralize user information.
Web Services9

Conclusion

In this article we’ve seen how to create a very simple web service, how to view the details of our web service using WSDL, and also how to put everything we’ve learnt into one complete authentication web service.

In another article I will cover how we can consume the web service we’ve just made, but until then you should experiment with what you’ve learnt in this article and also checkout some of the books and links shown below.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: