Sunteți pe pagina 1din 89

Notes

Asynchronous XML Web


Service Methods
To improve performance of Web service methods that invoke long-running methods that block their
thread, you should consider exposing them as asynchronous Web service methods. Implementing an
asynchronous Web service method allows that thread to execute other code when it is returned to the
thread pool. This allows one more of the limited number of threads in the thread pool to execute,
enhancing the overall performance and scalability of the system.

In general, Web service methods that call methods that perform I/O operations are good candidates for
asynchronous implementation. Examples of such methods include methods that communicate with other
Web services, access remote databases, perform network I/O, and read and write to large files. All these
methods spend the bulk of their time executing in hardware, which leaves the thread for executing the Web
service method blocked. That thread can be freed up to execute other code if the Web service method is
implemented asynchronously.
Regardless of whether a Web service method is implemented asynchronously, clients can communicate
with it asynchronously. Asynchronous communication is exposed to .NET clients within the proxy class that
is generated by the Web Services Description Language (WSDL.EXE) tool, even if a Web service method is
implemented synchronously. The proxy class contains Begin and End methods for communicating with each
Web service method asynchronously. Therefore, the decision to implement a Web service method
asynchronously or synchronously should be based upon performance.

To implement an asynchronous Web service


method
1. Split a synchronous Web service method into two methods, each with the same base name, one
with that name starting with Begin and the other End.
2. The parameter list for the Begin method contains all the in and by reference parameters for the
method's functionality plus two additional parameters.
o By reference parameters are listed as in parameters. 

o The second from the last parameter must be an AsyncCallback.


The AsyncCallback parameter allows a client to supply a delegate, which is invoked when
the method completes. When an asynchronous Web service method calls another
asynchronous method, this parameter can be passed into the second from last parameter
for that method. 

o The last parameter is an Object. The Object parameter allows a caller to supply state


information to the method. When an asynchronous Web service method calls another
asynchronous method, this parameter can be passed into the last parameter for that
method.
o The return value must be of type IAsyncResult.

3. The parameter list for the End method consists of an IAsyncResult followed by any out and by


reference parameters specific to the method's functionality.
o The return value is the same type as the return value of a synchronous Web service
method.

o By reference parameters are listed as out parameters.

Example
C#

VB

using System;
using System.Web.Services;

[WebService(Namespace="http://www.contoso.com/")]
public class MyService : WebService
{
public RemoteService remoteService;
public MyService()
{
// Create a new instance of proxy class for
// the Web service to be called.
remoteService = new RemoteService();
}
// Define the Begin method.
[WebMethod]
public IAsyncResult BeginGetAuthorRoyalties(String Author,
AsyncCallback callback, object asyncState)
{
// Begin asynchronous communictation with a different XML Web
// service.
return remoteService.BeginReturnedStronglyTypedDS(Author,
callback,asyncState);
}
// Define the End method.
[WebMethod]
public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult
asyncResult)
{
// Return the asynchronous result from the other Web service.
return remoteService.EndReturnedStronglyTypedDS(asyncResult);
}
}
How to: Chain Asynchronous
Calls with a Web Service
Method
The following code example demonstrates how to chain asynchronous calls when a Web service method
makes more than one asynchronous call and the calls must execute sequentially.
The BeginGetAuthorRoyaltiesmethod makes an asynchronous call to determine whether the author
passed in is valid and sets up an intermediate callback named AuthorRoyaltiesCallback to receive
the results. That intermediate callback then asynchronously calls to get the royalties for that author, if the
author is valid.

Example
C#

VB

using System.Web.Services;
using System.Data;
using System;
// This imports the proxy class for the Web services
// that the sample communicates with.
using AsyncWS.localhost;

namespace AsyncWS
{
[WebService(Namespace="http://www.contoso.com/")]
public class MyService : System.Web.Services.WebService
{
public RemoteService remoteService;
public MyService()
{
remoteService = new RemoteService();
}

[WebMethod]
public IAsyncResult BeginGetAuthorRoyalties(String Author,
AsyncCallback callback, Object asyncState)
{
// Saves the current state for the call that gets the author's
// royalties.
AsyncStateChain state = new AsyncStateChain();
state.originalState = asyncState;
state.Author = Author;
state.originalCallback = callback;

// Creates an intermediary callback.


AsyncCallback chainedCallback = new
AsyncCallback(AuthorRoyaltiesCallback);
return remoteService.BeginGetAuthors(chainedCallback,state);
}
// Intermediate method to handle chaining the
// asynchronous calls.
public void AuthorRoyaltiesCallback(IAsyncResult ar)
{
AsyncStateChain state = (AsyncStateChain)ar.AsyncState;
RemoteService rs = new RemoteService();

// Gets the result from the call to GetAuthors.


Authors allAuthors = rs.EndGetAuthors(ar);

Boolean found = false;


// Verifies that the requested author is valid.
int i = 0;
DataRow row;
while (i < allAuthors.authors.Rows.Count && !found)
{
row = allAuthors.authors.Rows[i];
if (row["au_lname"].ToString() == state.Author)
{
found = true;
}
i++;
}
if (found)
{
AsyncCallback cb = state.originalCallback;
// Calls the second Web service, because the author is
// valid.
rs.BeginReturnedStronglyTypedDS(state.Author,cb,state);
}
else
{
// Cannot throw the exception in this function or the XML Web
// service will hang. So, set the state argument to the
// exception and let the End method of the chained XML Web
// service check for it.
ArgumentException ex = new ArgumentException(
"Author does not exist.","Author");
AsyncCallback cb = state.originalCallback;
// Call the second Web service, setting the state to an
// exception.
rs.BeginReturnedStronglyTypedDS(state.Author,cb,ex);
}
}

[WebMethod]
public AuthorRoyalties EndGetAuthorRoyalties(IAsyncResult
asyncResult)
{
// Check whehter the first Web service threw an exception.
if (asyncResult.AsyncState is ArgumentException)
throw (ArgumentException) asyncResult.AsyncState;
else
return remoteService.EndReturnedStronglyTypedDS(asyncResult);
}
}
// Class to wrap the callback and state for the intermediate
// asynchronous operation.
public class AsyncStateChain
{
public AsyncCallback originalCallback;
public Object originalState;
public String Author;
}
}

Communicating with XML


Web Services Asynchronously
Communicating with a Web service asynchronously follows the two asynchronous method
invocation design patterns specified by the .NET Framework. Before you get to those details,
however, it is important to note that a Web service does not have to be specifically written to
handle asynchronous requests to be called asynchronously.

Wsdl.exe and the .NET Framework


Asynchronous Design Pattern
When the Web Services Description Language tool (Wsdl.exe) generates a client proxy class
to access a specified Web service, it provides the proxy class with two mechanisms for
communicating with each Web service method asynchronously. The first mechanism is the
Begin/End pattern. The second mechanism is the event-driven asynchronous programming
pattern available in version 2.0 of the .NET Framework. For a brief description of using the
patterns with Web services, see the following sections. For complete details about both
patterns, see Asynchronous Programming Design Patterns.
The Begin/End Invocation Pattern
Wsdl.exe automatically creates three methods for each operation (a Web service method in
ASP.NET) published in the Web service. One method is for synchronous access; the other
two are for asynchronous access. This is true even if there is only a synchronous
implementation of the Web service method. The following table describes those three
methods:

Method name in proxy class Description

<NameOfWebServiceMethod> Sends a message for the Web service method


named <NameOfWebServiceMethod>
synchronously.
Begin<NameOfWebServiceMethod Begins asynchronous message communication
> with a Web service method named
<NameOfWebServiceMethod>. The client
instructs the Begin method to start processing
the service call, but return immediately. The
return value is not the data type specified by
the Web service method, but rather a type
implementing the IAsyncResult interface.

End<NameOfWebServiceMethod> Ends an asynchronous message


communication with a Web service method
named <NameOfWebServiceMethod>,
returning a value that is the result of the Web
service method call.
The Begin and End methods follow the naming convention for the .NET Framework's
asynchronous design pattern. The design pattern predicates that there are two asynchronous
methods named as such for each synchronous method.
For an example, consider a Web service class PrimeFactorizer that has a Web service
method that searches for prime factors, with the following signature:
public long[] Factorize(long factorizableNum)
Such a method could take a relatively extended period of time to finish processing, depending
on the input. Thus, it is a good example of when you should have your Web service client to
call the Web service method asynchronously.
If Wsdl.exe used this Web service as an input for generating client proxy code (using the ?
wsdl query string for an ASP.NET Web service), it would generate methods with the
following signatures:
C#

public long[] Factorize(long factorizableNum)


public System.IAsyncResult BeginFactorize(long factorizableNum,
System.AsyncCallback callback, object asyncState)
public long[] EndFactorize(System.IAsyncResult asyncResult)
Implementing a Web Service Client That Makes an Asynchronous Method
Call Using the Begin/End Pattern
How does a client know when to call the End method? There are two techniques for
implementing a client to determine this, as defined by the .NET Framework:

 Wait technique: Use one of the methods of the WaitHandle class to cause a client to wait for
the method to complete. 

 Callback technique: Pass a callback function into the Begin method, which is then called to
retrieve the results when the method has completed processing.

Note: Regardless of which of the two techniques a client chooses to communicate with a


Web service asynchronously, the SOAP messages sent and received are identical to the
SOAP messages generated through the synchronous proxy method. That is, there is still only
one SOAP request and SOAP response sent and received across the network. The proxy class
accomplishes this by handling the SOAP response using a different thread than the thread the
client used to call the Begin method. Therefore, the client can continue to perform other work
on its thread, while the proxy class handles receiving and processing the SOAP response.
Wait Technique Using the Begin/End Pattern
The WaitHandle class implements methods that support waiting for synchronization objects
to be signaled: WaitOne, WaitAny, and WaitAll. The signaling of a synchronization object
is an indication that threads waiting upon the specified resource can then access the resource.
The Web service client accesses a WaitHandle object through the AsyncWaitHandle property
of the IAsyncResult object returned by the Begin method.
For an example of this technique, see How to: Implement an Asynchronous Web Service
Client Using the Wait Technique.
Callback Technique Using the Begin/End Pattern
With the callback technique, a callback function implements the AsyncCallback delegate,
which enforces the signature:
public void MethodName(IAsyncResult ar)
For an example of this technique, see How to: Implement an Asynchronous Web Service
Client Using the Callback Technique.
If the callback requires synchronized/thread-affinity context, it is dispatched through the
context dispatcher infrastructure. In other words, the callback might execute asynchronously
with respect to its caller for such contexts. That is precisely the semantics of the one-way
qualifier on method signatures. It means that any such method call might execute
synchronously or asynchronously, with respect to the caller, and the caller cannot make any
assumptions about completion of such a call when execution control returns to it.
Calling the End method before the asynchronous operation is complete will block the caller.
The behavior for calling it a second time with the same IAsyncResult returned by
the Begin method is undefined.
Asynchronous Web Service Clients Using the Event-Driven
Asynchronous Pattern
Multithreaded Programming with the Event-based Asynchronous Pattern introduces a new asynchronous
programming model that uses events to handle callbacks, making it easier to build multithreaded
applications without having to implement complex multithreaded code yourself. For an overview of the new
event-driven asynchronous model, see Event-based Asynchronous Pattern Overview. For details about
client implementations using the new model, see How to: Implement a Client of the Event-based
Asynchronous Pattern.

How to: Manage State in Web


Services Created Using
ASP.NET
Web services have access to the same state management options as other ASP.NET applications when the
class that implements the Web service derives from the WebService class. The WebService class contains
many of the common ASP.NET objects, including the Session and Application objects.
To access and store state specific to a
particular client session
1. Declare a Web service.

C#

<%@ WebService Language="C#" Class="ServerUsage" %>

VB

<%@ WebService Language="VB" Class="ServerUsage" %>


2. Add a reference to the System.Web.Services namespace.

C#

using System.Web.Services;

VB

Imports System.Web.Services
3. Derive the class that implements the Web service from WebService .

C#

public class ServerUsage : WebService

VB

Public Class ServerUsage : Inherits WebService


4. Declare a Web service method, setting the EnableSession property of the WebMethod attribute
to true.

C#

[ WebMethod(EnableSession=true) ]
public int PerSessionServiceUsage()

VB

< WebMethod(EnableSession:=True) > _


Public Function PerSessionServiceUsage() As Integer
5. Store state in the Session, which specifies a name for the state for later retrieval. In the following
example the value 1 is stored in a state variable named MyServiceUsage.

C#

Session["MyServiceUsage"] = 1;

VB
Session("MyServiceUsage") = 1
6. Access the state variable stored in the Session .
In the following example, the MyServiceUsage state variable is accessed to increment its value.

C#

Session["MyServiceUsage"] = ((int) Session["MyServiceUsage"]) + 1;

VB

Session("MyServiceUsage") = CInt(Session("MyServiceUsage")) + 1

To access and store state specific to the Web


application hosting the Web service
1. Declare a Web service.

C#

<%@ WebService Language="C#" Class="ServerUsage" %>

VB

<%@ WebService Language="VB" Class="ServerUsage" %>


2. Add a reference to the System.Web.Services namespace.

C#

using System.Web.Services;

VB

Imports System.Web.Services
3. Derive the class that implements the Web service from WebService .

C#

public class ServerUsage : WebService

VB

Public Class ServerUsage : Inherits WebService


4. Declare a Web service method.

C#

[ WebMethod ]
public int PerSessionServiceUsage()

VB
< WebMethod > _
Public Function PerSessionServiceUsage() As Integer
5. Store state in the Application, which specifies a name for the state for later retrieval. In the
following example the value 1 is stored in a state variable named appMyServiceUsage.

C#

Application["appMyServiceUsage"] = 1;

VB

Application("appMyServiceUsage") = 1
6. Access the state variable stored in the Application.
In the following example, the appMyServiceUsage state variable is accessed to increment its
value.

C#

Application["appMyServiceUsage"] =
((int) Application["appMyServiceUsage"]) + 1;

VB

Application("appMyServiceUsage") = _
CInt(Application("appMyServiceUsage")) + 1

Example
C#

VB

<%@ WebService Language="C#" Class="ServerUsage" %>


using System.Web.Services;

public class ServerUsage : WebService {


[ WebMethod(Description="Number of times this service has been
accessed.") ]
public int ServiceUsage() {
// If the Web service method hasn't been accessed,
// initialize it to 1.
if (Application["appMyServiceUsage"] == null)
{
Application["appMyServiceUsage"] = 1;
}
else
{
// Increment the usage count.
Application["appMyServiceUsage"] = ((int)
Application["appMyServiceUsage"]) + 1;
}
return (int) Application["appMyServiceUsage"];
}
[ WebMethod(Description="Number of times a particular client session has
accessed this Web service method.",EnableSession=true) ]
public int PerSessionServiceUsage() {
// If the Web service method hasn't been accessed, initialize
// it to 1.
if (Session["MyServiceUsage"] == null)
{
Session["MyServiceUsage"] = 1;
}
else
{
// Increment the usage count.
Session["MyServiceUsage"] = ((int) Session["MyServiceUsage"]) + 1;
}
return (int) Session["MyServiceUsage"];
}
}

Transactions in ASP.NET XML


Web Services
For an XML Web service created using ASP.NET, you can declare the Web service's transactional behavior
by setting the TransactionOption property of the WebMethod attribute applied to the Web service method.
For an explanation of how transactions work for Web service methods, see  Transactions in ASP.NET XML
Web Services.

To participate in a transaction from a Web


service method
1. Declare a Web service.

C#

<%@ WebService Language="C#" Class="Orders" %>

VB

<%@ WebService Language="VB" Class="Orders" %>


2. Add an Assembly directive to System.EnterpriseServices.
3. <%@ Assembly
name="System.EnterpriseServices,Version=1.0.3300.0,Culture=neutral,Pu
blicKeyToken=b03f5f7f11d50a3a" %>
4. Add references to the System.Web.Services and System.EnterpriseServices namespaces.

C#

using System.Web.Services;
using System.EnterpriseServices;
VB

Imports System.Web.Services
Imports System.EnterpriseServices
5. Declare a Web service method, setting the TransactionOption property of
the WebMethodAttribute attribute to System.EnterpriseServices.TransactionOption.RequiresNew .

C#

[ WebMethod(TransactionOption=TransactionOption.RequiresNew)]
public int DeleteAuthor(string lastName)

VB

< WebMethod(TransactionOption:=TransactionOption.RequiresNew)> _
Public Function DeleteAuthor(lastName As String) As Integer

TransactionOption
Enumeration
Specifies the automatic transaction type requested by the component.
Namespace:  System.EnterpriseServices
Assembly:  System.EnterpriseServices (in System.EnterpriseServices.dll)

Syntax
C#
C++
F#
VB
[SerializableAttribute]
public enum TransactionOption

Members

Member
Description
name

Disabled Ignores any transaction in the current context.

NotSupporte Creates the component in a context with no governing transaction.


d
Supported Shares a transaction, if one exists.

Required Shares a transaction, if one exists, and creates a new transaction if


necessary.

RequiresNe Creates the component with a new transaction, regardless of the


w state of the current context.

Remarks
When using the .NET Installation Tool (Regsvcs.exe), the transaction option for
a ServicedComponent defaults to Disabled.

Examples
The following code example demonstrates the use of the TransactionOption type.
C#
C++
VB

using System;
using System.EnterpriseServices;
using System.Reflection;

// References:
// System.EnterpriseServices

// An instance of this class will not participate in transactions, but can


// share its caller's context even if its caller is configured as
// NotSupported, Supported, Required, or RequiresNew.
[Transaction(TransactionOption.Disabled)]
public class TransactionAttribute_TransactionDisabled : ServicedComponent
{
}

// An instance of this class will not participate in transactions, and will


// share its caller's context only if its caller is also configured as
// NotSupported.
[Transaction(TransactionOption.NotSupported)]
public class TransactionAttribute_TransactionNotSupported :
ServicedComponent
{
}

// An instance of this class will participate in its caller's transaction


// if one exists.
[Transaction(TransactionOption.Supported)]
public class TransactionAttribute_TransactionSupported : ServicedComponent
{
}
// An instance of this class will participate in its caller's transaction
// if one exists. If not, a new transaction will be created for it.
[Transaction(TransactionOption.Required)]
public class TransactionAttribute_TransactionRequired : ServicedComponent
{
}

// A new transaction will always be created for an instance of this class.


[Transaction(TransactionOption.RequiresNew)]
public class TransactionAttribute_TransactionRequiresNew :
ServicedComponent
{
}

WebMethodAttribute.Transacti
onOption Property
Indicates the transaction support of an XML Web service method.
Namespace:  System.Web.Services
Assembly:  System.Web.Services (in System.Web.Services.dll)

Syntax
C#

C++

F#

VB

public TransactionOption TransactionOption { get; set; }


Property Value
Type: System.EnterpriseServices.TransactionOption
The transaction support of an XML Web service method. The default is Disabled.

Remarks
XML Web service methods can only participate as the root object in a transaction, due to the stateless
nature of the HTTP protocol. XML Web service methods can invoke COM objects that participate in the
same transaction as the XML Web service method, if the COM object is marked to run within a transaction
in the Component Services administrative tool. If an XML Web service method with
a TransactionOption property ofRequired or RequiresNew invokes another XML Web service method with
a TransactionOption property of Required or RequiresNew, each XML Web service method participates in
its own transaction, because an XML Web service method can only act as the root object in a transaction.
Item Description

Disabled Indicates that the XML Web service method does not run within the
scope of a transaction. When a request is processed, the XML Web
service method is executed without a transaction.
[WebMethod(TransactionOption= TransactionOption.Disabled)]

NotSupporte Indicates that the XML Web service method does not run within the
d scope of a transaction. When a request is processed, the XML Web
service method is executed without a transaction.
[WebMethod(TransactionOption= TransactionOption.NotSupporte
d)]

Supported Indicates that the XML Web service method does not run within the
scope of transactions. When a request is processed, the XML Web
service is created without a transaction.
[WebMethod(TransactionOption= TransactionOption.Supported)]

Required Indicates that the XML Web service method requires a transaction.
Since XML Web service methods can only participate as the root
object in a transaction, a new transaction will be created for the XML
Web service method.
[WebMethod(TransactionOption= TransactionOption.Required)]

RequiresNe Indicates that the XML Web service method requires a new
w transaction. When a request is processed, the XML Web service is
created within a new transaction.
[WebMethod(TransactionOption= TransactionOption.RequiresNe
w)]
If an exception is thrown from or not caught by an XML Web service method, the transaction is
automatically aborted. If no exceptions occur the transaction is automatically committed unless the method
explicitly callsSetAbort.

Examples
The example below begins a new transaction when the Transfer method is called.
C#

VB

<%@ WebService Language="C#" Class="Bank"%>


<%@ assembly
name="System.EnterpriseServices,Version=1.0.3300.0,Culture=neutral,PublicKe
yToken=b03f5f7f11d50a3a" %>

using System;
using System.Web.Services;
using System.EnterpriseServices;

public class Bank : WebService {


[ WebMethod(TransactionOption=TransactionOption.RequiresNew) ]
public void Transfer(long Amount, long AcctNumberTo, long
AcctNumberFrom) {
MyCOMObject objBank = new MyCOMObject();

if (objBank.GetBalance(AcctNumberFrom) < Amount )


// Explicitly abort the transaction.
ContextUtil.SetAbort();
else {
// Credit and Debit methods explictly vote within
// the code for their methods whether to commit or
// abort the transaction.
objBank.Credit(Amount, AcctNumberTo);
objBank.Debit(Amount, AcctNumberFrom);
}
}
}

WebMethodAttribute Class
Adding this attribute to a method within an XML Web service created using ASP.NET makes the method
callable from remote Web clients. This class cannot be inherited.
Namespace:  System.Web.Services
Assembly:  System.Web.Services (in System.Web.Services.dll)

Syntax
C#
C++
F#
VB
[AttributeUsageAttribute(AttributeTargets.Method)]
public sealed class WebMethodAttribute : Attribute

The WebMethodAttribute type exposes the following members.

Constructors

Show:  Inherited  Protected

  Name Description

WebMethodAttribute() Initializes a new instance of


the WebMethodAttribute class.
WebMethodAttribute(Boolean) Initializes a new instance of
the WebMethodAttribute class.

WebMethodAttribute(Boolean, Initializes a new instance of


TransactionOption) the WebMethodAttribute class.

WebMethodAttribute(Boolean, Initializes a new instance of


TransactionOption, Int32) the WebMethodAttribute class.

WebMethodAttribute(Boolean, Initializes a new instance of


TransactionOption, Int32, Boolean) the WebMethodAttribute class.

Top

Properties

Show:  Inherited  Protected

  Name Description

BufferResponse Gets or sets whether the response for this request is


buffered.

CacheDuration Gets or sets the number of seconds the response should be


held in the cache.

Description A descriptive message describing the XML Web service


method.

EnableSession Indicates whether session state is enabled for an XML


Web service method.

MessageName The name used for the XML Web service method in the
data passed to and returned from an XML Web service
method.
TransactionOptio Indicates the transaction support of an XML Web service
n method.

TypeId When implemented in a derived class, gets a unique


identifier for this Attribute. (Inherited from Attribute.)

Top

Methods

Show:  Inherited  Protected

  Name Description

Equals Infrastructure. Returns a value that indicates whether this


instance is equal to a specified object. (Inherited
from Attribute.)

Finalize Allows an object to try to free resources and perform other


cleanup operations before it is reclaimed by garbage
collection. (Inherited from Object.)

GetHashCode Returns the hash code for this instance. (Inherited


from Attribute.)

GetType Gets the Type of the current instance. (Inherited


from Object.)

IsDefaultAttribute When overridden in a derived class, indicates whether the


value of this instance is the default value for the derived
class. (Inherited from Attribute.)

Match When overridden in a derived class, returns a value that


indicates whether this instance equals a specified
object. (Inherited from Attribute.)

MemberwiseClon Creates a shallow copy of the current Object. (Inherited


e from Object.)
ToString Returns a string that represents the current
object. (Inherited from Object.)

Top

Explicit Interface Implementations

Show:  Inherited  Protected

  Name Description

_Attribute.GetIDsOfNames Maps a set of names to a corresponding set of


dispatch identifiers. (Inherited from Attribute.)

_Attribute.GetTypeInfo Retrieves the type information for an object,


which can be used to get the type information
for an interface. (Inherited from Attribute.)

_Attribute.GetTypeInfoCou Retrieves the number of type information


nt interfaces that an object provides (either 0 or
1). (Inherited from Attribute.)

_Attribute.Invoke Provides access to properties and methods


exposed by an object. (Inherited
from Attribute.)

Top

Remarks
Methods within a class that have this attribute set are called XML Web service methods. The method and
class must be public and running inside an ASP.NET Web application.

Topic

Walkthrough: Creating and Using an ASP.NET Web Service in Visual Web Developer

Examples
In the example below the method GetMachineName can be remotely called across the Web, because it has
a WebMethodAttribute. GetUserName cannot be called remotely, because it does not have
a WebMethodAttribute, even though it is public.
C#
VB
<%@ WebService Language="C#" Class="Util"%>
using System;
using System.Web.Services;
public class Util: WebService {
public string GetUserName() {
return User.Identity.Name;
}

[ WebMethod(Description="Obtains the Server Machine Name",


EnableSession=true)]
public string GetMachineName() {
return Server.MachineName;
} }

Implementing an Implicit
Transaction using Transaction
Scope
The TransactionScope class provides a simple way to mark a block of code as participating in a transaction,
without requiring you to interact with the transaction itself. A transaction scope can select and manage the
ambient transaction automatically. Due to its ease of use and efficiency, it is recommended that you use
the TransactionScope class when developing a transaction application.
In addition, you do not need to enlist resources explicitly with the transaction.
Any System.Transactions resource manager (such as SQL Server 2005) can detect the existence of an
ambient transaction created by the scope and automatically enlist.

Creating a transaction scope


The following sample shows a simple usage of the TransactionScope class.
The transaction scope is started once you create a new TransactionScope object.  As illustrated in the code
sample, it is recommended that you create scopes with a using statement. The using statement is available
both in C# and in Visual Basic, and works like a try...finally block to ensure that the scope is disposed of
properly.
When you instantiate TransactionScope, the transaction manager determines which transaction to
participate in. Once determined, the scope always participates in that transaction. The decision is based on
two factors: whether an ambient transaction is present and the value of
the TransactionScopeOption parameter in the constructor. The ambient transaction is the transaction
within which your code executes. You can obtain a reference to the ambient transaction by calling the
static Current property of the Transaction class. For more information on how this parameter is used, see
the Managing transaction flow using TransactionScopeOption section of this topic.

Completing a transaction scope


When your application completes all the work it wants to perform in a transaction, you should call
the Complete method only once to inform the transaction manager that it is acceptable to commit the
transaction. It is very good practice to put the call to Complete as the last statement in the using block.
Failing to call this method aborts the transaction, because the transaction manager interprets this as a
system failure, or equivalent to an exception thrown within the scope of transaction. However, calling this
method does not guarantee that the transaction wil be committed. It is merely a way of informing the
transaction manager of your status. After calling the Complete method, you can no longer access the
ambient transaction by using theCurrent property, and attempting to do so will result in an exception
being thrown.
If the TransactionScope object created the transaction initially, the actual work of committing the
transaction by the transaction manager occurs after the last line of code in the  using block. If it did not
create the transaction, the commit occurs whenever Commit is called by the owner of
the CommittableTransaction object. At that point the Transaction Manager calls the resource managers and
informs them to either commit or rollback, based on whether the Complete method was called on
the TransactionScope object.
The using statement ensures that the Dispose method of the TransactionScope object is called even if an
exception occurs. The Dispose method marks the end of the transaction scope. Exceptions that occur after
calling this method may not affect the transaction. This method also restores the ambient transaction to it
previous state.
A TransactionAbortedException is thrown if the scope creates the transaction, and the transaction is
aborted. A TransactionIndoubtException is thrown if the transaction manager cannot reach a Commit
decision. No exception is thrown if the transaction is committed.

Rolling back a transaction


If you want to rollback a transaction, you should not call the Complete method within the transaction
scope. For example, you can throw an exception within the scope. The transaction in which it participates in
will be rolled back.

Managing transaction flow using


TransactionScopeOption
Transaction scope can be nested by calling a method that uses a TransactionScope from within a method
that uses its own scope, as is the case with the RootMethod method in the following example,
C#

void RootMethod()
{
using(TransactionScope scope = new TransactionScope())
{
/* Perform transactional work here */
SomeMethod();
scope.Complete();
}
}

void SomeMethod()
{
using(TransactionScope scope = new TransactionScope())
{
/* Perform transactional work here */
scope.Complete();
}
}
The top-most transaction scope is referred to as the root scope.
The TransactionScope class provides several overloaded constructors that accept an enumeration of the
type TransactionScopeOption, which defines the transactional behavior of the scope.
A TransactionScope object has three options:
 Join the ambient transaction, or create a new one if one does not exist.
 Be a new root scope, that is, start a new transaction and have that transaction be the new ambient
transaction inside its own scope.
 Not take part in a transaction at all. There is no ambient transaction as a result.
If the scope is instantiated with Required, and an ambient transaction is present, the scope joins that
transaction. If, on the other hand, there is no ambient transaction, then the scope creates a new transaction,
and become the root scope. This is the default value. When Required is used, the code inside the scope
does not need to behave differently whether it is the root or just joining the ambient transaction. It should
operate identically in both cases.
If the scope is instantiated with RequiresNew, it is always the root scope. It starts a new transaction, and its
transaction becomes the new ambient transaction inside the scope.
If the scope is instantiated with Suppress, it never takes part in a transaction, regardless of whether an
ambient transaction is present. A scope instantiated with this value always have null as its ambient
transaction.
The above options are summarized in the following table.

TransactionScopeOption Ambient Transaction The scope takes part in

Required No New Transaction (will be the root)

Requires New No New Transaction (will be the root)

Suppress No No Transaction

Required Yes Ambient Transaction

Requires New Yes New Transaction (will be the root)

Suppress Yes No Transaction


When a TransactionScope object joins an existing ambient transaction, disposing of the scope object may
not end the transaction, unless the scope aborts the transaction. If the ambient transaction was created by a
root scope, only when the root scope is disposed of, does Commit get called on the transaction. If the
transaction was created manually, the transaction ends when it is either aborted, or committed by its
creator.
The following example shows a TransactionScope object that creates three nested scope objects, each
instantiated with a different TransactionScopeOption value.
C#

using(TransactionScope scope1 = new TransactionScope())


//Default is Required
{
using(TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Required))
{
...
}

using(TransactionScope scope3 = new


TransactionScope(TransactionScopeOption.RequiresNew))
{
...
}
using(TransactionScope scope4 = new
TransactionScope(TransactionScopeOption.Suppress))
{
...
}
}
The example shows a code block without any ambient transaction creating a new scope ( scope1)
with Required. The scope scope1 is a root scope as it creates a new transaction (Transaction A) and
makes Transaction A the ambient transaction. Scope1 then creates three more objects, each with a
different TransactionScopeOption value. For example, scope2 is created with Required, and since there
is an ambient transaction, it joins the first transaction created by scope1. Note that scope3 is the root
scope of a new transaction, and that scope4 has no ambient transaction.
Although the default and most commonly used value of TransactionScopeOption is Required, each of the
other values has its unique purpose.
Suppress is useful when you want to preserve the operations performed by the code section, and do not
want to abort the ambient transaction if the operations fail. For example, when you want to perform
logging or audit operations, or when you want to publish events to subscribers regardless of whether your
ambient transaction commits or aborts. This value allows you to have a non-transactional code section
inside a transaction scope, as shown in the following example.
C#

using(TransactionScope scope1 = new TransactionScope())


{
try
{
//Start of non-transactional section
using(TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Suppress))
{
//Do non-transactional work here
}
//Restores ambient transaction here
}
catch
{}
//Rest of scope1
}

Voting inside a nested scope


Although a nested scope can join the ambient transaction of the root scope, calling Complete in the nested
scope has no affect on the root scope. Only if all the scopes from the root scope down to the last nested
scope vote to commit the transaction, will the transaction be committed.

Setting the TransactionScope timeout


Some of the overloaded constructors of TransactionScope accept a value of type TimeSpan, which is used
to control the timeout of the transaction. A timeout set to zero means an infinite timeout. Infinite timeout is
useful mostly for debugging, when you want to isolate a problem in your business logic by stepping
through your code, and you do not want the transaction you debug to time out while you attempt to locate
the problem. Be extremely careful using the infinite timeout value in all other cases, because it overrides the
safeguards against transaction deadlocks.
You typically set the TransactionScope timeout to values other than default in two cases. The first is during
development, when you want to test the way your application handles aborted transactions. By setting the
timeout to a small value (such as one millisecond), you cause your transaction to fail and can thus observe
your error handling code. The second case in which you set the value to be less than the default timeout is
when you believe that the scope is involved in resource contention, resulting in deadlocks. In that case, you
want to abort the transaction as soon as possible and not wait for the default timeout to expire.
When a scope joins an ambient transaction but specifies a smaller timeout than the one the ambient
transaction is set to, the new, shorter timeout is enforced on the TransactionScope object, and the scope
must end within the nested time specified, or the transaction is automatically aborted. If the nested scope's
timeout is more than that of the ambient transaction, it has no effect.

Setting the TransactionScope isolation level


Some of the overloaded constructors of TransactionScope accept a structure of
type TransactionOptions to specify an isolation level, in addition to a timeout value. By default, the
transaction executes with isolation level set to Serializable. Selecting an isolation level other
than Serializable is commonly used for read-intensive systems. This requires a solid understanding of
transaction processing theory and the semantics of the transaction itself, the concurrency issues involved,
and the consequences for system consistency.
In addition, not all resource managers support all levels of isolation, and they may elect to take part in the
transaction at a higher level than the one configured.
Every isolation level besides Serializable is susceptible to inconsistency resulting from other transactions
accessing the same information. The difference between the different isolation levels is in the way read and
write locks are used. A lock can be held only when the transaction accesses the data in the resource
manager, or it can be held until the transaction is committed or aborted. The former is better for
throughput, the latter for consistency. The two kinds of locks and the two kinds of operations (read/write)
give four basic isolation levels. See IsolationLevel for more information.
When using nested TransactionScope objects, all nested scopes must be configured to use exactly the
same isolation level if they want to join the ambient transaction. If a nested TransactionScope object tries
to join the ambient transaction yet it specifies a different isolation level, an ArgumentException is thrown.

Implementing an Explicit
Transaction using
CommittableTransaction
The CommittableTransaction class provides an explicit way for applications to use a transaction, as opposed
to using the TransactionScope class implicitly. It is useful for applications that want to use the same
transaction across multiple function calls or multiple thread calls. Unlike the TransactionScope class, the
application writer needs to specifically call the Commit and Rollback methods in order to commit or abort
the transaction.

Overview of the CommittableTransaction class


The CommittableTransaction class derives from the Transaction class, therefore providing all the
functionality of the latter. Specifically useful is the Rollback method on the Transaction class that can also
be used to rollback a CommittableTransaction object.
The Transaction class is similar to the CommittableTransaction class but does not offer
a Commit method. This enables you to pass the transaction object (or clones of it) to other methods
(potentially on other threads) while still controlling when the transaction is committed. The called code is
able to enlist and vote on the transaction, but only the creator of the CommittableTransaction object has
the ability to commit the transaction.
You should note the followings when working with the CommittableTransaction class,
 Creating a CommittableTransaction transaction does not set the ambient transaction. You need
to specifically set and reset the ambient transaction, to ensure that resource managers operate
under the right transaction context when appropriate. The way to set the current ambient
transaction is by setting the static Current property on the global Transaction object.
 A CommittableTransaction object cannot be reused. Once a CommittableTransaction object has
been committed or rolled back, it cannot be used again in a transaction. That is, it cannot be set as
the current ambient transaction context.

Creating a CommittableTransaction
The following sample creates a new CommittableTransaction and commits it.
Creating an instance of CommittableTransaction does not automatically set the ambient transaction
context. Therefore, any operation on a resource manager is not part of that transaction. The
static Current property on the global Transaction object is used to set or retrieve the ambient transaction
and the application must manually set it to ensure that resource managers can participate in the
transaction. It is also a good practice to save the old ambient transaction and restore it when you finish
using the CommittableTransaction object.
To commit the transaction, you need to explicitly call the Commit method. For rolling back a transaction,
you should call the Rollback method. It is important to note that until a CommittableTransaction has
been committed or rolled back, all the resources involved in that transaction are still locked.
A CommittableTransaction object can be used across function calls and threads. However, it is up to the
application developer to handle exceptions and specifically call the Rollback method in case of failures.

Asynchronous Commit
The CommittableTransaction class also provides a mechanism for committing a transaction
asynchronously. A transaction commit can take substantial time, as it might involve multiple database
access and possible network latency. When you want to avoid deadlocks in high throughput applications,
you can use asynchronous commit to finish the transactional work as soon as possible, and run the commit
operation as a background task. TheBeginCommit and EndCommit methods of
the CommittableTransaction class allow you to do so.
You can call BeginCommit to dispatch the commit holdup to a thread from the thread pool. You can also
call EndCommit to determine if the transaction has actually been committed. If the transaction failed to
commit for whatever reason, EndCommit raises a transaction exception. If the transaction is not yet
committed by the time EndCommit is called, the caller is blocked until the transaction is committed or
aborted.
The easiest way to do an asynchronous commit is by providing a callback method, to be called when
committing is finished. However, you must call the EndCommit method on the
original CommittableTransaction object used to invoke the call. To obtain that object, you can downcast
the IAsyncResult parameter of the callback method, since the CommittableTransaction class
implements IAsyncResult class.
The following example shows how an asynchronous commit can be done.
C#

public void DoTransactionalWork()


{
Transaction oldAmbient = Transaction.Current;
CommittableTransaction committableTransaction = new
CommittableTransaction();
Transaction.Current = committableTransaction;

try
{
/* Perform transactional work here */
// No errors - commit transaction asynchronously
committableTransaction.BeginCommit(OnCommitted,null);
}
finally
{
//Restore the ambient transaction
Transaction.Current = oldAmbient;
}
}
void OnCommitted(IAsyncResult asyncResult)
{
CommittableTransaction committableTransaction;
committableTransaction = asyncResult as CommittableTransaction;
Debug.Assert(committableTransaction != null);
try
{
using(committableTransaction)
{
committableTransaction.EndCommit(asyncResult);
}
}
catch(TransactionException e)
{
//Handle the failure to commit
}
}

Transaction Management
Escalation
Windows hosts a set of services and modules that together constitute a transaction manager. Transaction
management escalation describes the process of migrating a transaction from one of the transaction
manager's components to another.
System.Transactions includes a transaction manager component that coordinates a transaction involving at
most, a single durable resource or multiple volatile resources. Because the transaction manager uses only
intra-application domain calls, it yields the best performance. Developers need not interact with the
transaction manager directly. Instead, a common infrastructure that defines interfaces, common behavior,
and helper classes is provided by the System.Transactions namespace.
When you want to provide the transaction to another object in another application domain (including
across process and machine boundaries) on the same computer, the System.Transactions infrastructure
automatically escalates the transaction to be managed by the Microsoft Distributed Transaction
Coordinator (MSDTC). The escalation also occurs if you enlist another durable resource manager. When
escalated, the transaction remains managed in its elevated state until its completion.
Between the System.Transactions transaction and MSDTC transaction, there is an intermediary type of
transaction that is made available through the Promotable Single Phase Enlistment (PSPE). PSPE is another
important mechanism in System.Transactions for performance optimization. It allows a remote durable
resource, located in a different application domain, process or computer, to participate in
a System.Transactions transaction without causing it to be escalated to an MSDTC transaction. For more
information about PSPE, see Enlisting Resources as Participants in a Transaction.
How Escalation is Initiated
Transaction escalation reduces performance because the MSDTC resides in a separate process, and
escalating a transaction to the MSDTC results in messages being sent across process. To improve
performance, you should delay or avoid escalation to MSDTC; thus, you need to know how and when the
escalation is initiated.
As long as the System.Transactions infrastructure handles volatile resources and at most one durable
resource that supports single-phase notifications, the transaction remains in the ownership of
the System.Transactionsinfrastructure. The transaction manager avails itself only to those resources that
live in the same application domain and for which logging (writing the transaction outcome to disk) is not
required. An escalation that results in the System.Transactions infrastructure transferring the ownership of
the transaction to MSDTC happens when:
 At least one durable resource that does not support single-phase notifications is enlisted in the
transaction.
 At least two durable resources that support single-phase notifications are enlisted in the
transaction. For example, enlisting a single connection with does not cause a transaction to be
promoted. However, whenever you open a second connection to a database causing the database
to enlist, the System.Transactions infrastructure detects that it is the second durable resource in
the transaction, and escalates it to an MSDTC transaction.
 A request to "marshal" the transaction to a different application domain or different process is
invoked. For example, the serialization of the transaction object across an application domain
boundary. The transaction object is marshaled-by-value, meaning that any attempt to pass it
across an application domain boundary (even in the same process) results in serialization of the
transaction object. You can pass the transaction objects by making a call on a remote method that
takes a Transaction as a parameter or you can try to access a remote transactional-serviced
component. This serializes the transaction object and results in an escalation, as when a transaction
is serialized across an application domain. It is being distributed and the local transaction manager
is no longer adequate.
The following table lists all the possible exceptions that can be thrown during escalation.

Exception type Condition

InvalidOperationException An attempt to escalate a transaction with isolation


level equal to Snapshot.

TransactionAbortedExceptio The transaction manager is down.


n

TransactionException The escalation fails and the application is aborted.

Managing Concurrency with


DependentTransaction
The Transaction object is created using the DependentClone method. Its sole purpose is to guarantee that
the transaction cannot commit while some other pieces of code (for example, a worker thread) are still
performing work on the transaction. When the work done within the cloned transaction is complete and
ready to be committed, it can notify the creator of the transaction using the  Complete method. Thus, you
can preserve the consistency and correctness of data.
The DependentTransaction class can also be used to manage concurrency between asynchronous tasks. In
this scenario, the parent can continue to execute any code while the dependent clone works on its own
tasks. In other words, the parent's execution is not blocked until the dependent completes.

Creating a Dependent Clone


To create a dependent transaction, call the DependentClone method and pass
the DependentCloneOption enumeration as a parameter. This parameter defines the behavior of the
transaction if Commit is called on the parent transaction before the dependent clone indicates that it is
ready for the transaction to commit (by calling the Complete method). The following values are valid for
this parameter:
 BlockCommitUntilComplete creates a dependent transaction that blocks the commit process of the
parent transaction until the parent transaction times out, or until Complete is called on all
dependents indicating their completion. This is useful when the client does not want the parent
transaction to commit until the dependent transactions have completed. If the parent finishes its
work earlier than the dependent transaction and callsCommit on the transaction, the commit
process is blocked in a state where additional work can be done on the transaction and new
enlistments can be created, until all of the dependents call Complete. As soon as all of them have
finished their work and call Complete, the commit process for the transaction begins.
 RollbackIfNotComplete, on the other hand, creates a dependent transaction that automatically
aborts if Commit is called on the parent transaction before Complete is called. In this case, all the
work done in the dependent transaction is intact within one transaction lifetime, and no one has a
chance to commit just a portion of it.
The Complete method must be called only once when your application finishes its work on the dependent
transaction; otherwise, a InvalidOperationException is thrown. After this call is invoked, you must not
attempt any additional work on the transaction, or an exception is thrown.
The following code example shows how to create a dependent transaction to manage two concurrent tasks
by cloning a dependent transaction and passing it to a worker thread.
C#

public class WorkerThread


{
public void DoWork(DependentTransaction dependentTransaction)
{
Thread thread = new Thread(ThreadMethod);
thread.Start(dependentTransaction);
}

public void ThreadMethod(object transaction)


{
DependentTransaction dependentTransaction = transaction as
DependentTransaction;
Debug.Assert(dependentTransaction != null);
try
{
using(TransactionScope ts = new
TransactionScope(dependentTransaction))
{
/* Perform transactional work here */
ts.Complete();
}
}
finally
{
dependentTransaction.Complete();
dependentTransaction.Dispose();
}
}

//Client code
using(TransactionScope scope = new TransactionScope())
{
Transaction currentTransaction = Transaction.Current;
DependentTransaction dependentTransaction;
dependentTransaction =
currentTransaction.DependentClone(DependentCloneOption.BlockCommitUntilComp
lete);
WorkerThread workerThread = new WorkerThread();
workerThread.DoWork(dependentTransaction);
/* Do some transactional work here, then: */
scope.Complete();
}

The client code creates a transactional scope that also sets the ambient transaction. You should not pass
the ambient transaction to the worker thread. Instead, you should clone the current (ambient) transaction
by calling theDependentClone method on the current transaction, and pass the dependent to the worker
thread.
The ThreadMethod method executes on the new thread. The client starts a new thread, passing the
dependent transaction as the ThreadMethod parameter.
Because the dependent transaction is created with BlockCommitUntilComplete, you are guaranteed that
the transaction cannot be committed until all of the transactional work done on the second thread is
finished andComplete is called on the dependent transaction. This means that if the client's scope ends
(when it tries to dispose of the transaction object at the end of the using statement) before the new thread
calls Complete on the dependent transaction, the client code blocks until Complete is called on the
dependent. Then the transaction can finish committing or aborting.

Concurrency Issues
There are a few additional concurrency issues that you need to be aware of when using
the DependentTransaction class:
 If the worker thread rolls back the transaction but the parent tries to commit it,
a TransactionAbortedException is thrown.
 You should create a new dependent clone for each worker thread in the transaction. Do not pass
the same dependent clone to multiple threads, because only one of them can call Complete on it.
 If the worker thread spawns a new worker thread, make sure to create a dependent clone from the
dependent clone and pass it to the new thread.

Securing XML Web Services


Created Using ASP.NET
Deciding which security implementation is best for a Web service begins with looking at two key security
principles: authentication and authorization. Authentication is the process of validating an identity based on
credentials, such as a user name and password, against an authority. When an identity has been
authenticated, authorization determines whether the identity is authorized to access a resource.
Web services created using ASP.NET can choose their security options from the authentication and
authorization options offered by ASP.NET or customized SOAP-based security. ASP.NET operates in
conjunction with Internet Information Services (IIS) to provide several authentication and authorization
options. It is also possible to create custom authentication options, such as the use of SOAP headers.
Additionally, ASP.NET offers the ability, known as impersonation, to execute a request using the client
credentials. For more information about using impersonation, see ASP.NET Impersonation.
This topic summarizes the authentication and authorization options available to Web services built using
ASP.NET. For more information about security options available to ASP.NET Web applications, see Securing
ASP.NET Web Applications and Building Secure ASP.NET Applications: Authentication, Authorization, and
Secure Communication.
For more information about accessing remote resources from ASP.NET-based applications, see the
"Impersonation/Delegation Model" and "Trusted Subsystem Model" topics in Chapter 3 of Building Secure
ASP.NET Applications.

Authentication Options for XML Web Services


Web services created using ASP.NET have several options for authenticating clients, so the big question is:
Which one is right for a specific Web service? In choosing the right security option, one of the things a
developer has to choose between is the level of security and performance. For some Web services, it is
critical that client credentials are sent over the network using encryption, so an algorithm that encrypts the
client credentials is essential. For example, a developer writing a Web service that processes credit cards
probably worries more about the client credentials being stolen than the extra overhead of encrypting the
credit card data.
The following table is a summary of the authentication options available to Web services built using
ASP.NET. Options prefixed with Windows are a part of the Microsoft Windows authentication options
available to Web services created using ASP.NET.
Summary of Authentication Options

Authenticatio
Description
n option

Windows - Use for non-secure identification of clients, as the user name and
Basic password are sent in base 64-encoded strings in plain text. Passwords
and user names are encoded, but not encrypted, in this type of
authentication. A determined, malicious user equipped with a
network-monitoring tool can intercept user names and passwords.

Windows - Use for secure identification of clients in Internet scenarios. The user
Basic over name and password are sent over the network using Secure Sockets
SSL Layer (SSL) encryption, rather than plain text. This is relatively easy
to configure and works for Internet scenarios. However, using SSL
degrades performance.

Windows - Use for secure identification of clients in Internet scenarios. Uses


Digest hashing to transmit client credentials in an encrypted manner so the
password is not transmitted in clear text. In addition, Digest
authentication can work through proxy servers. However, it is not
widely supported on other platforms.

Windows - Uses NTLM or Kerberos. Uses a cryptographic exchange with the


Integrated user's Microsoft Internet Explorer Web browser.
Windows
Windows - Use for secure identification of clients in Internet and intranet
Client scenarios. Requires each client to obtain a certificate from a mutually
Certificates trusted certificate authority. Certificates are optionally mapped to
user accounts, which are used by IIS for authorizing access to the
Web service.

Forms Not supported by Web services. This is a system by which


unauthenticated requests are redirected to an HTML form using
HTTP client-side redirection. Most clients of Web services will not
want to provide credentials using a UI; you must work around this if
you want to use forms authentication.

SOAP Useful for both secure and non-secure Internet scenarios. User
headers – credentials are passed within the SOAP header of the SOAP
Custom message. The Web server, regardless of the platform hosting the
Web service, provides a custom authentication implementation.
For all options listed above, except the use of SOAP headers, the security settings are specified using a
combination of configuration files and IIS. The custom SOAP headers option is detailed following the
Authorization section, as that solution involves both authentication and authorization.
Windows Authentication
Both IIS and ASP.NET provide support for authenticating Web applications, including Web services, using
security built in to Windows. Windows provides three options for authentication: Basic, Digest, and
Integrated Windows. Additionally, each option can be used with SSL. As all Windows authentication options
except Basic encrypt the data in some form, the additional level of encryption offered by SSL is typically
only used in conjunction with Basic or Client Certificates.
Regardless of which Windows authentication option is used, the procedures for setting up both the Web
service and Web service client are similar. For more information, see How to: Configure an XML Web Service
for Windows Authentication. No code needs to be added to a Web service to use Windows authentication,
as the authentication options are set in a configuration file and IIS. Code to pass the client credentials to the
Web service must be added to a Web service client.
If SSL is chosen as part of the authenticating mechanism used by a Web service, SSL needs to be configured
for the Web application hosting the Web service or for the Web service itself, using IIS. The service
description and, consequently, proxy classes generated from the service description will reflect that the
Web service uses SSL (if the service description and service help page are accessed using SSL). The URL to
the Web service within the service description will be prefixed with https. For more information about
setting up SSL, see the IIS documentation.
Client Certificate Authentication
Client Certificates help provide a secure mechanism for authentication, as clients are required to send an
electronic document, called a client certificate, identifying a client using an SSL connection to the Web
server. The SSL connection encrypts the client credentials contained within the client certificate as they are
sent over the network. Communication between the client and the Web server is encrypted using a
combination of the encryption keys sent by the client and keys provided by the Web server. Once the
communication is established, only the client and server computers can communicate to each other using
that SSL connection.
A client certificate can be obtained from a certificate authority, which can either be the Web server itself or
a trusted intermediary between the client and server. Once a certificate has been obtained, and the Web
server has been configured to accept client certificates, a client can send the client certificate to the Web
server over an SSL connection, when a Web service is called. For more information about client certificates,
see the IIS documentation. For more information about setting up Client Certificate authentication for a
Web service, see How to: Configure an XML Web Service for Windows Authentication.
Authorization Options for XML Web Services
The purpose of authorization is to determine whether an identity should be granted the requested type of
access to a given resource. There are two fundamental ways to authorize access to a given resource: file
authorization and URL authorization. File authorization can be used whenever Windows authentication is
used, as the permissions are set in IIS on a per-file basis. URL authorization can be used with any of the
built-in authentication mechanisms supported by ASP.NET. With URL authorization, configuration is done
through a configuration file, where users can be selectively granted or denied access to any files associated
with ASP.NET, including .asmx files.
For more information about setting up authorization on a per-file basis, see the IIS documentation.
For more information about setting up authorization using a configuration file, see ASP.NET Authorization.
Custom Authentication Using SOAP Headers
The Windows authentication mechanisms, including client certificates, rely on the HTTP transport, whereas
SOAP is transport-independent. Web services built using ASP.NET use SOAP over HTTP, as well as HTTP-
POST and HTTP-GET implementations that return non-SOAP XML documents. So, one reason to create a
custom authentication mechanism is to decouple authentication from the transport. This can be
accomplished by passing the authentication credentials in the SOAP header.
SOAP headers are a great way of passing out-of-band or information not related to the semantics of a Web
service. Unlike the Body element of a SOAP message, which includes the in and out parameters for the
Web service operation that are processed by the Web service method, the  Header element is optional and
can thus be processed by the infrastructure. That is, processed by infrastructure developed to provide a
custom authentication mechanism.
For a description of one method of using SOAP headers for authentication, see How to: Perform Custom
Authentication Using SOAP Headers.
To use SOAP headers for authentication, a Web service client would send its credentials to the Web service
by adding the expected SOAP header to the SOAP request and populating it with the client credentials. To
use SOAP header authentication, a Web service must do two things: specify that it expects the SOAP header
containing the authentication credentials and authorize the client access to the Web service.

How to: Configure an XML


Web Service for Windows
Authentication
Follow these procedures to configure and pass client credentials to a Web service using all forms of
Windows authentication except Client Credentials. For that case, follow the procedures in the Client
Certificate Authentication section.

To configure a Web service for Windows


authentication
1. Configure the Web service to use Windows authentication, using IIS.
IIS allows you to specify security at either the directory or file level. If you want to specify the
security for a Web service on a per-file basis, set the permissions for the Web service on the .asmx
file in IIS. The .asmx file is the entry point into the Web service. See the IIS documentation for
details.
2. Modify the configuration file to specify Windows authentication.
Set the mode attribute of the authentication XML element in a configuration file to "Windows".
The following code example modifies a configuration file to use Windows authentication.
// Fragment of a Web.config file.
<authentication mode= "Windows">
</authentication>

To pass client credentials to a Web service


using Windows authentication
1. Create a new instance of the proxy class to the Web service. If a proxy class has not been
generated, see Creating an XML Web Service Proxy for details
2. Create a new instance of the NetworkCredential class, setting
the UserName, Password and Domain properties.
3. Create a new instance of CredentialCache.
4. Add the NetworkCredential to the CredentialCache using the Add method of CredentialCache
5. Assign the instance of CredentialCache to the Credentials property of the proxy class.
If Integrated Windows authentication is used, then you must set the Credentials property
to System.Net.CredentialCache.DefaultCredentials.
When the Credentials property is set to DefaultCredentials then the client negotiates with the
server to do Kerberos and/or NTLM authentication depending on how the server is configured.
6. The following code example sets the client credentials passed to a Web service method using
Windows authentication.

Client Certificate Authentication


Follow these procedures to configure and pass client credentials to a Web service using the Client
Credentials form of Windows authentication.
To configure a Web service for Client Certificate authentication
1. The following list is an overview of how to configure IIS to authenticate clients using client
certificates. For details, see the IIS documentation.
2. Install SSL.
3. Configure the Web application to accept client certificates.
4. Modify the configuration file to specify Windows authentication for the Web service.
Set the mode attribute of the authentication XML element in a configuration file to "Windows".
The following code example modifies a configuration file to use Windows authentication.
// Fragment of a Web.config file.
<authentication mode= "Windows">
</authentication>
To pass client credentials to a Web service using Client Certificate authentication
1. Create a new instance of the proxy class to the Web service. If a proxy class has not been
generated, see Creating an XML Web Service Proxy for details.
2. Create a new instance of the X509Certificate.
3. Invoke the CreateFromCertFile method to load the client certificate from a file.
A client can obtain a client certificate file from a trusted certificate authority. For details, see the IIS
documentation.
4. Add the X509Certificate to the ClientCertificates ClientCertificates collection of the proxy class.
The following code example demonstrates how a Web service client passes its credentials using a
client certificate. A client certificate issued from the Web server is loaded from a file with
the CreateFromCertFilemethod and then added to the ClientCertificates property of the proxy
class.

VB
' Instantiate proxy class to a Bank Web service.
Dim bank As BankSession = new BankSession()

' Load the client certificate from a file.


Dim x509 As X509Certificate =
X509Certificate.CreateFromCertFile("c:\user.cer")

' Add the client certificate to the ClientCertificates property


' of the proxy class.
bank.ClientCertificates.Add(x509)

' Call the method on the proxy class, which requires authentication
' using client certificates.
bank.Deposit(500)

C#

// Instantiate proxy class to a Bank Web service.


BankSession bank = new BankSession();

// Load the client certificate from a file.


X509Certificate x509 =
X509Certificate.CreateFromCertFile(@"c:\user.cer");

// Add the client certificate to the ClientCertificates property


// of the proxy class.
bank.ClientCertificates.Add(x509);

// Call the method on the proxy class, which requires


// authentication using client certificates.
bank.Deposit(500);

Example
When the Credentials property is set to System.Net.CredentialCache.DefaultCredentials then the client
negotiates with the server to do Kerberos and/or NTLM authentication depending on how the server is
configured.
The following code example sets the client credentials passed to a Web service method using Windows
authentication.
C#

VB

using System;
using System.Web.Services.Protocols;
using System.Net;
using MyMath;

public class Calculator


{
public static void Main()
{
// Create a new instance of the proxy class to an XML
// Web service method.
MyMath.Math math = new MyMath.Math();
// Create a new instance of CredentialCache.
CredentialCache credentialCache = new CredentialCache();

// Create a new instance of NetworkCredential using the client


// credentials.
NetworkCredential credentials = new
NetworkCredential(UserName,SecurelyStroredPassword,Domain);

// Add the NetworkCredential to the CredentialCache.


credentialCache.Add(new Uri(math.Url),
"Basic", credentials);

// Add the CredentialCache to the proxy class credentials.


math.Credentials = credentialCache;

// Call the method on the proxy class.


int result = math.Add(3,5);
}
}

How to: Perform Custom


Authentication Using SOAP
Headers
This topic is specific to a legacy technology. XML Web services and XML Web service clients should
now be created using Windows Communication Foundation .

The following custom solution is built using ASP.NET to provide an authentication mechanism using SOAP
headers. The solution involves a custom IHttpModule on the Web server that executes the following steps:

1. The HTTP Module parses HTTP messages to check whether they are SOAP messages.

2. If the HTTP Module detects a SOAP message, it reads the SOAP headers.

3. If the SOAP message has the SOAP header with authentication credentials, HTTP Module raises a
custom global.asax event.

In the sample provided, the HTTP Module authenticates the user and sets Context properties that a Web
service can use to decide whether the client is authorized access to the Web service.

Note:

In this sample, the text is sent over the network in clearly readable text (it is not encrypted). If
clear text is not secure enough for your application, add an encryption algorithm.
Example
The following code example is an HTTP Module that parses HTTP messages for SOAP requests. If the HTTP
message is a SOAP message, the custom WebServiceAuthenticationEvent is raised.
C#

VB

using System;
using System.Web;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.Web.Services.Protocols;

namespace Microsoft.WebServices.Security {

public sealed class WebServiceAuthenticationModule : IHttpModule


{
private WebServiceAuthenticationEventHandler
_eventHandler = null;

public event WebServiceAuthenticationEventHandler Authenticate


{
add { _eventHandler += value;}
remove {_eventHandler -= value;}
}

public void Dispose()


{
}

public void Init(HttpApplication app)


{
app.AuthenticateRequest += new
EventHandler(this.OnEnter);
}

private void OnAuthenticate(WebServiceAuthenticationEvent e)


{
if (_eventHandler == null)
return;

_eventHandler(this, e);
if (e.User != null)
e.Context.User = e.Principal;
}

public string ModuleName


{
get{ return "WebServiceAuthentication"; }
}

void OnEnter(Object source, EventArgs eventArgs) {


HttpApplication app = (HttpApplication)source;
HttpContext context = app.Context;
Stream HttpStream = context.Request.InputStream;

// Save the current position of stream.


long posStream = HttpStream.Position;

// If the request contains an HTTP_SOAPACTION


// header, look at this message.
if (context.Request.ServerVariables["HTTP_SOAPACTION"]
== null)
return;

// Load the body of the HTTP message


// into an XML document.
XmlDocument dom = new XmlDocument();
string soapUser;
string soapPassword;

try
{
dom.Load(HttpStream);

// Reset the stream position.


HttpStream.Position = posStream;

// Bind to the Authentication header.


soapUser =
dom.GetElementsByTagName("User").Item(0).InnerText;
soapPassword =
dom.GetElementsByTagName("Password").Item(0).InnerText;
}
catch (Exception e)
{
// Reset the position of stream.
HttpStream.Position = posStream;

// Throw a SOAP exception.


XmlQualifiedName name = new
XmlQualifiedName("Load");
SoapException soapException = new SoapException(
"Unable to read SOAP request", name, e);
throw soapException;
}

// Raise the custom global.asax event.


OnAuthenticate(new WebServiceAuthenticationEvent
(context, soapUser, soapPassword));
return;
}
}
}

The following code example is the custom authentication event that is raised by the  HTTP Module, if a
SOAP request is received.
C#

VB

namespace Microsoft.WebServices.Security {
using System;
using System.Web;
using System.Security.Principal;

public class WebServiceAuthenticationEvent : EventArgs {


private Iprincipal _IPrincipalUser;
private HttpContext _Context;
private string _User;
private string _Password;

public WebServiceAuthenticationEvent(HttpContext context)


{
_Context = context;
}

public WebServiceAuthenticationEvent(HttpContext context,


string user, string password)
{
_Context = context;
_User = user;
_Password = password;
}
public HttpContext Context
{
get { return _Context;}
}
public IPrincipal Principal
{
get { return _IPrincipalUser;}
set { _IPrincipalUser = value;}
}
public void Authenticate()
{
GenericIdentity i = new GenericIdentity(User);
this.Principal = new GenericPrincipal(i, new String[0]);
}
public void Authenticate(string[] roles)
{
GenericIdentity i = new GenericIdentity(User);
this.Principal = new GenericPrincipal(i, roles);
}
public string User
{
get { return _User; }
set { _User = value; }
}
public string Password
{
get { return _Password; }
set { _Password = value; }
}
public bool HasCredentials {
get
{
if ((_User == null) || (_Password == null))
return false;
return true;
}
}
}
}

The following code example is the delegate for the custom WebServiceAuthenticationEvent event.


C#

VB

namespace Microsoft.WebServices.Security
{
using System;

public delegate void WebServiceAuthenticationEventHandler(Object sender,


WebServiceAuthenticationEvent e);
}
The following code example is a Web service that defines the Authentication SOAP header that a
client must pass. The Web service does not have to do the authentication. Rather, it can inspect
theUser.Identity.IsAuthenticated property to determine if the HTTP Module has authenticated the user.
C#

VB

<%@ WebService Language="C#" Class="SecureWebService" %>

using System;
using System.Web.Services;
using System.Web.Services.Protocols;

public class Authentication : SoapHeader {


public string User;
public string Password;
}

public class SecureWebService : WebService{


public Authentication authentication;

[WebMethod]
[SoapHeader("authentication")]
public string ValidUser(){
if (User.IsInRole("Customer"))
return "User is in role customer";

if (User.Identity.IsAuthenticated)
return "User is a valid user";
return "not authenticated";
}
}
The following code example is a Web service client that passes the necessary credentials for a custom SOAP
header authentication mechanism within an Authentication SOAP header.
C#

VB

// Create a new instance of a Web service proxy class.


SecureWebService s = new SecureWebService();

// Create the Authentication SOAP header and set values.


Authentication a = new Authentication();
a.User = user.Value;
a.Password = password.Value;

// Assign the Header.


s.AuthenticationValue = a;

string result = s.ValidUser();


span1.InnerHtml = result;

How to: Create Web Services


That Parse the Contents of a
Web Page
Web services created using ASP.NET provide an HTML parsing solution that enables developers to parse
content from a remote HTML page and programmatically expose the resulting data. For a detailed
explanation, seeHTML Parsing by ASP.NET XML Web Services.

To specify an operation and input parameters


1. Create a Web Services Description Language (WSDL) document, which is typically saved with the
file name extension .wsdl. The document's content must consist of valid XML according to the
WSDL schema. For a prototype, you can use a WSDL document dynamically generated for a Web
service running on ASP.NET. Make a request with a ?wsdl argument appended to the Web service
URL.
2. Specify the elements that define the operation each Web service method that parses HTML text.
This step and the next one require a knowledge of the WSDL format.
3. If the parsing method takes input parameters, specify the elements that represent those
parameters and associate them with the operation.

To specify the data returned from a parsed


HTML page
1. Add a namespace-qualified <text> XML element within the <output> element that appears via
the XPath /definitions/binding/operation/output. The <operation> element represents the Web
service method that retrieves parsed HTML.
Note:

The operation name inside a binding must be globally unique or Wsdl.exe can be run with the
namespace specified to prevent naming collisions caused by other WSDL files imported in the
same application.

1. Add <match> XML elements in the service description within the <text> XML element for each
piece of data you want to return from the parsed HTML page.

2. Apply attributes to the <match> element. The valid attributes are presented in a table under the
topic HTML Parsing by ASP.NET XML Web Services.

To generate client proxy code for the Web


service
1. Run the Wsdl.exe tool from the Windows® Software Development Kit (SDK). Pass the WSDL file
you created as an input.

Example
The following code example is a simple Web page sample containing <TITLE> and <H1> tags.
<HTML>
<HEAD>
<TITLE>Sample Title</TITLE>
</HEAD>
<BODY>
<H1>Some Heading Text</H1>
</BODY>
</HTML>
The following code example is a service description that parses the contents of the HTML page, extracting
the contents of the text within the <TITLE> and <H1> tags. In the code example,
a TestHeaders method is defined for the GetTitleHttpGet binding. The TestHeaders method
defines two pieces of data that can be returned from the parsed HTML page in <match> XML
elements: Title and H1, which parse the contents of the <TITLE> and <H1> tags, respectively.
<?xml version="1.0"?>
<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s0="http://tempuri.org/"
targetNamespace="http://tempuri.org/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema targetNamespace="http://tempuri.org/"
attributeFormDefault="qualified"
elementFormDefault="qualified">
<s:element name="TestHeaders">
<s:complexType derivedBy="restriction"/>
</s:element>
<s:element name="TestHeadersResult">
<s:complexType derivedBy="restriction">
<s:all>
<s:element name="result" type="s:string" nullable="true"/>
</s:all>
</s:complexType>
</s:element>
<s:element name="string" type="s:string" nullable="true"/>
</s:schema>
</types>
<message name="TestHeadersHttpGetIn"/>
<message name="TestHeadersHttpGetOut">
<part name="Body" element="s0:string"/>
</message>
<portType name="GetTitleHttpGet">
<operation name="TestHeaders">
<input message="s0:TestHeadersHttpGetIn"/>
<output message="s0:TestHeadersHttpGetOut"/>
</operation>
</portType>
<binding name="GetTitleHttpGet" type="s0:GetTitleHttpGet">
<http:binding verb="GET"/>
<operation name="TestHeaders">
<http:operation location="MatchServer.html"/>
<input>
<http:urlEncoded/>
</input>
<output>
<text xmlns="http://microsoft.com/wsdl/mime/textMatching/">
<match name='Title' pattern='TITLE&gt;(.*?)&lt;'/>
<match name='H1' pattern='H1&gt;(.*?)&lt;'/>
</text>
</output>
</operation>
</binding>
<service name="GetTitle">
<port name="GetTitleHttpGet" binding="s0:GetTitleHttpGet">
<http:address location="http://localhost" />
</port>
</service>
</definitions>
The following code example is a portion of the proxy class generated by Wsdl.exe for the previous service
description.
C#

VB

' GetTitle is the name of the proxy class.


public class GetTitle : HttpGetClientProtocol
{
public TestHeadersMatches TestHeaders()
{
return ((TestHeadersMatches)(this.Invoke("TestHeaders",
(this.Url + "/MatchServer.html"), new object[0])));
}
}
public class TestHeadersMatches
{
public string Title;
public string H1;
}

HTML Parsing by ASP.NET


XML Web Services
Web services created using ASP.NET provide an HTML parsing solution that enables developers to parse
content from a remote HTML page and programmatically expose the resulting data. For a detailed
explanation, seeHTML Parsing by ASP.NET XML Web Services.

To specify an operation and input parameters


1. Create a Web Services Description Language (WSDL) document, which is typically saved with the
file name extension .wsdl. The document's content must consist of valid XML according to the
WSDL schema. For a prototype, you can use a WSDL document dynamically generated for a Web
service running on ASP.NET. Make a request with a ?wsdl argument appended to the Web service
URL.
2. Specify the elements that define the operation each Web service method that parses HTML text.
This step and the next one require a knowledge of the WSDL format.
3. If the parsing method takes input parameters, specify the elements that represent those
parameters and associate them with the operation.

To specify the data returned from a parsed


HTML page
1. Add a namespace-qualified <text> XML element within the <output> element that appears via
the XPath /definitions/binding/operation/output. The <operation> element represents the Web
service method that retrieves parsed HTML.

Note:

The operation name inside a binding must be globally unique or Wsdl.exe can be run with the namespace spe
application.

1. Add <match> XML elements in the service description within the <text> XML element for each
piece of data you want to return from the parsed HTML page.

2. Apply attributes to the <match> element. The valid attributes are presented in a table under the
topic HTML Parsing by ASP.NET XML Web Services.
To generate client proxy code for the Web
service
1. Run the Wsdl.exe tool from the Windows® Software Development Kit (SDK). Pass the WSDL file
you created as an input.

Example
The following code example is a simple Web page sample containing <TITLE> and <H1> tags.
<HTML>
<HEAD>
<TITLE>Sample Title</TITLE>
</HEAD>
<BODY>
<H1>Some Heading Text</H1>
</BODY>
</HTML>
The following code example is a service description that parses the contents of the HTML page, extracting
the contents of the text within the <TITLE> and <H1> tags. In the code example,
a TestHeaders method is defined for the GetTitleHttpGet binding. The TestHeaders method
defines two pieces of data that can be returned from the parsed HTML page in <match> XML
elements: Title and H1, which parse the contents of the <TITLE> and <H1> tags, respectively.
<?xml version="1.0"?>
<definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s0="http://tempuri.org/"
targetNamespace="http://tempuri.org/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema targetNamespace="http://tempuri.org/"
attributeFormDefault="qualified"
elementFormDefault="qualified">
<s:element name="TestHeaders">
<s:complexType derivedBy="restriction"/>
</s:element>
<s:element name="TestHeadersResult">
<s:complexType derivedBy="restriction">
<s:all>
<s:element name="result" type="s:string" nullable="true"/>
</s:all>
</s:complexType>
</s:element>
<s:element name="string" type="s:string" nullable="true"/>
</s:schema>
</types>
<message name="TestHeadersHttpGetIn"/>
<message name="TestHeadersHttpGetOut">
<part name="Body" element="s0:string"/>
</message>
<portType name="GetTitleHttpGet">
<operation name="TestHeaders">
<input message="s0:TestHeadersHttpGetIn"/>
<output message="s0:TestHeadersHttpGetOut"/>
</operation>
</portType>
<binding name="GetTitleHttpGet" type="s0:GetTitleHttpGet">
<http:binding verb="GET"/>
<operation name="TestHeaders">
<http:operation location="MatchServer.html"/>
<input>
<http:urlEncoded/>
</input>
<output>
<text xmlns="http://microsoft.com/wsdl/mime/textMatching/">
<match name='Title' pattern='TITLE&gt;(.*?)&lt;'/>
<match name='H1' pattern='H1&gt;(.*?)&lt;'/>
</text>
</output>
</operation>
</binding>
<service name="GetTitle">
<port name="GetTitleHttpGet" binding="s0:GetTitleHttpGet">
<http:address location="http://localhost" />
</port>
</service>
</definitions>
The following code example is a portion of the proxy class generated by Wsdl.exe for the previous service
description.
C#

VB

' GetTitle is the name of the proxy class.


public class GetTitle : HttpGetClientProtocol
{
public TestHeadersMatches TestHeaders()
{
return ((TestHeadersMatches)(this.Invoke("TestHeaders",
(this.Url + "/MatchServer.html"), new object[0])));
}
}
public class TestHeadersMatches
{
public string Title;
public string H1;
}

How to: Enable Output Caching on a Web


Service Client
The following code example demonstrates how to use the Duration property on the client application
to specify output caching for a period of 60 seconds. 

Example
C#

VB

<%@ Page Language="C#" %>


<%@ Import Namespace="System.Net" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>
<html>
<script language="C#" runat="server">
void EnterBtn_Click(Object Src, EventArgs e)
{
MyMath.Math math = new MyMath.Math();
// Call the Web service.
float total = math.Add(Convert.ToInt32(Num1.Text),
Convert.ToInt32(Num2.Text));
// Display the results in a Label control.
Total.Text = "Total: " + total.ToString();
}
</script>
<body>
<form action="MathClient.aspx" runat=server>
<font face="Verdana">
Enter the two numbers you want to add and press
the Total button.
<p>
Number 1:
<asp:textbox id="Num1"
runat=server/>
+
Number 2:
<asp:textbox id="Num2"
runat=server/>
=
<asp:button id="Total_Button"
text="Total"
OnClick="EnterBtn_Click"
runat=server/>
<p>
<asp:label id="Total" runat=server/>
</font>
</form>
</body>
</html>
How to: Enable Server-Side Output Caching
for a Web Service
The following code example demonstrates how to use the CacheDuration property on Web service
methods to specify output caching for a period of 60 seconds. This example illustrates one of the
guidelines explained in the topic, Design Guidelines for XML Web Services Created Using ASP.NET.

There are two issues that can affect output caching in an ASP.NET 2.0 Web service application.

In ASP.NET 2.0 the HTTP method of the test page has changed from GET to POST. However, POSTs are
not normally cached. If you change the test page in an ASP.NET 2.0 Web service application to use
GET, caching works properly.

In addition, HTTP indicates that a user agent (the browser or calling application) should be able to
override server caching by setting the "Cache-Control" to "no-cache". ASP.NET applications, therefore,
ignore cached results when they find a "no-cache" header.

Example
C#

VB

<%@ WebService Language="C#" Class="MathService" %>


using System;
using System.Web.Services;
public class MathService : WebService {
[WebMethod(CacheDuration=60)]
public float Add(float a, float b)
{
return a + b;
}
[WebMethod(CacheDuration=60)]
public float Subtract(float a, float b)
{
return a - b;
}
[WebMethod(CacheDuration=60)]
public float Multiply(float a, float b)
{
return a * b;
}
[WebMethod(CacheDuration=60)]
public float Divide(float a, float b)
{
if (b==0) return -1;
return a / b;
}
}

Interview Questions

1. What are Windows services?

Windows services, previously known as NT services, are applications that are installed on the system as
system services. In other words, Windows services are applications that run in the background with the
Windows operating system. The primary use of Windows services is to reduce the consumption of
memory required for performing backend operations. Let's take an example to understand this easily.
Suppose you want to perform a variety of functions, such as monitor the performance of your computer
or application, check the status of an application, and manage various devices, such as printers. 

In such a case, you can use Windows services to reduce memory consumption. In addition, Windows
services can run on your system even if you have not logged on to your computer. In addition, these
services do not have any user interface.

2. Can you share a process between Windows services?

Yes, you can share a process between Windows services.

3. In .NET, which is the parent class to create all Windows services?

The ServiceBase class is the parent class to create all Windows services.

4. Which class in .NET is used to install a Windows service?

The ServiceInstaller class, also known as the project installer class, is used to install a Windows
service.

5. While installing a Windows service, an EventLogInstaller class is automatically created


to install the event log related to the particular service. Is it true?

Yes, it is true.

6. Which property of the ServiceBase class can be used to specify whether a service can be


paused and resumed?

The CanPauseAndContinue property provides such type of service.

7. Describe the services that UDDI provides to Web applications.

UDDI provides the following types of services to a Web application:

 XML Schema for business descriptions - Includes information about the service publisher
(contact name, address, and so on) and specifications on the Web service
 Web registry of Web services - Includes business, service, and binding information for the Web
service
8. Write the file extension for a Web service.

A Web service file extension is .asm file. For example, service1.asmx is a Web service file.

9. Which method is used to uninstall the Windows services?

The Uninstall() method is used to uninstall the Windows services.

10. What is the use of the mustUnderstand attribute in the Header element of a SOAP


message?

The mustUnderstand attribute indicates that a header entry is either required or optional for the
recipient to process further.

11. Explain the WSDL.

WSDL is a short form for Web Services Description Language, which is used to describe a Web service in
terms of the messages that it creates and accepts. The WSDL document is an XML file that contains the
interface schema for the Web service. It identifies the methods that are used during the exchange
between a Web service consumer and a Web service provider. The following are the elements contained
in the WSDL document:

 Types - Describe the variations of data types that are used to exchange messages between the
user and the provider.
 Message - Describes the actual message or method call.
 portType - Describes the set of operations and each related message.
 binding - Describes the protocol details.
 service - Used to make groups a set of related ports together.

12. What advantage UDDI has over DISCO?

The UDDI directory has an advantage over a DISCO file, as it provides a single location where a client
can find the Web services offered by different organizations.

13. How can you ensure that only authorized users access your Web service?

You should use the <authorization> element to ensure that only authorized users access your Web
service. This element allows or denies access to your Web service according to their role.

14. Describe the EventLog class.

The EventLog class is used to access the Windows event logs from Windows services. Using EventLog,
you can also customize Windows event logs that record information about important software and
hardware events, such as the events of the .NET controls, keyboard, or other hardware devices. 

The EventLog class allows you to read or write to event logs, delete logs, and create as well as delete
event sources. You can use the EventLog class to create event logs while creating an event source. An
event source can be used to write to only one event log at a particular time. However, it is possible to
associate one event log to multiple sources.

15. How can you prevent your Web services from unauthorized access?

The following are the ways to prevent your Web service from unauthorized access:

 Using encryption and message-based security.


 Using authentication and access controls for the Web service.

16. Explain the concept of Web services in brief.

A Web service may be defined as an independent and self-sustained unit of a software application that is
hosted on the Web and implement specific functionalities to execute the business logic. A Web service
provides so many functionalities, such as generating pay slips for employees, computing tax,
broadcasting weather report, and providing updated news. The Web service allows application to share
information or exchange data with other applications across different operating systems and hardware.  

Therefore, the work of a Web service is to unite software by exchanging data irrespective of their
operating systems, supported hardware, and programming language used in their development. The
Web services transfer data in the XML format and use Simple Object Access Protocol (SOAP) to
communicate. It is an XML based protocol. The Web services use Web Services Description Language
(WSDL) and Universal Description, Discovery, and Integration (UDDI) to describe itself.

17. What advantages have Web services over Component Object Model (COM) and Distributed
Component Object Model (DCOM)?

The advantages of Web services over COM and DCOM are as follows:

 Web services are simple to use and can be implemented on varied platforms.
 Web services are loosely coupled; as a result, their interfaces and methods can be extended.
 Web services do not carry any state information with them so that multiple requests can be
processed simultaneously.

18. Mention the namespace that you must import in code to build a Web service.

System.Web.Services is the elementary namespace, which must be imported to develop code of a


Web service.

19. What does the portType element of a WSDL document contain?

The portType element contains the operations exposed by the Web service, and the messages involved
in the communication between the Web service and its consumers.

20. What is DISCO?

DISCO is a technology developed by Microsoft to publish and discover Web services. It discovers URLs of
all XML Web services located on a Web server and creates a list of these Web services in a file called as
a DISCO file.

21. Which two methods are used to discover the URL of Web services?

The two methods to discover the URL of Web services are Web service discovery tool ( Disco.exe)
and UDDI.

22. Which step is necessary to perform before a Web service can be consumed?

It is necessary to build a proxy class by using the wsdl.exe utility before a Web service can be
consumed.

23. Which property of the WebMethod attribute allows you to maintain the state of objects
across sessions in a Web method?
The WebMethod attribute's EnableSession property enables you to enable session state for a Web
method.

24. Write the names of public properties defined in the WebService class.

There are many properties defined in the WebServices class:

 Application - Obtains the application object for the current HTTP request
 Context - Obtains the HttpContext object for the current request, which encapsulates all
HTTP-specific context used by the HTTP server to process Web requests
 Server - Obtains the HttpServerUtility object for the current request
 Session - Obtains the HttpSessionState object for the current request
 SoapVersion - Obtains the version of the SOAP protocol used to make the SOAP request to a
Web service
 User - Obtains the Server User Object. This property can be used to authenticate whether a
user is authorized to execute the request.

25. What do you understand by SOAP encoding?

The Serialization of the types, such as integers and strings, inside a SOAP message is called encoding.
The SOAP objects use XML elements and attributes to serialized data, for example, encodingStyle is
an attribute of theEnvelop element, which is used to specify the encoding rules for a SOAP object.

26. What is the use of a .disco file?

A client application uses a .disco file to locate or discover the documents that contain the description
of a Web service. The .disco file contains links to other resources, which describe essential features,
such as capabilities of a Web service. The links contained in a .disco file can refer to other discovery
documents or XSD schemas. The description about the services and capabilities of a Web service is
written in Web services Description Language (WSDL). A .disco file can also contain the information
about other XML Web services that reside on the same or a different Web server.

27. Mention the name of the directory where it is necessary to locate the proxy file to use a
Web service.

The proxy file must be stored in the /bin directory. This directory is situated under the root directory of
the application.

28. Does a Web service have state?

The Web services do not have any technique to maintain state. However, it can access ASP.NET objects,
such as application and session if they extend from the WebService base class.

29. Which namespace must be included in a code that enables a XML Web service to write
events in an event log file?

The System.Diagnostics is the namespace, which must be included in a code to enable a Web


service for writing events in an event log file.

30. Which tool installs the DLL on your local computer and installs the Windows service in a
transactional manner?
The Installutil.exe tool.

Handling and Throwing


Exceptions in XML Web
Services
Exceptions thrown by a Web service method created using ASP.NET are sent back to the client in the form
of a SOAP fault. A SOAP fault is a Fault XML element within a SOAP message that specifies when an error
occurred. It may contain details such as the exception string and the source of the exception. For details on
SOAP faults, see the SOAP specification on the W3C Web site (http://www.w3.org/TR/SOAP).
Fortunately, both clients and Web services created using ASP.NET do not populate or parse the  Fault XML
element directly, but rather use the common design pattern for throwing and catching exceptions in the
.NET Framework. A Web service can throw either a generic SoapException or an exception specific to the
problem, such as an ArgumentOutOfRangeException. Either way, ASP.NET serializes the exception into a
valid SOAP message by placing the exception into a SOAP Fault element. When the SOAP message is
deserialized on an ASP.NET client, the SOAP fault is converted to a SoapException exception, with the
exception details placed in theMessage property. A client can thus set up a try/catch block to catch
a SoapException. A code example of a Web service throwing an exception is provided in How to: Throw
Exceptions from a Web Service Created Using ASP.NET. A code example of a Web service client catching an
exception is provided in How to: Handle Exceptions Thrown by a Web Service Method.
A Web application can be comprised of multiple Web services. However, the Application_Error event
within the Global.asax Syntax file cannot be used for global exception handling. The HttpHandler for Web
services consumes any exception that occurs while a Web service is executing and turns it into a SOAP fault
before the Application_Error event is called. Build a SOAP extension to process Web service exceptions in
a global exception handler. A SOAP extension can check for the existence of an exception in
the ProcessMessage method. Within the ProcessMessage method, check the Exception property of
the SoapMessage passed when theStage property is set to AfterSerialize. For details on SOAP extensions,
see SOAP Message Modification Using SOAP Extensions.

Throwing Exceptions from a Web Service


Created Using ASP.NET
Propagating errors back to a client is done by throwing exceptions. A Web service method can do this in
the following ways:

 Throw a SoapException exception.

 Throw a SoapHeaderException exception.

 Throw an exception specific to the problem.

 Allow ASP.NET to throw the exception.

The following table describes the exceptions a Web service can explicitly throw and how an ASP.NET client
receives each exception:
What a Web service can do, what a
Type of exception thrown
client receives

Exception other A Web service method detects an


thanSoapException orSoapHeaderExceptio exception case and throws the
n specific exception, such
as ArgumentOutOfRangeException.
A .NET Framework client receives
a SoapException with the details
serialized into text in
the Message property.

SoapException A Web service method detects an


exception case and throws
a SoapException. It also provides
additional details regarding the
problem. The Web service method
populates the Detailproperty to
provide this additional information.
A .NET Framework client receives
the SoapException with the
additional information.

SoapHeaderException A Web service method detects an


exception case while processing a
SOAP Header element. The Web
service method throws
a SoapHeaderException, which
translates into a Fault element placed
inside the
response's Header element. The fault
must appear in the response header in
this situation according to the SOAP
specification. A .NET Framework
client receives
theSoapHeaderException.
You should throw an exception that is specific to the problem or provide extra details to
a SoapException or SoapHeaderException, as described in the preceding table.

Exceptions Not Handled by an XML Web


Service Method
If a Web service method does not catch an exception that occurs within the method, the following table
outlines how the exception is handled by ASP.NET.

When What ASP.NET does


unhandled
exception
occurs

While The exception is caught by ASP.NET and thrown back to the client.
executing The Web service client created using the .NET Framework receives
the Web a SoapException with the exception details placed in
service the Message property.
method

While ASP.NET throws a SoapHeaderException. A Web service client


processing created using the .NET Framework receives
SOAP the SoapHeaderException.
headers

How to: Define and Process


SOAP Headers
Web services created using ASP.NET can define and manipulate SOAP headers. Defining a SOAP header is
accomplished by defining a class representing the data in a particular SOAP header and deriving it from
theSoapHeader class.

To define a class representing a SOAP header


1. Create a class deriving from the SoapHeader class with a name matching the root element for the
SOAP header.

C#

public class MyHeader : SoapHeader

VB

Public Class MyHeader : Inherits SoapHeader


2. Add public fields or properties, matching the names and their respective data types for each
element in the SOAP header.
For instance, given the following SOAP header, the class following it defines a class representing
the SOAP header.

C#

<soap:Header xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<MyHeader xmlns="http://www.contoso.com">
<Created>dateTime</Expires>
<Expires>long</Expires>
</MyHeader>
</soap:Header>

public class MyHeader : SoapHeader


{
public DateTime Created;
public long Expires;
}

VB

Public Class MyHeader : Inherits SoapHeader


Public Created As DateTime
Public Expires As Long
End Class

To process SOAP headers within a Web service


1. Add a public member to the class implementing the Web service of the type representing the
SOAP header.

C#

[WebService(Namespace="http://www.contoso.com")]
public class MyWebService
{
// Add a member variable of the type deriving from SoapHeader.
public MyHeader timeStamp;

VB

<WebService(Namespace:="http://www.contoso.com")> _
Public Class MyWebService
' Add a member variable of the type deriving from SoapHeader.
Public TimeStamp As MyHeader
2. Apply a SoapHeader attribute to each Web service method that intends to process the SOAP
header. Set the MemberName property of the SoapHeader attribute to the name of the member
variable created in the first step.

C#

[WebMethod]
[SoapHeader("timeStamp")]
public void MyWebMethod()

VB

<WebMethod, SoapHeader("TimeStamp")> _
Public Sub MyWebMethod()
3. Within each Web service method that the SoapHeader attribute is applied to, access the member
variable created in the first step to process the data sent in the SOAP header.

C#

[WebMethod]
[SoapHeader("myHeaderMemberVariable")]
public string MyWebMethod()
{
// Verify that the client sent the SOAP Header.
if (timeStamp == null) timeStamp = new MyHeader();
// Set the value of the SoapHeader returned to the client.
timeStamp.Expires = 60000;
timeStamp.Created = DateTime.UtcNow;

return("Hello World!");
}

VB

<WebMethod,SoapHeader("TimeStamp", _
Direction:=SoapHeaderDirection.InOut)> _
Public Function MyWebMethod() As String
' Process the SoapHeader.
If (TimeStamp Is Nothing) Then
TimeStamp = New MyHeader
End If
TimeStamp.Expires = 60000
TimeStamp.Created = DateTime.UtcNow

Return "Hello World!"


End Function

Example
The following code example demonstrates how to define and process a SOAP header in a Web service
created using ASP.NET. The MyWebService Web service has a member variable
named myHeaderMemberVariable, which is of a type deriving from SoapHeader (MyHeader) and set
to the MemberName property of the SoapHeader attribute. In addition, a SoapHeader attribute is applied
to the MyWebMethod Web service method specifying myHeaderMemberVariable. Within
the MyWebMethod Web service method, myHeaderMemberVariable is accessed to get the value of
the Username XML element of the SOAP header.
C#

VB

<%@ WebService Language="C#" Class="MyWebService" %>


using System.Web.Services;
using System.Web.Services.Protocols;

// Define a SOAP header by deriving from the SoapHeader class.


public class MyHeader : SoapHeader
{
public DateTime Created;
public long Expires;
}

[WebService(Namespace="http://www.contoso.com")]
public class MyWebService
{
// Add a member variable of the type deriving from SoapHeader.
public MyHeader myHeaderMemberVariable;

// Apply a SoapHeader attribute.


[WebMethod]
[SoapHeader("myHeaderMemberVariable")]
public void MyWebMethod()
{
// Process the SoapHeader.
if (myHeaderMemberVariable.Username == "admin")
{
// Do something interesting.
}
}
}

In the previous example, if the SOAP request to the MyWebMethod has a MyHeader SOAP header with
a UserName element set to Admin, additional code is executed. That is, the following SOAP request
causes that code to execute.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<MyHeader xmlns="http://www.contoso.com">
<Created>dateTime</Created>
<Expires>long</Expires>
</MyHeader>
</soap:Header>
<soap:Body>
<MyWebMethod xmlns="http://www.contoso.com" />
</soap:Body>
</soap:Envelope>

How to: Build a Client That


Processes SOAP Headers
A Web services client can send and receive SOAP headers when communicating with a Web service. When a
proxy class is generated for a Web service expecting or returning SOAP headers using the Wsdl.exe utility,
the proxy class includes information about the SOAP headers. Specifically, the proxy class has member
variables representing the SOAP headers that correlate to those found in the Web service. The proxy class
also has definitions for the corresponding classes representing the SOAP header. For example, proxy classes
generated for the previous Web service will have a member variable of type MyHeader and a definition for
the MyHeaderclass. For details on creating a proxy class, see Creating an XML Web Service Proxy.
Note: If the Web service defines the member variables representing the SOAP headers of
type SoapHeader or SoapUnknownHeader instead of a class deriving from SoapHeader, a proxy class will
not have any information about that SOAP header.

To process SOAP headers within a Web service


client
1. Create a new instance of the class representing the SOAP header.

VB

Dim mySoapHeader As MyHeader = New MyHeader()

C#

MyHeader mySoapHeader = new MyHeader();


2. Populate the values for the SOAP header.

VB

mySoapHeader.Username = UserName
mySoapHeader.Password = SecurelyStoredPassword

C#

mySoapHeader.Username = Username;
mySoapHeader.Password = SecurelyStoredPassword
3. Create a new instance of the proxy class.

VB

Dim proxy As MyWebService = New MyWebService()

C#

MyWebService proxy = new MyWebService();


4. Assign the SOAP header object to the member variable of the proxy class representing the SOAP
header.

VB

proxy.MyHeaderValue = mySoapHeader

C#

proxy.MyHeaderValue = mySoapHeader
5. Call the method on the proxy class that communicates with the Web service method.
The SOAP header portion of the SOAP request sent to the Web service will include the contents of
the data stored in the SOAP header object.

VB

Dim results as String = proxy.MyWebMethod()

C#

string results = proxy.MyWebMethod();

Example
The following code example demonstrates how to pass a SOAP header from a client to a Web service.
C#

VB

<%@ Page Language="C#" %>

<asp:Label id="ReturnValue" runat="server" />


<script runat=server language=c#>

void Page_Load(Object o, EventArgs e)


{

MyHeader mySoapHeader = new MyHeader();

// Populate the values of the SOAP header.


mySoapHeader.Username = Username;
mySoapHeader.Password = SecurelyStoredPassword;

// Create a new instance of the proxy class.


MyWebService proxy = new MyWebService();

// Add the MyHeader SOAP header to the SOAP request.


proxy.MyHeaderValue = mySoapHeader;

// Call the method on the proxy class that communicates with


// your Web service method.
string results = proxy.MyWebMethod();

// Display the results of the method in a label.


ReturnValue.Text = results;
}
</script>
Building XML Web Service
Clients

Using a Web service encompasses the communication of Web service methods over a network using
industry standard protocols. However, before an application can begin communicating with Web service
methods, there are four basic steps it must accomplish:

1. Determine if a Web service exists. You can look in a directory, such as UDDI Services, for the
vendors that provide Web services with specific functionalities. The directory has a URL to the
vendor's Web site.

2. Discover a Web service. Given a URL to a vendor, Web service discovery is invoked to get the
specific details about each Web service that is available at that URL. Information about each Web
service is returned to the client in the form of a service description, which is an XML document that
describes the Web service in the Web Services Description Language (WSDL). The service
description concretely details how to communicate with a Web service. For information about Web
service discovery, see Web Service Discovery.

3. Given a service description, generate a proxy class, which can communicate with Web service
methods based on the precise definition in the service description. For instructions, see Creating an
XML Web Service Proxy. 

Because the proxy class communicates with the Web service across the Internet, it is a good idea to
verify that the Url property of the proxy class references a trusted destination. 

4. Create a client application, which invokes methods of the proxy class. The methods of the proxy
class can communicate with the Web service methods over the Internet, using industry standard
protocols. For more information, see Creating Clients for XML Web Services.

After discovering that a Web service exists using Web service discovery, you can view information about the
Web service and the Web service methods it implements in a more user-friendly format than the service
description. To do so, access the service help page described in How to: Explore Existing XML Web Services
Created Using ASP.NET.
Web services can be used by a variety of client applications. You can communicate with a Web service from
any Web application, including another Web service. The client of a Web service is not necessarily a client-
based application; in reality, most clients are server-based applications, such as Web Forms and other Web
services.
As shown in the previous graphic, there are two Web service clients: an ASP.NET Web Form and a Web
service. The ASP.NET Web Form, which the user sees, communicates with the  GetCurrentPrices Web
service. TheGetCurrentPrices Web service then acts as a Web service client by communicating with
the StockServices Web service to obtain the stock quote. The stock quote is then returned to
the GetCurrentPrices Web service, which subsequently passes it back to the ASP.NET Web Form.

How to: Explore Existing XML


Web Services Created Using
ASP.NET
Once you know the URL for a Web service created using ASP.NET, you can use the URL to access a Web
page known as the service help page. This page provides information about the functionality of the Web
service, including the Web service methods it implements, their parameters, and their return types. In
addition, you can use the service help page to test the functionality of the Web service.
For example, suppose you are accessing a Web service called Investor, which is used to retrieve the
stock price for a valid stock symbol. You know the base URL for this Web service is
http://www.contoso.com/Investor.asmx. Entering this URL into a browser with no extensions or parameters
produces a Web page with information about the Web service and the Web service methods it implements.
In addition to viewing information about the Web service in the browser, you can also obtain a more formal
definition of the Web service by viewing its service description, which is an XML document written in the
Web Services Description Language (WSDL). A link at the top of the service help page allows you to view
the service description. You can use the service description to manually generate a proxy class to the Web
service. For more information about creating a proxy class, see Creating an XML Web Service Proxy.

To access the service help page for a Web


service
1. In your browser's address bar, enter the base URL for the Web service, using the following format:
2. http://servername/vrootname/webservicename.asmx

Parameter Value

servername The Web server on which the Web service resides.

apppath The name of the Web application that is hosting the Web
service.

webservicename.asm The name of the file where the Web service is defined.
x
3. For example, to access a Web service called StockServices.asmx, residing on a Web server named
StockTicker, enter the following:
4. http://StockTicker/StockServices.asmx

To access the service description for a Web


service
1. Access the service help page for the Web service as just described.
2. Click the Service Description link at the top of the page.

How to: Access XML Web


Services from a Browser
After you publish a Web service created using ASP.NET, you can test its functionality by using a browser to
call it via either HTTP-GET or HTTP-POST. Access its .asmx file in a browser and then click hyperlinks to the
Web service methods, or access individual methods directly by appending a query string to the .asmx URL.

Note:

By default, a Web service created using ASP.NET is able to support multiple protocols, including SOAP over HTTP a
the response.

To test a Web service in a browser using HTTP-


GET
1. Deploy your Web service to a Web server. For more information, see XML Web Service Publishing
and Deployment.
2. Access a Web browser and enter the URL for your Web service in the address bar, using the
following format:
3. http://servername/apppath/webservicename.asmx

Path portion Value


Servername The name of the server on which your Web service was
deployed.

Apppath The name of your virtual directory and the rest of the Web
application path.

webservicename.asm The name of the Web service .asmx file.


x
4. For example, suppose you have published a Web service named StockServices. When
published, the base URL for this service is http://<servername>/apppath/StockServices.asmx. You
could test this service by entering this HTTP-GET request in the browser's address bar:
5. http://<servername>/apppath/StockServices.asmx
6. The server, in response to this request, displays the Web service's HTML description page.
7. The Web service's HTML description page shows you all the Web service methods supported by a
particular Web service. Link to the desired Web service method and enter the necessary
parameters to test the method and see the XML response.

To directly test a Web service method in a


browser using HTTP-GET
1. Deploy your Web service to a Web server. For more information, see XML Web Service Publishing
and Deployment.
2. Access a Web browser and enter the URL for your Web service method in the address bar, using
this format:
3. http://servername/vdir/webservicename.asmx/Methodname?parameter=value

Parameter Value

Servername The name of the server on which your Web service is


deployed.

Apppath The name of your virtual directory and the rest of the Web
application path.

webservicename.asm The name of the Web service .asmx file.


x

Methodname The name of a public method that is exposed by your Web


service. If left blank, the Web service's description page is
shown, listing each public method available in the .asmx file.
(Optional)

Parameter The appropriate parameter name and value for any


parameters required by your method. If left blank, the Web
service's description page is shown, listing each public
method available in the .asmx file. (Optional)
Note:

The Web service method name in this syntax is case sensitive, but the server, project, and Web
service names are not.

5. For example, suppose the StockServices Web service from the preceding procedure contains a
Web service method called GetQuote; the Web service method accepts a stock symbol as a
parameter, returning the price as a double-precision floating-point number. Enter the following
HTTP-GET request in the browser's address bar to test this method:
6. http://<servername>/apppath/StockServices.asmx/GetStockQuote?tickerName=MSFT
7. The server sends a response containing an XML document, which is displayed in the browser. For
the GetQuote example, the XML has the current price of the stock you request. The result might
look like the following:
<?xml version="1.0" ?>
<double>74.5</double>

To test a Web service in a browser using HTTP-


POST
1. Deploy your Web service to a Web server. For more information, see XML Web Service Publishing
and Deployment. This procedure uses as an example the following Web service, deployed as a file
math.asmx that is accessible from the virtual root of a site http://www.contoso.com:

C#

<%@ WebService Language="C#" Class="Math" %>


using System.Web.Services;
public class Math : WebService {
[ WebMethod ]
public int Add(int num1, int num2) {
return num1+num2;
}

[ WebMethod ]
public int Subtract(int num1, int num2) {
return num1-num2;
}
}

VB

<%@ WebService Language="VB" Class="Math" %>


Imports System.Web.Services

Public Class Math


Inherits WebService

<WebMethod> _
Public Function Add(num1 As Integer, num2 As Integer) As Integer
Return num1 + num2
End Function

<WebMethod> _
Public Function Subtract(num1 As Integer, num2 As Integer) As
Integer
Return num1 - num2
End Function
End Class
2. Create an HTML page with a form that has its method attribute set to POST. Use the following
format:
3. <form method=POST
action='http://www.contoso.com/math.asmx/Subtract'>
4. <input type="text" size="5" name='num1'\"></td> -
5. <input type="text" size="5" name='num2'\"></td> =
6. <input type=submit value="Subtract"> </td>
7. </form>

Parameter Value

Method POST. If you want to test your Web service using HTTP-POST, use
POST.

Action URL to the Web service method. In the previous example, math.asmx
is the Web service and Subtract is the Web service method.

type="text" For each parameter of the Web service method, create input tags


with the type attribute set to "text". This allows you to type a
parameter value in the text input control.

name='num The name of the Web service method parameter. Add as many text
1' input controls on the form as there are parameters in the Web service
method. For instance, if a Web service method has three parameters,
three text input controls are needed that each have
their name attribute set to the name of the parameter.

type=submit Add a submit button so you can post the data back to the Web service
method.
8. Access a Web browser and enter the URL for the HTML document you created in the previous step.
The HTML document created in the previous step is displayed.
9. Enter the appropriate values for the Web service method in the text boxes and click
the submit button.
For example, if you entered 6 and then 3 into the two text boxes for the
example's Subtract Web service method, the following result is returned:
<?xml version="1.0" ?>
<int xmlns="http://tempuri.org/">3</int>
Web Services Discovery
Given the URL to a discovery document residing on a Web server, a developer of a client application can
learn that a Web service exists, what its capabilities are, and how to properly interact with it. This process is
known as Web service discovery.
Through the process of Web service discovery, a set of files is downloaded to the local computer containing
details about the existence of Web services. The files can be service descriptions, XSD schemas, or discovery
documents. Using the Wsdl.exe tool, you can create a proxy class to the Web service described by a service
description or XSD schema. For details about creating a proxy class, see Creating an XML Web Service
Proxy. A downloaded discovery document contains information about the existence of other Web services
that might reside on a different Web server. For details about the contents of a discovery document,
see How to: Enable Discovery for XML Web Services.
You can use the Web Services Discovery tool (Disco.exe) from a command prompt to perform Web service
discovery on a URL.
Disco /out:location /username:user /password:mypwd /domain:mydomain
http://www.contoso.com/my.disco

Note:

The arguments listed are the commonly used arguments for Disco.exe.
For the full syntax of Disco.exe, see Web Services Discovery Tool
(Disco.exe).

Parameter Value

http://www.contoso.com/my.disco The URL to enact the discovery


process on.

/out:location The location to create the file


containing the discovery results.
The default value is the current
directory. (Optional)

/username:user The user name to use when


connecting to a Web server that
requires authentication. (Optional)

/password:mypwd The password to use when


connecting to a Web server that
requires authentication. (Optional)

/domain:mydomain The domain to use when connecting


to a Web server that requires
authentication. (Optional)
Creating Clients for XML Web
Services
A Web service client is any component or application that communicates with a Web service using SOAP
messages, or a comparable messaging protocol. A Web service client can be a traditional client application.
A client can also be another Web application. (In this situation, the Web application would consume the
XML within the SOAP message, format it, and send the result back to an ultimate client — perhaps a Web
browser.)
Create a Web service client by following these basic steps:

1. Create a proxy class for the Web service.

2. Reference the proxy class in the client code.

3. Create an instance of the proxy class in the client code.

4. If anonymous access has been disabled for the Web application hosting the Web service, set
the Credentials property of the proxy class.

5. Call the method on the proxy class that corresponds to the Web service method with which you
want to communicate.

For most clients, these steps differ only in how the proxy class is referenced and how the Web service client
is deployed.

Note:

If you create a Web service client using the following topics and your proxy fails with the
exception text, 
"The request failed with HTTP status 401: Access Denied," there is a good chance that you have
not yet passed your security credentials to the credential cache on the proxy. For details on
passing the correct credential information to the service, see How to: Configure an XML Web
Service for Windows Authentication.
Creating an XML Web Service
Proxy
By definition, Web services can be communicated with over a network using industry standard protocols,
including SOAP. That is, a client and a Web service communicate using SOAP messages, which encapsulate
the in and out parameters as XML. Fortunately, for Web service clients, the proxy class handles the work of
mapping parameters to XML elements and then sending the SOAP message over the network.
As long as a service description exists, a proxy class can be generated if the service description conforms to
the Web Services Description Language (WSDL). A service description defines how to communicate with a
Web service. With a service description, a proxy class can be created with the Wsdl.exe tool. In turn, a Web
service client can then invoke methods of the proxy class, which communicate with a Web service over the
network by processing the SOAP messages sent to and from the Web service. Because the proxy class
communicates with the Web service across the Internet, it is a good idea to verify that the Url property of
the proxy class references a trusted destination.
By default, the proxy class uses SOAP over HTTP to communicate with the Web service. However, Wsdl.exe
can generate proxy classes to communicate with a Web service, using either the HTTP-GET protocol or
HTTP-POST protocol. To specify that the proxy class should use HTTP-GET or HTTP-POST, provide
the /protocol switch to the Wsdl.exe tool, as described in the following table.

Using Wsdl.exe to Generate an XML Web


Service Proxy Class
You can use the Web Services Description Language tool (Wsdl.exe) from a command prompt to create a
proxy class, specifying (at a minimum) the URL to a Web service or a service description, or the path to a
saved service description.
Wsdl /language:language /protocol:protocol /namespace:myNameSpace
/out:filename /username:username /password:password /domain:domain <url or
path>

Note:

The arguments listed here are the commonly used arguments for Wsdl.exe. For the full syntax of Wsdl.exe, see We
Language Tool (Wsdl.exe).

Parameter Value

<url or path> A URL or path to a service descri


Language).
If you specify a file, supply a file
mywebservice.wsdl
If you specify a URL, the URL m
created using ASP.NET, you can
service. For example,
http://www.contoso.com/MyWeb

/language:language The language the proxy class is g


Basic .NET, and JScript .NET, re

/protocol:protocol The protocol used to communicat


and HTTP-POST. The default pro

/namespace:myNameSpace The namespace of the generated p

/out:filename The name of the file to create that


implements the Web service. (Op

/username:username The user name to use when conne

/password:password The password to use when connec

/domain:domain The domain to use when connecti

Generated Proxy Class Details


When Wsdl.exe is used to generate a proxy class, a single source file is generated in the specified language.
This file contains a proxy class that exposes both synchronous and asynchronous methods for each Web
service method of the Web service. For example, if a Web service contains a Web service method
named Add, the proxy class has the following methods for calling the Add Web service
method: Add, BeginAdd, and EndAdd. TheAdd method of the proxy class is used to communicate with
the Add Web service method synchronously, but the BeginAdd and EndAdd methods are used to
communicate with a Web service method asynchronously. For more information about communicating with
Web service methods asynchronously, see Communicating with XML Web Services Asynchronously.
Each method of the generated proxy class contains the appropriate code to communicate with the Web
service method. If an error occurs during communication with the Web service and the proxy class, an
exception is thrown. For more information about handling exceptions, see Handling and Throwing
Exceptions in XML Web Services.
The parameter order may differ between the defined order in the Web service method and the associated
method of the proxy class. In most cases, the parameter order matches. However, if the Web service
expectsDocument formatted SOAP messages, there is one case where the parameter order does not
match. If a Web service method has out parameters defined prior to an in parameter, the out parameters
are placed after all the in parameters in the proxy class. For example, in the following code example, the
Web service method MyWebMethod has the outStr out parameter declared prior to the inStr in
parameter. However, in the proxy class, the inStr parameter is declared prior to outStr.
C#

VB

// Declare MyWebMethod in the Web service.


MyWebMethod(out string outStr, string inStr)

// This is the corresponding MyWebMethod in the proxy class.


MyWebMethod(string inStr, out string outStr).
In some cases, the proxy class generated by Wsdl.exe uses a least common denominator approach for
casting objects to a type specified in a service description. As a result, the generated type in the proxy class
might not be what the developer wants or expects. For example, when Wsdl.exe encounters
an ArrayList type in a service description, it creates an Object array in the generated proxy class. To ensure
the correct object type casts, open the file that contains the generated proxy class and change any incorrect
object types to the expected object type.

Warnings Thrown by Wsdl.exe


When supplying multiple service descriptions to Wsdl.exe, two of the error messages that might be raised
are the following:

 Warning: Ignoring duplicate service description with TargetNamespace=<schema namespace>


from location <schema URI>. 

Indicates the TargetNamespace for two or more of the supplied service descriptions are identical.
As the TargetNamespace is supposed to be a unique identifier for a particular XML document,
which in this case is a service description, Wsdl.exe assumes that the two service descriptions are
identical. In doing so, Wsdl.exe builds just one proxy class for one of the service descriptions. If this
is not your intended result, you can change this. For service descriptions that represent Web
services created using ASP.NET, you can apply a WebService attribute that specifies a
unique Namespace property to the class that implements the Web service.
That Namespace property is then used as the TargetNamespace in the service description to
uniquely identify the Web service. 

 Warning: Ignoring duplicate schema with TargetNamespace=<schema Namespace> from location


<schema URI>. 

Indicates the TargetNamespace for two or more XML schemas within the supplied service
descriptions are identical. Because the TargetNamespace is supposed to be a unique identifier for
a particular XML document, which in this case is the XML schema, Wsdl.exe assumes that the two
XML schemas are identical. In doing so, Wsdl.exe builds a class for just one of the schemas. If this is
not the intended result, theTargetNamespace for each XML schema must be changed to a unique
URI. Exactly how the TargetNamespace is modified depends on the origin of the particular XML
schemas. 

SOAP Message Formatting


Standard SOAP Message
Formats Specified Using WSDL
The industry-standard Web Services Description Language (WSDL), which defines a schema for XML
documents that in turn define Web services, offers two central SOAP formatting options. Both options are
specified in XML elements not in the primary WSDL namespace, http://schemas.xmlsoap.org/wsdl/, but
rather in the namespace http://schemas.xmlsoap.org/wsdl/soap/. This secondary namespace commits a
Web service to the SOAP protocol.

SOAP Formatting Options


The two formatting options are:

 Style: For the child element, and possibly the grandchildren, of the Body element in a SOAP
message. This is specified as the style attribute of a binding WSDL element (typically) or
an operation element.

 Use: For the Web service method parameters, or a return value, that appear at the next level down.
This is specified as the use attribute of a body element.

For details on the SOAP specification, see the W3C Web site (http://www.w3.org/TR/SOAP). Details on the
WSDL specification can also be found at the W3C Web site ().

Allowed Values of the Style Attribute


WSDL allows two values for the style attribute that controls overall SOAP body formatting:

 RPC: Parameters, or a return value, are automatically placed in a parent element whose own parent
is the SOAP Body element. The parameters or return value appear without namespace
qualification. This scheme is described in Section 7 of the SOAP 1.1 specification.
Specified style="rpc".

For a SOAP request, the element below the SOAP Body is named after a WSDL operation element,
which corresponds to Web service method. Each element within that element represents a
parameter and is named after its respective parameter. 

For a SOAP response, the name of the element below the SOAP Body is the operation name
with Response appended. The name of the element underneath, representing the return value, is
the operation name but with the suffix Return.

 Document: The contents of the SOAP Body element are fully specified in the WSDL as XML
elements defined in an XML Schema definition. The XML schema is specified in, or imported into,
the WSDL document. The WSDL is oblivious to parameters and return values; it only deals with
XML documents. The developer, or preferably the Web services infrastructure, takes care of how
parameters and return values translate into XML Schema elements and types.
Specified style="document".

The top-level XML elements are specified as message parts -- part elements that are defined in
a message element and point to XSD element declarations. Normally, there is no more than one
part, so that the SOAPBody contents are truly an XML document, although WSDL itself doesn't
prohibit multiple elements.

WSDL allows two values for the use attribute that controls parameter, and return value, formatting:

 Encoded: Data is formatted according to a scheme is described in Section 5 of the SOAP 1.1
specification. SOAP encoding uses a subset of the XML Schema for binding between XML
documents and the data they represent. SOAP encoding also employs references for elements that
appear multiple times in a document. Specified use="encoded".
 Literal: Data is formatted literally according to XML Schema definitions specified in, or imported
into, the WSDL document. Specified use="literal".

Instead of handcrafting a WSDL document, a developer that creates a Web service for
ASP.NET can specify these SOAP formats by applying attributes to either individual Web
service methods or entire Web service classes. If a developer does not specify these
attributes, the default SOAP formats are used.
If you are developing a Web service based on an existing WSDL document, you can run the
Wsdl.exe tool with the /server option to generate an abstract Web service class that has the
appropriate attribute values automatically set.
Without the /server option, Wsdl.exe produces a client proxy class that sets the relevant
SOAP formatting attributes to the appropriate values to communicate with the Web service
described by the input WSDL document. A client proxy class uses most of the same attributes
that can be specified on the server. Normally, a developer does not need to manually add or
edit these attributes in the client proxy class because normally the client is generated by
Wsdl.exe to ensure that it complies with the service contract specified by the WSDL
document.
The following table outlines the formatting choices supported by Web services and clients
created using ASP.NET and the .NET Framework, along with the attributes that accomplish
each specific combination. The attributes with a Service suffix can be applied to a class that
implements a Web service (not a client proxy class) to set the default formatting style for
Web service methods within the class. The attributes with a Method suffix can be applied
either to a Web service method or to a method in a client proxy class that calls a Web service
method. The details of each combination are covered in the following paragraphs.

Parame
SOAP Body formatting (style)
ter
SOAP Body formatting (style) for for RPC-based SOAP messages
forma
Document-based SOAP messages according to SOAP 1.1 Section
tting
7s
(use)

Literal SoapDocumentMethod or SoapDocu SoapRpcMethod or SoapRp


— mentService cService
based Use=Literal Use=Literal
on an This is the default.
XSD
schem
a for
each
parame
ter

Encod SoapDocumentMethod or SoapDocu SoapRpcMethod or SoapRp


ed - mentService cService
SOAP Use=Encoded Use=Encoded
1.1 This is the default.
Sectio
n 5
encodi
ng
rules

Note:

The actual attribute names use the Attribute suffix. In the source code, the names can be
abbreviated, as shown in the preceding table.

Controlling the Overall SOAP Body Formatting


For style, which controls whether the Web service run-time engine applies the RPC
conventions or defers to XML documents, the default choice in an ASP.NET Web service is
document, not RPC.
Document style can be explicitly specified by applying
the SoapDocumentMethodAttribute attribute to a Web service method or client proxy
method, or by applying the SoapDocumentServiceAttribute attribute to a Web service class.
RPC style can be explicitly specified by applying the SoapRpcMethodAttribute attribute to a
Web service method or client proxy method, or by applying
the SoapRpcServiceAttribute attribute to a Web service class. For a service, a method-level
attribute overrides a class-level attribute.
These same attributes play a role in determining parameter and return value formatting, as
described later in this topic. They also play a role in determining whether a "wrapper"
element is automatically generated at runtime to contain the parameters or return value. For
more information, see How to: Control Whether Web Service Method Parameters Are
Enclosed in an Extra Element.
For more information about how to apply these attributes, see How to: Control the Overall
SOAP Body Formatting for a Web Service Method.

Controlling the Parameter and Return Value


Formatting
For use, which controls the formatting of the Web service method parameters or a return
value, the default choice in a document-style ASP.NET Web service is literal. The default
choice in an RPC-style ASP.NET Web service is encoded. You can change the use value by
setting the Use property on the
corresponding SoapDocumentMethodAttribute, SoapDocumentServiceAttribute, SoapR
pcMethodAttribute or SoapRpcServiceAttributeattributes to
either SoapBindingUse.Literal or SoapBindingUse.Encoded.
For more information about how to set the Use property, see How to: Control Parameter and
Return Value Formatting for a Web Service Method.
Controlling Whether Parameters Are Enclosed
in an Extra XML Element
The parameters or return value for a Web service method can automatically be encapsulated
within a parent XML element within the Body element of the SOAP message. The developer
does not have to specify the parent element. As you have seen, RPC formatting style does
this. However, it is also an option with a document formatting style. Instead of the parent
XML element, or wrapper, being specified in the WSDL document, the extra element is
implicitly inserted by the Web services infrastructure at runtime.
This convention is called wrapping and can be specified by setting
the SoapDocumentMethod.ParameterStyle or SoapDocumentService.ParameterStyle pr
operty to a value of SoapParameterStyle.Wrapped. Wrapped is also the default value.
The SoapParameterStyle enumeration also has a value of Default to specify the default
parameter style on the service class level, plus a value of Bare to turn off wrapping and
literally translate the XML elements that are specified by the WSDL as message parts into
method parameters and return values. With a Bare parameter style, each parameter or return
value corresponds to a specified message part.
The choice of whether to wrap is not specified in a WSDL document; with
both Wrapped and Bare, the binding style being used is document. Rather, the choice
involves the binding between XML and code—between the XML defined in the WSDL and
the parameters and return values of methods.
With the ParameterStyle property set to SoapParameterStyle.Bare, the developer is able to
specify a message that has multiple parts—literally multiple XML elements that appear as
children of the SOAP Body element. Technically, multiple elements do not constitute an
XML document because a document must have a single root. Therefore, the recommended
practice in the Web services community is to use a single message part with document-style
services. Each Web service method must use not its intended signature but a signature where
an object mapping to an XML document is the single parameter and another object mapping
to an XML document is the return value. A developer must write the code to extract or
package the true parameters or return values.
Therefore, normally it is sufficient for a developer to set the ParameterStyle property
to SoapParameterStyle.Wrapped and let the Web services infrastructure place parameters
and return values into XML documents.
For more information about how to set the ParameterStyle property, see How to: Control
Whether Web Service Method Parameters Are Enclosed in an Extra Element.

Setting the Default SOAP Formatting for an


Entire Web Service
As noted earlier in this topic,
the SoapDocumentServiceAttribute and SoapRpcServiceAttribute attributes can be used
to set default values for style, use and parameter-to-document mapping style for an entire
Web service class, but not for a client proxy class.
The SoapDocumentMethod and SoapRpcMethod attributes can be used to override
service-level settings for each Web service method.
For more information about how to use
the SoapDocumentService and SoapRpcService attributes, see How to: Modify the Default
SOAP Formatting for an Entire Web Service.
Customizing SOAP Messages with XML
Serialization
Besides specifying style, use, and whether to insert a wrapper element, you can directly
customize the XML in a SOAP message with XML serialization. By default, the .NET
Framework's Web services infrastructure automatically serializes public fields and properties
into XML messages.
The System.Xml.Serialization namespace includes numerous attributes for manipulating
XML. The following code example shows how some of these attributes can be applied
directly to Web service method parameters or return values.
C#

VB

[SoapDocumentMethod(
"http://www.contoso.com/DocumentBareLiteral",
Use=SoapBindingUse.Literal,
ParameterStyle=SoapParameterStyle.Bare)]
[return: XmlElement(Namespace="http://www.contoso.com",
IsNullable=true)]
public string DocumentBareLiteral(
[XmlElement(Namespace="http://www.contoso.com",
IsNullable=true)]
Address1 MyAddress,
[XmlElement(Namespace="http://www.contoso.com",
IsNullable=false)]
bool useZipPlus4) {
Some commonly used attributes are listed as follows, their names appear without
the Attribute suffix, which can be omitted:

 XmlElement: Specifies that a public field or property be serialized as an XML element. This is
the default attribute for serializing non-array public fields and properties. When
the XmlElement attribute is applied to public fields and properties of an array type attribute,
the array is serialized with other members, without a special parent element.

 XmlAttribute: Specifies that a public field or property be serialized as an XML attribute of the
element that represents the containing type.

 XmlArray: Specifies that a public field of an array type be serialized with a special parent
element. This is the default attribute for serializing public fields and properties of an array
type.

 XmlArrayItem: Used in combination with the XmlArray attribute to control the array


elements.

 XmlIgnore: Specifies that a public field or property not be serialized.

The preceding attributes, except for XmlIgnore, can also be used to specify an element or
attribute name besides the default, which is the member name for non-array members. They
can also be used to specify a namespace for a particular element. Usually, a Web service does
not mix namespaces and a namespace is required to be specified only at the class level, using
an attribute like WebService or WebServiceBinding.
For more information, see , see System.Xml.Serialization.

Note:

For RPC or encoded Web services, using RPC style with SOAP encoding, the use of XML serialization is restricted
Also, SOAP 1.1 Section 5 encoding, combined with document or RPC style, prohibits the binding of data to XML attr

Note:

If an abstract service class or client proxy class is generated from a WSDL document, the correct System.Xml.Ser
that are defined under the WSDL types element, whether they appear inline or are imported.

Note:

Using Nullable types in a Web service results in WSDL that contains the "nillable=true" setting for the type. However, when
not reflected in the resulting WSDL in the following cases: 1) When RPC-based SOAP messages are used, and 2) When Doc

SOAP Message Modification


Using SOAP Extensions
SOAP extensions allow developers to augment the functionality of a Web service by altering the SOAP
messages sent to and from a Web service or a Web service client. For instance, you can implement an
encryption or compression algorithm to run with an existing Web service.
To understand how a SOAP extension works, it is useful to first understand the lifetime of a Web service.
For more information, see Anatomy of an XML Web Service Lifetime.
The following illustration outlines the major phases of a call from a client to a Web service.
As you can see, the .NET Framework serializes and deserializes XML during phases on both the Web service
computer and the Web service client computer. A SOAP extension can be injected into the infrastructure to
inspect or modify the SOAP messages before and after each of these serialize and deserialize phases. For
instance, an encryption SOAP extension might encrypt the XML portion of the SOAP message after the .NET
Framework serializes the client's arguments, and then decrypt the SOAP message on the Web server before
the .NET Framework deserializes the SOAP message. These phases, where a SOAP extension might inspect
or modify the SOAP message, are defined in the SoapMessageStage enumeration. In this case, the SOAP
extension is encrypting in the AfterSerialize stage and decrypting in the BeforeDeserialize stage.
Typically, when a SOAP extension modifies the contents of a SOAP message, the modifications must be
done on both the client and the server. That is, if a SOAP extension were to run on the client and encrypt
the SOAP message, a corresponding SOAP extension must decrypt the SOAP message on the server. If the
SOAP message is not decrypted, then the ASP.NET infrastructure cannot deserialize the SOAP message into
an object.
Of course, a SOAP extension that does not modify the SOAP message, such as a SOAP extension that
simply logs the SOAP messages, can run on only the client or server. In this case, the recipient receives the
same SOAP message it would have if a SOAP extension were not running and the ASP.NET infrastructure
can deserialize the SOAP message. Also, if the SOAP extension does not modify the SOAP in a way that
makes deserialization impossible, the SOAP extension does not need to run on both the client and server.

Extending the SOAPExtension Class


To implement a SOAP extension, derive a class from the SoapExtension class. There are three methods of
the SOAPExtension class that should, or must, be implemented:

 ChainStream, a virtual method

 GetInitializer, an abstract method with two signatures

 Initialize, an abstract method

 ProcessMessage, an abstract method

How to implement these methods is explained in the step-by-step topic Walkthrough: Altering the SOAP
Message Using SOAP Extensions.
The ChainStream method is passed a Stream object and returns a Stream object. As the SOAP extension
executes during each SoapMessageStage and modifies the SOAP message, a SOAP extension should read
from theStream passed into ChainStream and write to the Stream returned from ChainStream. Therefore,
it is important within the ChainStream method to assign both Stream references to member variables.
The class deriving from SoapExtension uses the GetInitializer and Initialize methods to initialize internal
data, based on the Web service or Web service method it is applied to. For instance, a SOAP extension that
logs the SOAP message sent to and from a Web service method might initialize the name of a file to save
the logging information (based on the name of the Web service or the Web service method the SOAP
extension is running with).
At what point the Web services infrastructure calls the GetInitializer method and what parameters are
passed to the method depend on how the SOAP extension is configured, as follows:

 If the SOAP extension is configured using an attribute, GetInitializer is called by the Web services
infrastructure the first time a Web service method is accessed. 

 If the SOAP extension is configured in a configuration file, GetInitializer is called by the Web


services infrastructure only the first time the entire Web service is accessed. 

The Web services infrastructure caches the object that the GetInitializer method returns. Then each time
the SOAP extension runs with that Web service or Web service method, the infrastructure passes the
initializer object to the Initialize method.
Actual extended processing beyond the standard SOAP processing is performed by
the ProcessMessage method. Each time the Web services infrastructure calls ProcessMessage, it passes (as
an argument) an instance of a class derived from SoapMessage that contains information about the SOAP
message at that particular stage. If the SOAP extension is running with a Web service, then
a SoapServerMessage object is passed in. If the SOAP extension is running with a Web service client, then
a SoapClientMessage object is passed in.
Soap Extensions and Exceptions
Soap extensions must never throw exceptions themselves. They can, however, add exception information to
the Exception property on the SoapMessage object passed in the ProcessMessage method.
They can also serve as application-wide exception handler using the same facility to catch all exceptions in
the application for which the soap extension is installed and perform some behavior including modifying
the returned SOAP fault.

Order in Which SOAP Extension Methods are


Invoked
Now that you have looked at the methods a SOAP extension overrides, look at when the Web services
infrastructure invokes SOAP extension methods throughout the invocation of a Web service method. The
following steps assume that the SOAP extension is running on both the client and server. If the SOAP
extension is not running on both the client and the server, the steps associated with the SOAP extension
running on each are ignored by the .NET Framework.
Client Side Prepares a Request Message

1. A client invokes a method on the proxy class.

2. A new instance of the SOAP extension is created on the client.

3. If this is the first time this SOAP extension has executed with this Web service on the client, then
the GetInitializer method is invoked on the SOAP extension running on the client.

4. The Initialize method is invoked.

5. The ChainStream method is invoked.
6. The ProcessMessage method is invoked with SoapMessageStage set to BeforeSerialize.

7. ASP.NET on the client computer serializes the arguments of the Web service method into XML.

8. The ProcessMessage method is invoked with SoapMessageStage set to AfterSerialize.

9. ASP.NET on the client computer sends the SOAP message over the network to the Web server
hosting the Web service.

Server Side Receives a Request Message and Prepares a Response

1. ASP.NET on the Web server receives the SOAP message.

2. A new instance of the SOAP extension is created on the Web server.

3. On the Web server, if this is the first time this SOAP extension has executed with this Web service
on the server side, the GetInitializer method is invoked on the SOAP extension running on the
server.

4. The Initialize method is invoked.

5. The ChainStream method is invoked.

6. The ProcessMessage method is invoked with SoapMessageStage set to BeforeDeserialize.

7. ASP.NET deserializes the arguments within the XML.

8. The ProcessMessage method is invoked with SoapMessageStage set to AfterDeserialize.

9. ASP.NET creates a new instance of the class implementing the Web service and invokes the Web
service method, passing in the deserialized arguments. This object resides on the same computer
as the Web server.

10. The Web service method executes its code, eventually setting the return value and any out
parameters.

11. The ProcessMessage method is invoked with SoapMessageStage set to BeforeSerialize.

12. ASP.NET on the Web server serializes the return value and out parameters into XML.

13. The ProcessMessage method is invoked with SoapMessageStage set to AfterSerialize.

14. ASP.NET sends the SOAP response message over the network back to the Web service client.

Client Side Receives a Response Message

1. ASP.NET on the client computer receives the SOAP message.

2. The ProcessMessage method is invoked with SoapMessageStage set to BeforeDeserialize.

3. ASP.NET deserializes the XML into the return value and any out parameters.

4. The ProcessMessage method is invoked with SoapMessageStage set to AfterDeserialize.

5. ASP.NET passes the return value and any out parameters to the instance of the proxy class.
6. The client receives the return value and any out parameters.

Implementing the SOAP Extension


There are two ways to run a SOAP extension on either a client or server application. First, you can configure
the application to run the extension. To configure your SOAP extension to run for all Web methods on all
Web services, especially a vroot, edit the <soapExtensionTypes> Element section within the Web.config file.
The following code shows that the type attribute value must be on one line and include the fully qualified
name of the extension, plus the version, culture, and public key token of the signed assembly.
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="Contoso.MySoapExtension, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
priority="1" group="0"/>
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
Second, you can create a custom attribute that is applied to a Web service method. To create the custom
attribute, create a class that derives from SoapExtensionAttribute. For details about creating a custom
attribute, seeHow to: Implement a SOAP Extension. For more information about creating custom attributes,
see Creating Custom Attributes.

Note:

When implementing a SOAP extension, there is a possibility that a Denial of Service (DOS)
attack could be attempted if your extension uses an XmlTextReader to read the data stream.
One way of preventing such an attack is to ensure that the ProhibitDtd property is set to true.

Priorities and Priority Groups


Using either attributes or configuration, SOAP extensions can be assigned a priority that helps determine
the relative order of execution when multiple SOAP extensions are configured to run with an XML Web
service method. The higher the priority a SOAP extension is, the closer it executes to the SOAP message
being sent or received over the network. SOAP extensions belong to any of three priority groups. Within
each group, thepriority property distinguishes each member. The lower the priority property is, the higher
the relative priority (0 being the highest).
The three relative priority groups for SOAP extensions are: SOAP extensions configured using an attribute
and SOAP extensions specified in the configuration file with a group setting of 0 or 1. Their priorities are
ordered as follows:

 Highest priority group: SOAP extensions configured using a configuration file with a  group setting
of 0.

 Medium priority group: SOAP extensions configured using an attribute.

 Lowest priority group: SOAP extensions configured using a configuration file with a group setting
of 1.
The following code example is a configuration file that specifies that
the Logger.LoggerExtension SOAP extension runs within the relative priority group 0 and has a
priority of 1.
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="Logger.LoggerExtension,logger"
priority="1"
group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>

How to: Control the Overall


SOAP Body Formatting for a
Web Service Method
For overall SOAP body formatting, or style, the Web Services Description Language (WSDL) provides two
choices: RPC and document. The .NET Framework controls these choices in code using attributes.

To specify a Document formatting style


1. Apply a SoapDocumentMethod attribute or a SoapRpcMethod attribute to the method in the
proxy class calling the applicable Web service method.
Web services created using ASP.NET support the use of both the Literal and Encoded parameter
formatting styles. The following example combines the Document method formatting style with
the Literal parameter formatting style.

C#

[SoapDocumentMethod("http://www.contoso.com/DocumentWrappedLiteral",
RequestNamespace="http://www.contoso.com",
ResponseNamespace="http://www.contoso.com",
Use=SoapBindingUse.Literal)]
public string DocumentWrappedLiteral(Address MyAddress,
bool useZipPlus4) {

VB

<SoapDocumentMethod("http://www.contoso.com/DocumentWrappedLiteral",
_
RequestNamespace:="http://www.contoso.com", _
ResponseNamespace:="http://www.contoso.com", _
Use:=SoapBindingUse.Literal)> _
Public Function DocumentWrappedLiteral(ByVal MyAddress As Address,
_
ByVal useZipPlus4 As Boolean)As String
With the Document formatting style, an XSD schema is defined within the service description that
defines both the SOAP request and SOAP response. The following is an excerpt from the service
description for the SOAP request for the DocumentWrappedLiteral Web service method.
Because the first parameter to the DocumentWrappedLiteral Web service method is a class,
and the Literal parameter formatting style was specified, an XSD schema is created for
the address type.
<s:element name="DocumentWrappedLiteral">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="MyAddress"
nillable="true" type="s0:Address" />
<s:element minOccurs="1" maxOccurs="1" name="useZipPlus4"
type="s:boolean" />
</s:sequence>
</s:complexType>
</s:element>

<s:complexType name="Address">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="Street"
nillable="true" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="City"
nillable="true" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" name="Zip"
nillable="true"
type="s:string" />
</s:sequence>
</s:complexType>
With the XSD schema that is defined in the service description, the XML portion of the SOAP
request to the DocumentWrappedLiteral Service method follows. Note that the XML
elements beneath the Bodyelement in the SOAP request match the elements defined in the XSD
schema.
<?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>
<DocumentWrappedLiteral xmlns="http://www.contoso.com">
<MyAddress>
<Street>string</Street>
<City>string</City>
<Zip>string</Zip>
</MyAddress>
<useZipPlus4>boolean</useZipPlus4>
</DocumentWrappedLiteral>
</soap:Body>
</soap:Envelope>
To specify RPC formatting style
1. Apply a SoapRpcMethod attribute to the method in the proxy class calling the applicable Web
service method.

C#

[SoapRpcMethodAttribute("http://www.contoso.com/Rpc",
RequestNamespace="http://www.contoso.com",
ResponseNamespace="http://www.contoso.com")]
public Address Rpc(Address address, bool useZipPlus4) {

VB

<SoapRpcMethodAttribute("http://www.contoso.com/Rpc", _
RequestNamespace:="http://www.contoso.com", _
ResponseNamespace:="http://www.contoso.com")>
_
Public Function Rpc(ByVal address As Address, _
ByVal useZipPlus4 As Boolean) As Address
An XSD schema is not strictly defined in the service description for either the SOAP request or
SOAP response to the Rpc method in the previous example, but rather just the parts that comprise
them. Therefore, look at the SOAP request for the Rpc method, noting that the parameters are
encapsulated inside one element and they are encoded using the Encoded parameter formatting.
<?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:soapenc="http://schemas.xmlsoap.org/soap/encoding/
"
xmlns:tns="http://www.contoso.com"
xmlns:tnsTypes="http://www.contoso.com/encodedTypes"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:Rpc>
<address href="#1" />
<useZipPlus4>boolean</useZipPlus4>
</tns:Rpc>
<tnsTypes:Address id="1">
<Street id="2">string</Street>
<City id="3">string</City>
<Zip id="4">string</Zip>
</tnsTypes:Address>
</soap:Body>
</soap:Envelope>

XML Web Services Directives


The topics in this section describe the markup syntax that you can use within an XML Web service
built using ASP.NET. XML Web services created using ASP.NET are text files that have an .asmx file
name extension.

Note:

If an XML Web services sample has been developed using Visual Studio, a tilde ('~') can appear in a directive attribu
this usage, see ASP.NET Web Site Paths

In This Section

Term Definition

@ Assembly Directive in XML Links an assembly to an XML Web service during compilation.
Web Services

@ WebService Directive in Defines XML Web service specific (.asmx file) attributes used by
XML Web Services the ASP.NET parser and compiler.

@ Assembly Directive in XML Web Services


Links an assembly to an XML Web service during compilation, making all the assembly's classes and
interfaces available for use by the XML Web service.

C#
<%@ Assembly Name="assemblyname" %><%@ Assembly Src="pathname" %>

Attributes
Term Definition

Nam The name of the assembly to link to the XML Web service.
e
Note:
The assembly name does not include a file name extension.

Src The path to a source file to dynamically compile and link against.

Note:
You cannot include a Name and a Src attribute in the same @ Assembly directive. If you want to
than one directive on the page.

Remarks
The compiler references the assembly at compile time, allowing early binding. Once compilation of
the XML Web service is complete, the assembly is dyamically loaded into the application domain
when it changes, allowing late binding.

Assemblies that reside in your Web application's \bin directory are automatically linked to XML Web
services in that application. Such assemblies do not require the @ Assembly directive.

Note:

The path to the assembly or source file in an @ Assembly directive must be a relative path to the Web appl
service.

Example
The following code fragment uses two @ Assembly directives, the first to link to MyAssembly, a
user-defined assembly, the second to MySource.vb, a Visual Basic source file located in the src
folder beneath the directory of the Web application hosting the XML Web service.

<%@ Assembly Name="MyAssembly" %>


<%@ Assembly Src="src/MySource.vb" %>

@ WebService Directive in XML Web Services


Defines XML Web service specific (.asmx file) attributes used by the ASP.NET parser and compiler.

C#
<%@ WebService attribute="value" [attribute="value"…] %>

Attributes
Term Definition

Class Specifies the class implementing the XML Web service that is automatically compiled
the first time the XML Web service is accessed after changes. This value can be any
valid class name residing in either the same file as the WebService directive or within a
separate file. If the class resides in a separate file, it must be placed in the \Bin directory
underneath the Web application where the XML Web service resides. This attribute is
required for the XML Web service to compile.
CodeBehin Specifies the source file implementing the XML Web service, when the class
d implementing the XML Web service does not reside in the same file and has not been
compiled into an assembly and placed in the \Bin directory.

Debug Indicates whether the XML Web service should be compiled with debug symbols. true if
the XML Web service should be compiled with debug symbols; otherwise, false.

Language Specifies the language used when compiling all inline code within the XML Web
service file (.asmx). The values can represent any .NET-supported language, including
C#, VB, and JS, which refer to C#, Visual Basic .NET, and JScript .NET, respectively.

Transactions in ASP.NET WebServices


(CodeProject)

Introduction
The transaction support for XML Web services created using ASP.NET is based on the same
distributed transaction model found in the COM+ Services. This model is based on declaring
attributes to decide whether an object participates in a transaction, rather than writing specific code to
commit / roll back a transaction.

Once an XML Web service method is marked to participate in a transaction, it will automatically
execute within the scope of a transaction. You can control an object's transactional behavior by setting
a transaction attribute value on XML Web service method. The attribute value, in turn, determines the
transactional behavior of the instantiated object. Thus, based on the declared attribute value, an
object will automatically participate in an existing or ongoing transaction, be the root of a new
transaction, or never participate in a transaction at all.

In an XML Web service created using ASP.NET, you can declare the web method’s transactional
behavior by setting theTransactionOption property of the WebMethod attribute applied to an
XML Web service method. If an exception is thrown while the XML Web service method is executing,
the transaction is automatically aborted; conversely, if no exception occurs, the transaction is
automatically committed.
Lets look at the TransactionOption enumeration:
 Disabled: Ignores any transaction in the current context.
 NotSupported: Creates the component in a context with no governing transaction.
 Required: Shares a transaction if one exists, and creates a new transaction if necessary.
 RequiresNew: Creates the component with a new transaction, regardless of the state of the
current context.
 Supported: Shares a transaction, if one exists.
To participate in a transaction from an XML Web service method:
1. Declare an XML Web service.
 Collapse | Copy Code

<%@ WebService Language="C#" Class=" DBOperations " %>


2. Add an Assembly directive to System.EnterpriseServices.
 Collapse | Copy Code

<%@ Assembly name="System.EnterpriseServices" %>


3. Add references to
the System.Web.Services and System.EnterpriseServices namespaces.
 Collapse | Copy Code

using System.Web.Services;
using System.EnterpriseServices;
4. Declare an XML Web service method, setting the TransactionOption property of
the WebMethod attribute toTransactionOption.RequiresNew.
 Collapse | Copy Code

[ WebMethod(TransactionOption=TransactionOption.RequiresNew)]
public int DeleteAuthor(string lastName)
The following code example shows an XML Web service that exposes a single XML Web service
method, calledDBOperations. This XML Web service method performs a database operation that is
scoped within a transaction. If the database operation does throw an exception, the transaction is
automatically stopped; otherwise, the transaction is automatically committed.
 Collapse | Copy Code

<%@ WebService Language="C#" Class=" DBOperations " %>


<%@ Assembly name="System.EnterpriseServices" %>

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

public class DBOperations : WebService


{

[ WebMethod(TransactionOption=TransactionOption.RequiresNew)]
public int DeleteAuthor(string lastName)
{

String delCmdSql =
"DELETE FROM authors WHERE au_lname='" + lastName + "'" ;
String exceptionCausingCmdSQL =
"DELETE FROM NonExistingTable WHERE au_lname='" + lastName + "'" ;
SqlConnection myCon =
new SqlConnection("user id=sa;database=pubs;server=myserver");
SqlCommand delCmd = new SqlCommand(delCmdSQL,myCon);
SqlCommand exceptionCausingCmd = new
SqlCommand(exceptionCausingCmdSQL,myCon);

// This command should execute properly.


delCmd.Connection.Open();
delCmd.ExecuteNonQuery();
// This command results in an exception, so the first command is
// automatically rolled back.
int cmdResult = exceptionCausingCmd.ExecuteNonQuery();
myCon.Close();
return cmdResult;
}
}

Transactions across WebServices

Let us look at an example of how the transaction occurs across XML Web service methods.

Consider we are having two servers Server1 and Server2. Server1 hosts XML Web Services WService1
and WService2. Server2 hosts WService3.

WService1 exposes a Web method named WMethod1, WService2 exposes Wmethod2, and WService3


exposesWmethod3. The Wmethod1 of WService1 is shown in the following code segment:
 Collapse | Copy Code

[WebMethod(TransactionOption.RequiresNew)]
public void WMethod1 ()
{
Server1. WService2 Service2 = new Server1. WService2 ();
Server2.WService3 Service3 = new Server2. WService3 ();
Service2.WMethod2();
Service3.WMethod3();
}
The TransactionOption property of WMethod2 and WMethod3 are set
to TransactionOption.Required.
 Collapse | Copy Code

[WebMethod(TransactionOption.Required)]
public void WMethod2 ()
{
//Code to update a row in a table
}

[WebMethod(TransactionOption.Required)]
public void WMethod3 ()
{
//Code to update a row in another table
}
Develop a client application named myApp that consumes Wmethod1 of WService1. Run myApp.
While WMethod1 is calling WMethod3, close myApp.
What is the most likely result? What do you expect? A roll back of the updates made
by WMethod2 and WMethod3?
No, the Answer is Wmethod1 continues processing, and whatever updates that are made by
the WMethod2 andWMethod3 persists, because transactions do not flow across XML Web service
methods.

XML Web service methods can only participate in a transaction as the root of a new transaction. XML
Web service methods that call other XML Web service methods participate in different transactions, as
transactions do not flow across XML Web service methods.

S-ar putea să vă placă și