Tuesday, September 1, 2009

Web Services basics and Creating Web Services

XML Web Services Basics

Summary: An overview of the value of XML Web services for developers, with introductions to SOAP, WSDL, and UDDI.

Contents

What Is an XML Web Service?

XML Web services are the fundamental building blocks in the move to distributed computing on the Internet. Open standards and the focus on communication and collaboration among people and applications have created an environment where XML Web services are becoming the platform for application integration. Applications are constructed using multiple XML Web services from various sources that work together regardless of where they reside or how they were implemented.

There are probably as many definitions of XML Web Service as there are companies building them, but almost all definitions have these things in common:
  • XML Web Services expose useful functionality to Web users through a standard Web protocol. In most cases, the protocol used is SOAP.
  • XML Web services provide a way to describe their interfaces in enough detail to allow a user to build a client application to talk to them. This description is usually provided in an XML document called a Web Services Description Language (WSDL) document.
  • XML Web services are registered so that potential users can find them easily. This is done with Universal Discovery Description and Integration (UDDI).
I'll cover all three of these technologies in this article but first I want to explain why you should care about XML Web services.

One of the primary advantages of the XML Web services architecture is that it allows programs written in different languages on different platforms to communicate with each other in a standards-based way. Those of you who have been around the industry a while are now saying, "Wait a minute! Didn't I hear those same promises from CORBA and before that DCE? How is this any different?" The first difference is that SOAP is significantly less complex than earlier approaches, so the barrier to entry for a standards-compliant SOAP implementation is significantly lower. Paul Kulchenko maintains a list of SOAP implementations at: http://www.soapware.org/directory/4/implementations which at last count contained 79 entries. You'll find SOAP implementations from most of the big software companies, as you would expect, but you will also find many implementations that are built and maintained by a single developer. The other significant advantage that XML Web services have over previous efforts is that they work with standard Web protocols—XML, HTTP and TCP/IP. A significant number of companies already have a Web infrastructure, and people with knowledge and experience in maintaining it, so again, the cost of entry for XML Web services is significantly less than previous technologies.

We've defined an XML Web service as a software service exposed on the Web through SOAP, described with a WSDL file and registered in UDDI. The next logical question is. "What can I do with XML Web services?" The first XML Web services tended to be information sources that you could easily incorporate into applications—stock quotes, weather forecasts, sports scores etc. It's easy to imagine a whole class of applications that could be built to analyze and aggregate the information you care about and present it to you in a variety of ways; for example, you might have a Microsoft® Excel spreadsheet that summarizes your whole financial picture—stocks, 401K, bank accounts, loans, etc. If this information is available through XML Web services, Excel can update it continuously. Some of this information will be free and some might require a subscription to the service. Most of this information is available now on the Web, but XML Web services will make programmatic access to it easier and more reliable.
Exposing existing applications as XML Web services will allow users to build new, more powerful applications that use XML Web services as building blocks. For example, a user might develop a purchasing application to automatically obtain price information from a variety of vendors, allow the user to select a vendor, submit the order and then track the shipment until it is received. The vendor application, in addition to exposing its services on the Web, might in turn use XML Web services to check the customer's credit, charge the customer's account and set up the shipment with a shipping company.

In the future, some of the most interesting XML Web services will support applications that use the Web to do things that can't be done today. For example, one of the services that XML Web Services would make possible is a calendar service. If your dentist and mechanic exposed their calendars through this XML Web service, you could schedule appointments with them on line or they could schedule appointments for cleaning and routine maintenance directly in your calendar if you like. With a little imagination, you can envision hundreds of applications that can be built once you have the ability to program the Web.

For more information on XML Web services and the applications they will help you build, please see the MSDN XML Web Services Developer Center.

SOAP

Soap is the communications protocol for XML Web services. When SOAP is described as a communications protocol, most people think of DCOM or CORBA and start asking things like, "How does SOAP do object activation?" or "What naming service does SOAP use?" While a SOAP implementation will probably include these things, the SOAP standard doesn't specify them. SOAP is a specification that defines the XML format for messages—and that's about it for the required parts of the spec. If you have a well-formed XML fragment enclosed in a couple of SOAP elements, you have a SOAP message. Simple isn't it?
There are other parts of the SOAP specification that describe how to represent program data as XML and how to use SOAP to do Remote Procedure Calls. These optional parts of the specification are used to implement RPC-style applications where a SOAP message containing a callable function, and the parameters to pass to the function, is sent from the client, and the server returns a message with the results of the executed function. Most current implementations of SOAP support RPC applications because programmers who are used to doing COM or CORBA applications understand the RPC style. SOAP also supports document style applications where the SOAP message is just a wrapper around an XML document. Document-style SOAP applications are very flexible and many new XML Web services take advantage of this flexibility to build services that would be difficult to implement using RPC.
The last optional part of the SOAP specification defines what an HTTP message that contains a SOAP message looks like. This HTTP binding is important because HTTP is supported by almost all current OS's (and many not-so-current OS's). The HTTP binding is optional, but almost all SOAP implementations support it because it's the only standardized protocol for SOAP. For this reason, there's a common misconception that SOAP requires HTTP. Some implementations support MSMQ, MQ Series, SMTP, or TCP/IP transports, but almost all current XML Web services use HTTP because it is ubiquitous. Since HTTP is a core protocol of the Web, most organizations have a network infrastructure that supports HTTP and people who understand how to manage it already. The security, monitoring, and load-balancing infrastructure for HTTP are readily available today.

A major source of confusion when getting started with SOAP is the difference between the SOAP specification and the many implementations of the SOAP specification. Most people who use SOAP don't write SOAP messages directly but use a SOAP toolkit to create and parse the SOAP messages. These toolkits generally translate function calls from some kind of language to a SOAP message. For example, the Microsoft SOAP Toolkit 2.0 translates COM function calls to SOAP and the Apache Toolkit translates JAVA function calls to SOAP. The types of function calls and the datatypes of the parameters supported vary with each SOAP implementation so a function that works with one toolkit may not work with another. This isn't a limitation of SOAP but rather of the particular implementation you are using.

By far the most compelling feature of SOAP is that it has been implemented on many different hardware and software platforms. This means that SOAP can be used to link disparate systems within and without your organization. Many attempts have been made in the past to come up with a common communications protocol that could be used for systems integration, but none of them have had the widespread adoption that SOAP has. Why is this? Because SOAP is much smaller and simpler to implement than many of the previous protocols. DCE and CORBA for example took years to implement, so only a few implementations were ever released. SOAP, however, can use existing XML Parsers and HTTP libraries to do most of the hard work, so a SOAP implementation can be completed in a matter of months. This is why there are more than 70 SOAP implementations available. SOAP obviously doesn't do everything that DCE or CORBA do, but the lack of complexity in exchange for features is what makes SOAP so readily available.

The ubiquity of HTTP and the simplicity of SOAP make them an ideal basis for implementing XML Web services that can be called from almost any environment. For more information on SOAP, see the MSDN SOAP home page.

What About Security?

One of the first questions newcomers to SOAP ask is how does SOAP deal with security. Early in its development, SOAP was seen as an HTTP-based protocol so the assumption was made that HTTP security would be adequate for SOAP. After all, there are thousands of Web applications running today using HTTP security so surely this is adequate for SOAP. For this reason, the current SOAP standard assumes security is a transport issue and is silent on security issues.

When SOAP expanded to become a more general-purpose protocol running on top of a number of transports, security became a bigger issue. For example, HTTP provides several ways to authenticate which user is making a SOAP call, but how does that identity get propagated when the message is routed from HTTP to an SMTP transport? SOAP was designed as a building-block protocol, so fortunately, there are already specifications in the works to build on SOAP to provide additional security features for Web services. The WS-Security specification defines a complete encryption system.

WSDL

WSDL (often pronounced whiz-dull) stands for Web Services Description Language. For our purposes, we can say that a WSDL file is an XML document that describes a set of SOAP messages and how the messages are exchanged. In other words, WSDL is to SOAP what IDL is to CORBA or COM. Since WSDL is XML, it is readable and editable but in most cases, it is generated and consumed by software.
To see the value of WSDL, imagine you want to start calling a SOAP method provided by one of your business partners. You could ask him for some sample SOAP messages and write your application to produce and consume messages that look like the samples, but this can be error-prone. For example, you might see a customer ID of 2837 and assume it's an integer when in fact it's a string. WSDL specifies what a request message must contain and what the response message will look like in unambiguous notation.

The notation that a WSDL file uses to describe message formats is based on the XML Schema standard which means it is both programming-language neutral and standards-based which makes it suitable for describing XML Web services interfaces that are accessible from a wide variety of platforms and programming languages. In addition to describing message contents, WSDL defines where the service is available and what communications protocol is used to talk to the service. This means that the WSDL file defines everything required to write a program to work with an XML Web service. There are several tools available to read a WSDL file and generate the code required to communicate with an XML Web service. Some of the most capable of these tools are in Microsoft Visual Studio® .NET.

Many current SOAP toolkits include tools to generate WSDL files from existing program interfaces, but there are few tools for writing WSDL directly, and tool support for WSDL isn't as complete as it should be. It shouldn't be long before tools to author WSDL files, and then generate proxies and stubs much like COM IDL tools, will be part of most SOAP implementations. At that point, WSDL will become the preferred way to author SOAP interfaces for XML Web services.

An excellent description of WSDL is available, and you can find the WSDL specification at http://www.w3.org/TR/wsdl.

UDDI

Universal Discovery Description and Integration is the yellow pages of Web services. As with traditional yellow pages, you can search for a company that offers the services you need, read about the service offered and contact someone for more information. You can, of course, offer a Web service without registering it in UDDI, just as you can open a business in your basement and rely on word-of-mouth advertising but if you want to reach a significant market, you need UDDI so your customers can find you.
A UDDI directory entry is an XML file that describes a business and the services it offers. There are three parts to an entry in the UDDI directory. The "white pages" describe the company offering the service: name, address, contacts, etc. The "yellow pages" include industrial categories based on standard taxonomies such as the North American Industry Classification System and the Standard Industrial Classification. The "green pages" describe the interface to the service in enough detail for someone to write an application to use the Web service. The way services are defined is through a UDDI document called a Type Model or tModel. In many cases, the tModel contains a WSDL file that describes a SOAP interface to an XML Web service, but the tModel is flexible enough to describe almost any kind of service.
The UDDI directory also includes several ways to search for the services you need to build your applications. For example, you can search for providers of a service in a specified geographic location or for business of a specified type. The UDDI directory will then supply information, contacts, links, and technical data to allow you to evaluate which services meet your requirements.
UDDI allows you to find businesses you might want to obtain Web services from. What if you already know whom you want to do business with but you don't know what services are offered? The WS-Inspection specification allows you to browse through a collection of XML Web services offered on a specific server to find which ones might meet your needs.
More information about UDDI is available at http://www.uddi.org/about.html.
Step 1 - Create the Web Service
First we’ll create the Web service function or method that'll you'll call (or “expose”) over the Internet as you would any object-oriented class. The difference is that we’ll have to incorporate and import all the necessary Web Services namespaces, syntax and attributes, as well as our data namespaces, in this case. As this article uses C#, any important differences regarding VB will be shown as well.
So go ahead and copy the code below to a file called suppliers.asmx. Save it to your Inetpub/wwwroot folder, and then run it in your browser using http://localhost/suppliers.asmx. What you'll see is a list of the Web Service Descriptions, including the Web service name and the exposed method.
By clicking the exposed method link, you'll be presented with the three main protocols that are available for your use. Just so you know, the file with the .asmx extension is the actual Web Service file that enables the ASP.NET runtime to return all pertinent exposed Web service methods and information.
<%@ WebService Language="C#" Class="GetInfo" %>

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

[WebService(Description="My Suppliers List Web Service")]

public class GetInfo : WebService  
{

 [WebMethod(BufferResponse=true)]

 public DataSet ShowSuppliers (string str)  
 {

   SqlConnection dbConnection = new SqlConnection("server=(local);
                                uid=sa;pwd=;database=Northwind;");

   SqlDataAdapter objCommand = new SqlDataAdapter("select  
              ContactName, CompanyName, City, Phone from Suppliers  
              where Country = '" + str + "' order by ContactName  
              asc", dbConnection);

   DataSet DS = new DataSet();

   objCommand.Fill(DS);

   return DS;

   dbConnection.Close();
   dbConnection = null;

 }

}
The <%@ WebService Language="C#" Class="GetInfo" %> directive sets up the file as a Web Service, gives it a name and specifies the language it uses.
Aside from your typical data namespace import, you also add the Web Services namespace:
C#
using System.Web.Services
In VB this would be:
Imports System.Web.Services

Here I've added the [WebService(Description="My Suppliers List Web Service")], which gives a custom description. Next we create our class, which, in order that it be exposed, and able to inherit the Webservice base class, must be a public class.
public class GetInfo : WebService  
{
Now we mark the method that’s to be exposed via the WebMethod attribute. Every class that’s enclosed within a WebMethod will be exposed as a service. Also, I boost performance by setting the BufferResponse to true.
[WebMethod (BufferResponse=true)]
If you prefer to have the description right below the exposed WebMethod link, you can achieve it like this in C#:
[WebMethod (Description="My Suppliers List Web  
Service",BufferResponse=true)]
The VB version would incorporate the description and BufferResponse in one statement, namely WebMethod, that used angle brackets. This is placed after the class creation and Web service inheriting line, and on the same line with, but before the function, like so:
<WebMethod(Description:="My Suppliers List Web  
Service",BufferResponse:=True)>
Public Function  
ShowSuppliers (ByVal str As String) As DataSet
Next, we set up our method or VB function, which will accept a string parameter from our drop down list and pass this to our SQL query (you'll see all this in detail in Step 4). If you're really savvy you can pass this and other parameters with the help of C# structs (scaled down classes) to enumerate your data value types, and provide you with better memory allocation. But for now, we'll stick to the basics:
public DataSet ShowSuppliers (string str)
Here, we set up our dataset method to return us exactly that. Lastly, we perform typical data connection and access and return our results, and we're done! So far so good? After viewing this in your browser, the above code should to start to make sense. Let's go to Step 2.
Step 2 - Consume the Web Service Source File
Next, append ?WSDL to the Web services URI (Uniform Resource Identifier) like so:
http://localhost/suppliers.asmx?WSDL
“What's this?” you ask. This is the WSDL document that the client will use to access this service.
Even so, you don't have to know much about this unreadable code to produce results, which is where the WSDL.exe command-line tool comes into play. Due to the open protocol nature of Web services, this tool enables you to consume non-.NET Web Services as well.
You can bypass WSDL and test the XML results instantly through HTTP GET protocol, by typing the following into your browser:
http://localhost/suppliers.asmx/ShowSuppliers?str=USA
This passes USA as a parameter to the ShowSuppliers class method. Note that if you're using .NET SDK Beta 1.1 (v.1.1.4322), it seems to prefer HTTP POST protocol, so invoke the Web Service through its exposed method link. The XML results? A little crazy, huh?
Nevertheless, scroll down a little and you'll see the query results of our class call. Later in Step 4, all this gobbledygook will make much more readable sense.
So, to create our proxy class sourcefile, make a batch file named makeWS.bat and type in:
[C#]
wsdl.exe /l:CS /n:WService /out:bin/GetSuppliers.cs  
 http://localhost/suppliers.asmx?WSDL
[VB]
wsdl.exe /l:VB /n:WService /out:bin/GetSuppliers.vb  
 http://localhost/suppliers.asmx?WSDL
pause
This tells our WSDL tool that /l is the language you’re using.
/n: creates the Wservice namespace so you can reference it from your .aspx page, and finally send the C#/VB source file to the bin folder from which we'll create the dll assembly that we’ll use in Step 3. Also add pause, so after this is all said and done, you'll be prompted to press any key to continue, and more importantly, you’ll know for sure that it all went according to plan.
Now locate your new batch file, and double-click on it to run it. Once you’ve done this, you will have created, rather consumed, the proxy class or source file GetSuppliers.cs right from the .asmx file. Have a look in your bin folder.
Note that you could run these commands via the command-line prompt, but for the sake of convenience, I prefer the good old' batch file. You may be wondering where the phrase “consuming” came from? In this regard, it simply refers to the presentation of the Web Service to the "consumer”.
Build our Object
OK, now let's invoke the .NET C# compiler (csc.exe) or VB compiler (vbc.exe) to convert your source file into an assembly or DLL. Create a new .bat file named makelib.bat and type in:
[C#]
csc /t:library /out:bin\GetSuppliers.dll bin\GetSuppliers.cs    
 /reference:System.dll,System.Data.dll,System.Web.dll,
 System.Web.Services.dll,System.XML.dll /optimize
[VB]
vbc /t:library /out:bin\GetSuppliers.dll bin\GetSuppliers.vb    
 /reference:System.dll,System.Data.dll,System.Web.dll,
 System.Web.Services.dll,System.XML.dll /optimize  
pause
All this does is compile the source file from the bin folder to a DLL of set name, to the bin folder.
The /t:library instructs the compiler to create a dll (dynamic link library), rather than an exe (executable) file, with /reference: importing the necessary dll's libraries that will be used in our Web service. Finally, we /optimize our dll to produce smaller, faster, and more efficient output.
Step 4 - Put it All Together
Now copy and paste the code below to an .aspx .NET page and name it. This code is for the page that will access the assembly/DLL in your bin folder, and with all the Web server controls, pass the appropriate parameters to the Web Service. Go ahead and run it (http://localhost/Websrvce.aspx).
<%@ Page Language="C#" Explicit="true" Strict="true" Buffer="true"%>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="WService" %>

<html>
<script language="C#" runat="server">

void Page_Load(Object sender, EventArgs e)  
{  
 Response.Flush();
}

void SubmitBtn_Click (object src, EventArgs e)
{

 int RcdCount;
 string Catg = DropDown1.SelectedItem.Text;


 //Instantiate DLL
 GetInfo supInfo = new GetInfo();


 //Pass parameter into DLL function
 DataSet MyData = supInfo.ShowSuppliers(Catg);


 MyDataGrid.DataSource = MyData.Tables[0].DefaultView;
 MyDataGrid.DataBind();
 
 RcdCount = MyData.Tables[0].Rows.Count;
 if (RcdCount <= 0)  
 {

 Message.InnerHtml = "<b>No results were found for <FONT  
                    Color=Red><i>"+ Catg +"</i></font>";
 MyDataGrid.Visible = false; //Hide Results until needed

 }
 else
 {

   Message.InnerHtml = "<b><FONT Color=Red><i>" + Catg +
    "</i></font> has " + RcdCount + " local suppliers</b>";
 MyDataGrid.Visible = true;
 }
}

</script>
<body style="font: 10pt verdana">

<h4>Accessing Data with Web Services</h4>

<form runat="server">

<asp:DropDownList id=DropDown1 runat="server">
<asp:ListItem>Australia</asp:ListItem>
<asp:ListItem>Brazil</asp:ListItem>
<asp:ListItem>Canada</asp:ListItem>
<asp:ListItem>Denmark</asp:ListItem>
<asp:ListItem>Finland</asp:ListItem>
<asp:ListItem>France</asp:ListItem>
<asp:ListItem>Germany</asp:ListItem>
<asp:ListItem>Italy</asp:ListItem>
<asp:ListItem>Japan</asp:ListItem>
<asp:ListItem>Netherlands</asp:ListItem>
<asp:ListItem>Norway</asp:ListItem>
<asp:ListItem>Singapore</asp:ListItem>
<asp:ListItem>Spain</asp:ListItem>
<asp:ListItem>Sweden</asp:ListItem>
<asp:ListItem>UK</asp:ListItem>
<asp:ListItem>USA</asp:ListItem>
</asp:DropDownList>
<asp:button text="Submit" OnClick="SubmitBtn_Click" runat=server/>
<p>
<span id="Message" runat="server"/>

<p>


<ASP:DataGrid id="MyDataGrid" runat="server"
AutoGenerateColumns="True"
Width="100%"
BackColor="White"
Border="1"
BorderWidth="1"  
CellPadding="1"
CellSpacing="1"
Font-Size="10pt"
HeaderStyle-BackColor="White"
HeaderStyle-ForeColor="Blue"
AlternatingItemStyle-BackColor="White"
AlternatingItemStyle-ForeColor="Black"
ShowFooter="false"
/>

</form>

</body>
</html>
How It Works
Pretty cool, huh? Now, aside from the common data accessing and Web server control usage, I'll outline some specifics. By virtue of creating our proxy class with a namespace in Step 2, we need to import it to the dll we created in Step 3, like this:
<%@ Import Namespace="WService" %>
We then instantiate it or reference our object:
[C#]

GetInfo supInfo = new GetInfo();
[VB]
Dim supInfo As New WService.GetInfo()
This is our Web Service class. We then retrieve our dropdown list parameter, and pass it to our ShowSuppliers constructor method like so:
[C#]
string Catg = DropDown1.SelectedItem.Text;

DataSet MyData = supInfo.ShowSuppliers(Catg);
[VB]
Dim Catg As String = DropDown1.SelectedItem.Text

Dim MyData As DataSet = supInfo.ShowSuppliers (Catg)
And the rest? Just common .NET stuff, which I assume you have some grip on. Nevertheless, it shouldn't be too hard to follow or figure out. The .NET documentation and Quickstart Tutorials will help with plenty more information.
Well, guess what? We're done!
Show it Off
Congratulations are in order, for you have now built your first fully-fledged .NET XML Data Web Service, without any IDE program such a VS .NET I might add, and using a tool as simple as Notepad. Now can anyone really say this was a big ordeal? I didn't think so.
Additionally, if you're wondering how anyone else will "discover" your Web service, then look no further: with the XML Web service "discovery", you can advertise your Web service and expose its location and other information, alongside a .discomap file providing links to your files.
XML Web Service discovery, called DISCO for short, is Microsoft's Web Services Discovery tool. It "discovers" the URL for a Web Service and saves that information in a file on your local server. Here's how:
disco http://localhost/suppliers.asmx?DISCO
This creates a static discovery file containing a WSDL file with all the important information pertaining to your Web Service. Opposite this static discovery file is a dynamic discovery .vsdisco file, which notes all the available Web Services located within that URL.
Remember from Step 2 the WSDL command for creating the source file with "?WSDL"? Now, for an already "discovered" file, you can use:
wsdl.exe /l:CS /n:WService /out:bin/GetSuppliers.cs  
 http://localhost/suppliers.wsdl
to create your source file and, in turn, your DLL for Web Service access.
When you examine the created .disco file you'll notice it includes the following information:
<contractRef ref="http://localhost/suppliers.asmx?wsdl"  
 docRef="http://localhost/suppliers.asmx"  
 xmlns="http://schemas.xmlsoap.org/disco/scl/" />
This contains the link to your Web Service so others can discover it, alongside XSD schemas, and service descriptions. Using this information others can parse the WSDL document, build a proxy source file, and implement this Web Service locally!

If you do have something you'd like to share, run over to the Microsoft UDDI (Universal Description, Discovery and Integration) Business Registry (UBR) node at
http://uddi.microsoft.com, which is currently supported by Microsoft, IBM and Ariba. Here you can find other available Web Services and their details, register your Web Service, and discover more about this whole business.
A little "Asynchronousity"
Before, I conclude this article I need to mention an additional method of calling Web Services from your application. Web Services by default form are called “synchronously”. As a result, both the application and its inherent Web Service will have to finish simultaneously. As such, a quicker method within the application will have to wait for any slower one to finish, before the application can fully display its results, potentially creating an unnecessary delay for the client. Likewise, since Web Service calls make use of Port 80 for communications, they can at times cause this type of delay. How would you be able to remedy such a situation? With a little asynchronousity, of course!
There are four common ways to make asynchronous method calls. Here we will demonstrate waiting for our asynchronous call utilizing the WaitHandle method, which determines when the service call is complete. The other three possible methods for asynchronous calls include:
1.   The IsCompleted property of the IasyncResult returned by BeginInvoke, within our BeginSuppliers Method
2.   Executing a callback method when the asynchronous call finishes
3.   Finally, parallel any processing or code until the call completes prior to calling EndInvoke
Given that asynchronous calls can perform a given task without affecting other functions around them, let's implement our chosen technique. Going back to Step 2, you'll remember how we created our proxy class file for our .asmx Web Service file.
If you took the time to inspect it, you will have noticed that, aside from our main ShowSuppliers Dataset function, two additional functions were listed: BeginShowSuppliers and EndShowSuppliers. These are the asynchronous functions that will enable us to produce asynchronous Web Service calls implementing the WaitHandle Class’s WaitOne() Method, and here's how.
We do all this from the .aspx page we created in Step 4. Here's the additional code:
//Instantiate DLL
GetInfo supInfo = new GetInfo();

// Begin the Asynchronous call to ShowSuppliers
IAsyncResult AsyncWS = supInfo.BeginShowSuppliers(Catg, null, null);

//We wait for the callback
AsyncWS.AsyncWaitHandle.WaitOne();

//We return the data bypassing the initial ShowSuppliers Method
DataSet MyData = supInfo.EndShowSuppliers(AsyncWS);
Notice that just a few more lines of code were added. The only thing that changed was that we added our asynchronous methods right after we instantiated our dll. After this, we create an instance of the IasyncResult object that will let us know when the Web Service process has finished.
IAsyncResult AsyncWS = supInfo.BeginShowSuppliers(Catg, null, null);
Here, we called the asynchronous BeginShowSuppliers method that accepts our initial dropdown list parameter and two other mandatory arguments that, in this example, were not included, and were substituted with null. The second argument would typically call the AsyncCallBack object responsible for calling another method once the BeginShowSuppliers completes, contrary to our example. The third argument would contain information about the asynchronous operation.
We then next implement the AsyncWaitHandle that allows us to incorporate and handle different kinds of synchronization techniques. There are a few AsyncWaitHandles available to us. With the WaitOne method included below, we wait for the WaitHandle to receive a callback signal. Further available methods include: WaitAll(), which waits for all elements to receive a callback signal, and WaitAny(), which waits for any one of the elements to receive a callback signal. Both utilize specified arrays as one of the overloaded element arguments, alongside an Integer for specific time interval waiting, and/or Timespan as well. In any event, all WaitHandles have available to them multiple overload forms that can be further viewed in the .NET SDK documentation.
//We wait for the default callback
AsyncWS.AsyncWaitHandle.WaitOne();
A quick digression regarding the line above: although our WaitOne method as shown in default form will work fine, it can be overloaded. To illustrate, our WaitOne Handler, once overridden in a derived class, will block the current thread until the current WaitHandle receives a signal. The two arguments it allows, paralleling what the other two Wait methods also accept, are:
1.    waiting for a set number of milliseconds to pass, and
2.    a Boolean value, true or false, specifying whether to exit the synchronization domain before the wait.

Once the wait is over, we return our results via the EndShowSuppliers method that got the OK from the WaitHandle.
The AsyncWaitHandle method being a resource releaser, OK'd our supInfo.EndShowSuppliers method below, and in turn obtained our data, without letting the rest of our application grow impatient.
//We return the data
DataSet MyData = supInfo.EndShowSuppliers(AsyncWS);
Therefore, in coping with the possible speed limitations resulting from HTTP network traffic, we can implement our Web Service without any concern that the rest of our application will wait impatiently until it’s all completed. With some asynchronous"ity,” our application will run its entire course, in conjunction with our possibly leisurely Web Service, simply jumping in when it's finished.
In summing up, our BeginShowSuppliers method, once initialized, returns instantly (though not in this case, as we used the WaitHandler) to notify your applicable callback function that the process is done, and it's OK to call the EndShowSuppliers method and return the results.
And there you have it: a quick look at Asynchronous Web Services. As you may have wondered, yes, this can get far more complex than what we’ve discussed. Nevertheless, with the amount you have learned now, it should be a little less intimidating.
Conclusion
Realizing how fast you can create a nice, functional .NET XML Data Web Service -- and an Asychronous one to boot -– should have put a smile on your face.
Additionally, be sure to explore all the .NET documentation for greater detail on what was presented here for additional tweaking, implementing error handling, security, caching, and other aspects you should keep in mind when creating and consuming Web Services. There's plenty of stuff in the .NET documentation and online that goes into more detail about all this.

It's really quite easy to create and consume your own Web services, and to discover other available services over the Internet, and to consume and utilize them as if those applications reside on your local server! With each passing moment, .NET reveals itself to be a more truly amazing and extremely powerful platform. Until next time, happy .NETing!

The WebMethod attribute

To expose a method as a part of a web service, you must decorate it with the WebMethod attribute, which tells the compiler to treat it as such. Any method marked with the WebMethod attribute must be defined as public. Class methods exposed as web services follow the same object-oriented rules as any other class, and therefore methods marked private, protected, or internal are not accessible and will return an error if you attempt to expose them using the WebMethod attribute.
The WebMethod attribute has six associated properties to document and change the behavior of your web method. They are:
  • Description
  • MessageName
  • EnableSession
  • CacheDuration
  • TransactionOption
  • BufferResponse
The first two properties are used to document a web method, while the others affect its behavior. In the following sections, we'll introduce each briefly. Each property is described in greater detail in a later chapter.

The Description and MessageName Properties

To avoid forcing your consumers to guess at what a web method does based on its name, include a description for each of your web methods, just as you should for the service itself. This is particularly necessary when a web service contains overloaded web methods. For example, the following code fragment declares two methods named Add(), one that accepts parameters of type Integer and one that accepts parameters of type Floating:
...
[WebMethod]
public int Add(int a, int b)
{
  return a + b;
}
[WebMethod]
public float Add(float a, float b)
{
return a + b;
}
...
In fact, if you try to access a web service containing two methods with the same name but different method signatures (an overloaded method) through the IE test page, you get a runtime exception when you view the page. The error for the previous example is as follows: "Both Single Add(Single, Single) and Int32 Add(Int32, Int32) use the message name "Add". Use the MessageName property of the WebMethod custom attribute to specify unique message names for the methods."

The procedure for commenting web methods is very similar to that for commenting a service. Start each method declaration with a WebMethod attribute. Use its Description property to add a description of your web method and its MessageName property to change its name:
[WebMethod(MessageName="<name>", Description="<desc>")]
In our DNSLookupService example, the descriptive code would look like this:
[WebService(Namespace="http://www.bostontechnical.com/webservices/",
   Description="<b>A web service which performs Domain Name Lookups.</b>")]
public class DNSLookupService : System.Web.Services.WebService
{
  [WebMethod(MessageName="LookupDNS", 
             Description="Get an IP address for a given hostname string")]
  public string GetIPForHostname(string strHostname)
  {
    IPHostEntry hostInfo = Dns.GetHostByName(strHostname);
    return hostInfo.AddressList[0].ToString();
  }
}
 
 
Below Figure shows  WSDL with namespace and documented web methods
http://oreilly.com/catalog/prognetws/chapter/pws_0211.gif
Notice that the WSDL document includes a <portType> tag for each of the supported access protocols (POST/HTTP GET and SOAP). Each of the <portType> tags contains an additional XML documentation element, which itself contains the textual explanation for the web method. In addition, the name attribute of each of the input and output elements now contains the value of the names that we've assigned to the method: getIPForHostname. Because this documentation is now part of the WSDL page, it is programmatically accessible to a calling application. You will see why this documentation is particularly useful to the consumer in the next chapter when we talk about .NET proxy classes.

The EnableSession Property

ASP.NET web services (classes that derive from System.Web.Services.WebService) exist within the context of an ASP.NET application and therefore have access to the Application and Session objects of the ASP.NET application within which they reside. While an ASP.NET application has only one Application object, it can have multiple session objects, which can be used to store data on a per-client basis. This state management mechanism is disabled by default and can be enabled by setting the EnableSession property to true. Enabling session management can decrease performance, so leave it disabled if you don't plan on using it.
If session state is enabled, the server manages client state using a unique HttpSessionState object for each client. In order to differentiate between each client's Session, a unique identifier is assigned to each Session object when the client first interacts with the server. On subsequent interactions, the client must present its unique identifier in order for the server to retrieve any client-specific data that has been stored in session state. The unique identifier can be stored in a cookie on the client or can be included as part of the URL. In a typical ASP.NET application, which is accessed via a web browser, this state management system occurs behind the scenes. If cookies are enabled on the web browser, it will automatically present the appropriate cookie to the server along with each request. Because a web service is not accessed in the same manner, if you choose to enable session management, you must programmatically set the cookie each time you call your web service. (You'll learn more about this and other state management approaches in Chapter 5.)

The CacheDuration Property

Implementing proper caching in your web services can increase scalability and performance. One of the easiest ways to implement caching systems is with the CacheDuration property of the WebMethod attribute. .NET implements this type of caching, called output caching, by system by storing matching pairs of requests and responses in a hashtable in memory for the specified amount of time. During this time, any incoming request that matches a request already in cache forces the server to output the cached response. Use the CacheDuration property to set the number of seconds (integer) a request/response pair will be held in cache. The default is 0, meaning that the response is not cached.

This caching mechanism is often ideal for web methods that involve processor-intensive or other expensive queries where the results change infrequently. An example of this type of functionality is a web method that queries a database for news headlines that change daily. For a system like this, we might set the CacheDuration property for our web method to five minutes or more to reduce the number of round-trips to the database. Because the caching system is based on request/response pairs, it uses few server resources in situations like this in which the web method's range of expected input parameters is small. If, however, you have a wide range of expected input parameters (and therefore request strings), the cache hashtable can quickly grow to consume a great deal of memory or can cause valuable items to be deleted from the cache. This can be further aggravated if the output of your method (which is stored in cache) is sizable. An example of a web method that would not lend itself well to caching with 

CacheDuration is the GetIPForHostname method of our DNSLookupService. It meets the first part of the requirement, in that it involves a fairly expensive network operation to retrieve a reasonably static small result; however, this type of service receives a wide range of inputs. Using a high cache duration setting for this method would cause the hashtable to grow in memory as unique lookup requests were made to the service.

The TransactionOption Property

If you've ever programmed MTS or COM+ components, you're probably comfortable with the idea of developing transaction-based services. A transaction can be thought of as any set of procedures (e.g., events, function calls) that collectively result in a change of state such as a success or failure. One example is a credit card processing system that authenticates a credit card number, charges the card, and triggers a fulfillment process. If any of these three steps fails (e.g., the card is declined), the transaction as a whole will fail, and each of the individual processes must be returned to its original state (e.g., cancel a fulfillment process if it has been started). All three steps are part of a transaction.


Microsoft includes support in the .NET platform for MTS or COM+ style transactions through the System.EnterpriseServices namespace. We're not going to get into the details of developing transacted services in this book; however, it is important to understand the difference between .NET-style transactions and what we'll call distributed web service transactions.
.NET transaction support is set through the TransactionOption property of the WebMethod attribute. The five possible settings for this property are:
  • Disabled
  • NotSupported
  • Supported
  • Required
  • RequiresNew
By default, transactions are disabled. If you decide to use .NET transactions, your web method will be able to participate only as the root object in a transaction. This means that your web method may call other transaction-enabled objects, but may not itself be called as part of a transaction started by another object. This limitation is due to the stateless nature of the HTTP protocol. As a result, the Required and RequiresNew values for TransactionOption are equivalent (and both declare a RequiresNew method that will start a new transaction). Disabled, NotSupported, and Supported all disable transactions for the web method, despite what their names imply.

The BufferedResponse Property

The default behavior for a web method is to store a response in a memory buffer until either the buffer is full or the response is complete. This storage process is called serialization. In most scenarios, this behavior is preferred, because buffering results in improved performance by reducing the number of transmissions to the client. However, if your web method returns a large amount of data or takes a long time to run, you might want to disable buffering by setting the BufferResponse property to false. This setting causes .NET to send the response back to the client as it is serialized, but can reduce performance for smaller result sets.
For all practical purposes, there's no reason that you should ever need to change this property's value. For an .aspx page, the output of which is meant to be displayed to a user, it can make sense to disable buffering for long-running pages such as a search page, so that the user can start viewing the data before it's completely returned. Because web services are designed for host-to-host communication, this type of scenario rarely occurs. and the default value for this setting does not need to be changed.

Deploying a Web Service

The process you use to deploy your web services will vary depending on whether you use inline coding or code behind to write them and whether you use an IDE like Visual Studio .NET. As you've seen, deployment for web services written using the inline approach is a snap. Once you have written and tested a web service on your development machine, all you have to do is to save the raw source to a server running the .NET SDK and IIS 5.0 or later. .NET compiles the service and caches a copy of the compiled class for you. If the source page changes, .NET will automatically recompile and cache the new page. This process is handled by .NET using some of the classes found in the System.Web.Caching namespace. 

If you're using the code-behind approach, the deployment process is more involved. Let's take a closer look at what you need to do in order to be able to deploy your web services using the code-behind approach, first with and then without the help of Visual Studio .NET.

Deploying a Web Service with VS.NET

The deployment process in Visual Studio .NET is as simple as choosing the Build Solution option from the Build menu item (or pressing Ctrl-Shift-B). But, in order to take advantage of this two-click deployment, you first need to properly configure Visual Studio .NET to be able to deploy to your instance of IIS. Earlier we mentioned that there are two ways for Visual Studio .NET to communicate with IIS: Microsoft FrontPage Server Extensions, and UNC file shares. In the earlier example, we used FrontPage Extensions because they are easier to configure (or at least easier to explain). Let's take a closer look at the differences between Frontpage Extensions and UNC.

FrontPage Extensions and UNC

Visual Studio .NET offers you two methods of connecting to the web server. You can use either FrontPage Extensions or UNC. FrontPage Extensions is a technology that allows Visual Studio .NET to transfer files to and from the web server over HTTP. In order to use this method of file transfer, you must install and configure the FrontPage Server Extensions to the web server as we discussed in the earlier
The other way Visual Studio .NET can communicate with the web server is via UNC, or Universal Naming Convention file or folder shares. A file or folder share is just a file or folder on the network that is configured to be shared by one or more users. UNC provides a naming convention for identifying network resources, in this case the web server. UNC names consist of three parts: a server name, a share name, and a file path, separated by backslashes (\) as follows:

\\servername\share\file_path
This format is called a UNC path. The server name portion of the UNC path is either a network address (IP address) or a hostname that can be mapped to a network address using a naming service like DNS. The share can be either a custom share configured by a system administrator or one of several built-in shares. An example of a built-in share is the admin$ share, which typically maps to c:\winnt\, or the c$ share, which maps to c:\. The file path allows you to specify the subdirectory below the specific share. For example, the following path:

\\myserver\c$\inetpub
points to the c:\inetpub folder on a server called myserver.
If you choose UNC access for your project, it's important to make sure that the UNC path corresponds to the URL specified in the creation dialog box; otherwise, VS.NET will return an error.

Locally and remotely hosted projects

There are no configuration differences between web service projects hosted locally (i.e., on your workstation) or remotely (i.e., on a remote web server). Regardless of whether your projects are hosted locally or remotely, you should still use either FrontPage or UNC access. Of course, if you choose to use UNC access for your projects, you must make sure to configure a share to the appropriate IIS folder so that VS.NET can transfer files. For local workstation development, VS.NET takes care of some of the work for you automatically.

VS.NET UNC support

When VS.NET is installed, it creates an empty "VS Developers" user group and a share on the \inetpub\wwwroot folder called wwwroot$ (which we'll discuss shortly). VS.NET then grants the newly created group read and write permissions on that share. This VS Developers group is created without any members, so unless your user account has administrative privileges on your workstation, you will need to add yourself to this group.

By default, Visual Studio .NET is configured to use UNC access for projects. When you specify the URL for a new project, such as http://ws.uinspire.com/HelloWorldService in the earlier example, Visual Studio .NET attempts to create the project using the UNC path:

\\ws.uinspire.com\wwwroot$\HelloWorldService
If Visual Studio .NET is unable to connect using this UNC path, you get an error message asking you either to retry using a different UNC path or to try to open the project using FrontPage Server Extensions. If you are hosting your project on your local workstation, the fact that Visual Studio .NET automatically creates the wwwroot$ share upon install can make your life easier (assuming you've added yourself to the VS Developers group). However, if you want to host your project on a remote server, you will need to make sure this wwwroot$ share is properly configured or manually specify another path. You also have the option of installing the Visual Studio .NET Server Components to the remote server on which you wish to do your development.

FrontPage and UNC performance

UNC is the preferred access method primarily because it performs much better than FrontPage Extension's access. This shouldn't come as much of a surprise considering that FrontPage file transfers are done over the slower HTTP. As a result, if you have a choice between using UNC and FrontPage Extensions, it's preferable to use UNC. Another reason to choose UNC is that FrontPage Extensions have traditionally had security problems. If, however, you need to change Visual Studio .NET's default access method, you can do so. This option can be changed via Tools http://oreilly.com/catalog/prognetws/chapter/rarr.gifOptions http://oreilly.com/catalog/prognetws/chapter/rarr.gifProjects http://oreilly.com/catalog/prognetws/chapter/rarr.gifWeb Settings, then setting the Preferred Access Method to FrontPage.

TIP: While you have the option to use either a UNC file share or FrontPage Extensions for your project, FrontPage Extension's access is slower.

Even if you intend to use Visual Studio .NET (which does much of the deployment automatically) for web service development, it's still important to understand how this process works so that you can troubleshoot your web services. Let's start by taking a closer look at how IIS must be configured to support ASP.NET web services.

Deploying a Web Service Directly to IIS

An ASP.NET web service consists of a collection of resources (.asmx web services, global.asax, configuration information, compiled components stored in the \bin directory, and so on) that run as a so-called IIS virtual application. IIS allows you to divide an instance of a web server into multiple separate virtual applications. Each of these virtual applications has its own set of application mappings, debugging options, and configuration options like script timeout duration and session state timeout. This separation, particularly separation of the application mappings, makes virtual directories good containers for ASP.NET applications. When you create a web service project using VS.NET, this virtual application configuration can be done automatically, but if you're developing without VS.NET, you'll need tools like the Microsoft Management Console (MMC) snap-in or the command-line scripts included with IIS, as explained next.

The most common way to create a new virtual application is to create a new instance of a web site in IIS. By default, the root folder of the new web site will be configured as a virtual application, known as the application root, which can contain other virtual applications.
Another way to create an application root is to mark a folder (virtual or physical) within an IIS web site as an application. This will define the folder as the root of an application.
The most common way to create a virtual application in IIS is through the Internet Services Manager, a snap-in for the Microsoft Management Console. To create a virtual application from an existing directory, follow these steps:
  1. Locate the folder you wish to convert in the Internet Services Manager snap-in. We used a folder called DNSService in below figure
Below Figure Shows The IIS Management Console
http://oreilly.com/catalog/prognetws/chapter/pws_0212.gif 
  1. Right-click the folder and select Properties.
  2. Mark the folder as an application by clicking on the Create button of the Directory tab of the folder's Property dialog. (See below figure).
Below Figure Shows Configuring the virtual directory
http://oreilly.com/catalog/prognetws/chapter/pws_0213.gif 
  1. Click OK to accept the change.
The folder is now configured as an IIS virtual application. You can now manually add a \bin directory.

The \bin directory is the first place that .NET looks for compiled assemblies, and so every ASP.NET web service should have a \bin directory located directly beneath the application root folder. If one is not automatically created for you by a tool like VS.NET, you can create one manually by using Windows Explorer to navigate to the application's root folder (called DNSService in the previous example) and creating a new folder called root.

Remember that the location of the \bin directory is always relative to the virtual application root. Because IIS allows you to have nested virtual applications, sometime figuring out which \bin directory goes with which application can be confusing. For example, consider below figure and let's assume a code-behind .asmx page resides in the folder named dir2. If the virtual directory named store is configured as a virtual application, then .NET will attempt to find the associated code-behind assembly in the \bin directory associated with the store virtual application (www.yyz.com\store\bin). If, however, the store virtual directory is not configured as a virtual application, .NET will look in the \bin directory located at www.yyz.com\bin.

.NET always looks for the \bin directory located directly underneath the application root. If you start seeing .NET error messages like "Could not create type `xxx'", it's probably due to a problem with the way you've configured your virtual application.

Below Figure shows  \bin directory locations
http://oreilly.com/catalog/prognetws/chapter/pws_0214.gif 

Example deployment

To take advantage of the compiled code model for our DNSLookupService example, create an .asmx page with the following single line:

<%@ WebService Language="C#" Class="DNSLookupService"%>
and save it as DNSLookupService.asmx. When this page is accessed, .NET looks through the assemblies in the \bin subdirectory of the virtual application for one containing the class DNSLookupService. If an application makes use of multiple assemblies in the \bin directory, you need to specify the assembly that contains the DNSLookupService by adding its name to the Class attribute value as follows:

<%@ WebService Language="C#" Class="DNSLookupService, MyAssembly"%>
This line tells .NET to search the assembly MyAssembly for the class DNSLookupService. This .asmx page will return an error, however, until you compile the assembly and copy it to the \bin directory. Do this by putting the C# code into another file; for this example, call it DNSLooupService.asmx.cs, using the same naming convention that Visual Studio uses by default. We can then compile this source code from the command line using a command like the following:

csc.exe /out:bin\DNSLookupService.dll /target:library /r:System.Web.Services.dll DNSLookupService.asmx.cs

Using the .NET Compilers

If you develop your web service code as inline code, you will eventually need to compile it. The .NET SDK comes with a command-line compiler for each of the .NET languages that ships with the SDK. The .NET compilers, located in the \WINNT\Microsoft.NET\Framework\[version] directory, where [version] is the version number of your instance of the .NET Framework (mine is v1.0.3705), are listed in the following table.

.NET Language
Compiler
C#
csc.exe
VB.NET
vbc.exe
JSCRIPT.NET
Jsc.exe

There are several options for compiling a C# program into an assembly. If you're using Visual Studio, select "Build Solution" from the Build menu or use the shortcut Ctrl-Shift-B. Visual Studio .NET will compile your application into an assembly and place it into the \bin directory, usually under a subdirectory called debug or release depending on your settings. If you're compiling from the command line, use the csc.exe compiler to create your assembly, as shown in the following command:
csc.exe /out:bin\DNSLookupService.dll /target:library /r:System.Web.Services.dll DNSLookupService.asmx.cs

TIP: This command assumes that you are running the compiler from the directory on your web server that contains your C# source file, and that you have created a \bin subdirectory. For this command to work properly from any folder, include the compiler in your PATH environmental variable. In Windows 2000, this is done via Control Panel http://oreilly.com/catalog/prognetws/chapter/rarr.gifSystem Properties http://oreilly.com/catalog/prognetws/chapter/rarr.gifAdvanced tab http://oreilly.com/catalog/prognetws/chapter/rarr.gifEnvironment Variables http://oreilly.com/catalog/prognetws/chapter/rarr.gifSystem Variables, and adding \WINNT\Microsoft.NET\Framework\[version] to your PATH variable. Alternatively, if you have Visual Studio .NET installed, there is a menu option under Start http://oreilly.com/catalog/prognetws/chapter/rarr.gifPrograms http://oreilly.com/catalog/prognetws/chapter/rarr.gifVisual Studio .NET http://oreilly.com/catalog/prognetws/chapter/rarr.gifVisual Studio .NET Tools called Visual Studio .NET Command Prompt, which will open a command prompt window with the proper variables set for running the VS.NET tools.
The output from the previous command is shown in below figure.

Below Figure will show Compiling from the command line
http://oreilly.com/catalog/prognetws/chapter/pws_0215.gif

The compilation command tells the compiler to compile our source file DNSLookupService.asmx.cs into an assembly called DNSLookupService.dll. The /out: switch allows you to specify the output name and location for the compiled assembly. The /target: switch (which can be abbreviated as /t:) allows you to specify whether the output should be a console executable, Windows executable, library (DLL), or module. In our example, we want to build a DLL, so we've specified the library option, which forces the compiler to build our assembly to the \bin subdirectory (as specified with the /out switch).
The .NET compilers have a number of command-line switches. Some of the more useful ones are listed in below table.

 
Below Table will Show .NET command-line compiler switches
Switch
Description
/out:<file>
Specifies the name and location for the output file. The default action is for the compiler to derive the output name from the source filename.
/target:<type>
The target switch (short form, /t:) specifies the type of output file (types include exe, winexe, library, module).
/define:<symbol list>
Defines conditional compilation symbols; similar to using the #define xx statement in your program.
/doc:<file>
Specifies the output XML documentation that is created using any XML comments in your source code.
/recurse:<wildcard>
Specifies the names and locations of files to compile. For example, /recurse:dir1\dir2\*.cs compiles any files in and below dir2.
/reference:<file list>
The reference switch (short form, /r: ) specifies a list of assemblies (which must contain assembly manifests), separated by commas or semicolons, which will be made available for use at compile time. If you reference a file that itself references another file, both files must be included in the reference file list. This is also true for assemblies that contain classes that inherit from classes in other assemblies.
To import metadata from a file that does not contain an assembly manifest, such as a module, use the /addmodule switch.
/addmodule:<file list>
Same as /reference, but used for modules. Modules do not contain assembly manifests.
/win32res:<file>
Adds a Win32 resource file to your output file. A Win32 resource can contain version information that helps to identify your application to the Windows Explorer.
/win32icon:<file>
Allows you to specify an icon to be used by the Windows Explorer for the output file.
/debug[+|-] or:
/debug:[full|pdbonly]
Specifying + forces the compiler to write debugging information to a program database (.pdb) file. Specifying - causes no debug information to be written.
The /debug:full switch enables attaching a debugger to the running program. The /debug:pdbonly switch displays the assembler only when the program is attached to the debugger.
/optimize[+|-]
The optimize option (short form, /o) enables or disables compiler optimization for smaller and faster code. By default, optimization is enabled.
/incremental[+|-]
The incremental option (short form, /incr), incremental compilation compiles only those methods that have been modified since the last incremental compile. Information about the state of the previous compilation is stored in the <output_file_name>.dbg and <output_file_name>.incr files. These files are created the first time this option is used and henceforth are used for incremental builds.
In an incremental build, the /doc option is ignored.
Output files created with the incremental option may be larger than those created without.

Like most Windows command-line tools, the .NET compilers display a complete list of available options with the following command:
csc.exe /?

Once the source code has been compiled into an assembly and copied to the \bin directory, it's ready to be used by .NET. Unlike COM objects, which must be registered using regsvr32.exe before they can be used, .NET requires no such explicit registration.
In the next chapter, we cover some of the different ways of consuming web services using .NET applications.

1. If you're interested in learning more about WSDL, you can view the current spec at http://www.w3.org/TR/wsdl.html. Be forewarned that reading this document, while an excellent way to learn the intricacies of WSDL, is a sure cure for insomnia.
If you liked this article, share the love: