You are on page 1of 88

Notes

Asynchronous XML Service Methods

Web

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. 2. 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. 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.

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. 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
3.

The return value must be of type IAsyncResult.

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.

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. 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.

End<NameOfWebServiceMethod>

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


public void MethodName(IAsyncResult ar)

With the callback technique, a callback function implements the AsyncCallback delegate, which enforces the signature: 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

2.

<%@ WebService Language="VB" Class="ServerUsage" %> Add a reference to the System.Web.Services namespace.
C#

using System.Web.Services;
VB

3.

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

public class ServerUsage : WebService


VB

4.

Public Class ServerUsage : Inherits WebService Declare a Web service method, setting the EnableSession property of the WebMethod attribute to true.
C#

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


VB

5.

< WebMethod(EnableSession:=True) > _ Public Function PerSessionServiceUsage() As Integer 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

6.

Session("MyServiceUsage") = 1 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

2.

<%@ WebService Language="VB" Class="ServerUsage" %> Add a reference to the System.Web.Services namespace.
C#

using System.Web.Services;
VB

3.

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

public class ServerUsage : WebService


VB

4.

Public Class ServerUsage : Inherits WebService Declare a Web service method.


C#

[ WebMethod ] public int PerSessionServiceUsage()


VB

5.

< WebMethod > _ Public Function PerSessionServiceUsage() As Integer 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

6.

Application("appMyServiceUsage") = 1 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 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"] = Application["appMyServiceUsage"]) + 1; } return (int) Application["appMyServiceUsage"]; }

has

been

((int)

[ 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

5.

Imports System.Web.Services Imports System.EnterpriseServices 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 name Description

Disabled

Ignores any transaction in the current context.

NotSupported

Creates the component in a context with no governing transaction.

Supported

Shares a transaction, if one exists.

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.

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

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 Disabled

Description 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)] 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.NotSupported )] 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)] 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)] Indicates that the XML Web service method requires a new transaction. When a request is processed, the XML Web service is created within a new transaction. [WebMethod(TransactionOption= TransactionOption.RequiresNew) ]

NotSupporte d

Supported

Required

RequiresNew

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, 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); } } }

long

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 the WebMethodAttribute class.

of

WebMethodAttribute(Boolean)

Initializes a new instance the WebMethodAttribute class.

of

WebMethodAttribute(Boolean, TransactionOption)

Initializes a new instance the WebMethodAttribute class.

of

WebMethodAttribute(Boolean, TransactionOption, Int32)

Initializes a new instance the WebMethodAttribute class.

of

WebMethodAttribute(Boolean, TransactionOption, Int32, Boolean)


Top

Initializes a new instance the WebMethodAttribute class.

of

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.

TransactionOption

Indicates the transaction support of an XML Web service method.

TypeId
Top

When implemented in a derived class, gets a unique identifier for this Attribute. (Inherited from Attribute.)

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 from Object.)

the

current

instance. (Inherited

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.)

MemberwiseClone

Creates a shallow copy of the current Object. (Inherited from Object.)

ToString
Top

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

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.GetTypeInfoCount

Retrieves the number of type information interfaces that an object provides (either 0 or 1). (Inherited from Attribute.)

_Attribute.Invoke
Top

Provides access to properties and methods exposed by an object. (Inherited from Attribute.)

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 Requires New Suppress Required Requires New Suppress

No No No Yes Yes Yes

New Transaction (will be the root) New Transaction (will be the root) No Transaction Ambient Transaction New Transaction (will be the root) 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 TransactionScope(TransactionScopeOption.RequiresNew)) { ... } using(TransactionScope scope4 = new TransactionScope(TransactionScopeOption.Suppress)) { ... } } = new

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 CommittableTransaction(); Transaction.Current = committableTransaction; try { /* Perform transactional work here */ // No errors - commit transaction asynchronously committableTransaction.BeginCommit(OnCommitted,null); } finally {

new

//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 Escalation

Management

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. The transaction manager is down. The escalation fails and the application is aborted.

TransactionAbortedException TransactionException

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 = DependentTransaction; Debug.Assert(dependentTransaction != null); try { using(TransactionScope ts TransactionScope(dependentTransaction)) { /* Perform transactional work here */ ts.Complete(); } } finally { dependentTransaction.Complete(); dependentTransaction.Dispose(); } }

transaction

as

new

//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


Authentication option Description

Windows Basic

Use for non-secure identification of clients, as the user name and 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 networkmonitoring tool can intercept user names and passwords. Use for secure identification of clients in Internet scenarios. The user name and password are sent over the network using Secure Sockets Layer (SSL) encryption, rather than plain text. This is relatively easy to configure and works for Internet scenarios. However, using SSL degrades performance. Use for secure identification of clients in Internet scenarios. Uses 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. Uses NTLM or Kerberos. Uses a cryptographic exchange with the user's Microsoft Internet Explorer Web browser.

Windows Basic over SSL

Windows Digest

Windows Integrated Windows Windows

Use for secure identification of clients in Internet and intranet

Client Certificates

scenarios. Requires each client to obtain a certificate from a mutually trusted certificate authority. Certificates are optionally mapped to user accounts, which are used by IIS for authorizing access to the Web service. 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. Useful for both secure and non-secure Internet scenarios. User credentials are passed within the SOAP header of the SOAP message. The Web server, regardless of the platform hosting the Web service, provides a custom authentication implementation.

Forms

SOAP headers Custom

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 HTTPPOST 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. Modify the configuration file to specify Windows authentication.

2.

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. 2. 3. 4. 5. 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 Create a new instance of the NetworkCredential class, setting the UserName, Password and Domain properties. Create a new instance of CredentialCache. Add the NetworkCredential to the CredentialCache using the Add method of CredentialCache 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. The following code example sets the client credentials passed to a Web service method using Windows authentication.

6.

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. 2. 3. 4.

The following list is an overview of how to configure IIS to authenticate clients using client certificates. For details, see the IIS documentation. Install SSL. Configure the Web application to accept client certificates. 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. 2. 3. 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. Create a new instance of the X509Certificate. 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. 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

4.

' 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 using using using

System; System.Web.Services.Protocols; System.Net; 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. 2. 3. The HTTP Module parses HTTP messages to check whether they are SOAP messages. If the HTTP Module detects a SOAP message, it reads the SOAP headers. 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 using using using using using using

System; System.Web; System.IO; System.Xml; System.Xml.XPath; System.Text; 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 using using using

Microsoft.WebServices.Security { System; System.Web; 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. 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. If the parsing method takes input parameters, specify the elements that represent those parameters and associate them with the operation.

2. 3.

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. 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.

2.

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. 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. If the parsing method takes input parameters, specify the elements that represent those parameters and associate them with the operation.

2. 3.

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 speci 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. 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.

2.

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 Exceptions Services

and Throwing in XML Web

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:

Type of exception thrown

What a Web service can do, what a client receives

Exception other thanSoapException orSoapHeaderException

A Web service method detects an exception case and throws the specific exception, such as ArgumentOutOfRangeException. A .NET Framework client receives a SoapException with the details serialized into text in the Message property. 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. 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.

SoapException

SoapHeaderException

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 unhandled

What ASP.NET does

exception occurs

While executing the Web service method While processing SOAP headers

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

ASP.NET throws a SoapHeaderException. A Web service client created using the .NET Framework receives the SoapHeaderException.

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

2.

Public Class MyHeader : Inherits SoapHeader 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

2.

<WebService(Namespace:="http://www.contoso.com")> _ Public Class MyWebService ' Add a member variable of the type deriving from SoapHeader. Public TimeStamp As MyHeader 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

3.

<WebMethod, SoapHeader("TimeStamp")> _ Public Sub MyWebMethod() 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#

2.

MyHeader mySoapHeader = new MyHeader(); Populate the values for the SOAP header.
VB

mySoapHeader.Username = UserName mySoapHeader.Password = SecurelyStoredPassword

C#

3.

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

Dim proxy As MyWebService = New MyWebService()

C#

4.

MyWebService proxy = new MyWebService(); Assign the SOAP header object to the member variable of the proxy class representing the SOAP header.
VB

proxy.MyHeaderValue = mySoapHeader

C#

5.

proxy.MyHeaderValue = mySoapHeader 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. 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. 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.

2.

3.

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 clientbased 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 apppath

The Web server on which the Web service resides. The name of the Web application that is hosting the Web service. The name of the file where the Web service is defined.

webservicename.asmx
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. 2. Access the service help page for the Web service as just described. 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 an the response.

To test a Web service in a browser using HTTPGET


1. 2. Deploy your Web service to a Web server. For more information, see XML Web Service Publishing and Deployment. 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. The name of your virtual directory and the rest of the Web application path. The name of the Web service .asmx file.

Apppath

webservicename.asmx

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. 2. Deploy your Web service to a Web server. For more information, see XML Web Service Publishing and Deployment. 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. The name of your virtual directory and the rest of the Web application path. The name of the Web service .asmx file. 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) 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)

Apppath

webservicename.asmx Methodname

Parameter

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. 7.

http://<servername>/apppath/StockServices.asmx/GetStockQuote?tickerName=MSFT 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 HTTPPOST


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 Create an HTML page with a form that has its method attribute set to POST. Use the following format:

2.

3. 4. 5. 6. 7.

<form action='http://www.contoso.com/math.asmx/Subtract'> <input type="text" size="5" name='num1'\"></td> <input type="text" size="5" name='num2'\"></td> = <input type=submit value="Subtract"> </td> </form>

method=POST

Parameter

Value

Method

POST. If you want to test your Web service using HTTP-POST, use POST. URL to the Web service method. In the previous example, math.asmx is the Web service and Subtract is the Web service method. 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. The name of the Web service method parameter. Add as many text 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. Add a submit button so you can post the data back to the Web service method.

Action

type="text"

name='num1'

type=submit
8. 9.

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. 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 http://www.contoso.com/my.disco

/password:mypwd

/domain:mydomain

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. The location to create the file containing the discovery results. The default value is the current directory. (Optional) The user name to use when connecting to a Web server that requires authentication. (Optional) The password to use when connecting to a Web server that requires authentication. (Optional) The domain to use when connecting to a Web server that requires authentication. (Optional)

/out:location

/username:user

/password:mypwd

/domain:mydomain

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. 2. 3. 4. Create a proxy class for the Web service. Reference the proxy class in the client code. Create an instance of the proxy class in the client code. If anonymous access has been disabled for the Web application hosting the Web service, set the Credentials property of the proxy class. Call the method on the proxy class that corresponds to the Web service method with which you want to communicate.

5.

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 Web Language Tool (Wsdl.exe).

Parameter

Value

<url or path>

A URL or path to a service descrip Language). If you specify a file, supply a file th mywebservice.wsdl If you specify a URL, the URL mu created using ASP.NET, you can re service. For example, http://www.contoso.com/MyWebS

/language:language

The language the proxy class is gen Basic .NET, and JScript .NET, resp

/protocol:protocol

The protocol used to communicate and HTTP-POST. The default prot

/namespace:myNameSpace /out:filename

The namespace of the generated pr

The name of the file to create that c implements the Web service. (Opti

/username:username /password:password /domain:domain

The user name to use when connec

The password to use when connect

The domain to use when connectin

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 ter formatt ing (use) SOAP Body formatting (style) for RPC-based SOAP messages according to SOAP 1.1 Section 7s

SOAP Body formatting (style) Document-based SOAP messages

for

Literal based on an XSD schema for each parame ter Encode d SOAP 1.1 Section 5 encodi ng rules
Note:

SoapDocumentMethod or SoapDocum entService Use=Literal This is the default.

SoapRpcMethod or SoapRpc Service Use=Literal

SoapDocumentMethod or SoapDocum entService Use=Encoded

SoapRpcMethod or SoapRpc Service Use=Encoded This is the default.

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 codebetween 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 partsliterally 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 Serialization

SOAP

Messages

with

XML

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. P Also, SOAP 1.1 Section 5 encoding, combined with document or RPC style, prohibits the binding of data to XML attrib

Note:

If an abstract service class or client proxy class is generated from a WSDL document, the correct System.Xml.Seria 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 N not reflected in the resulting WSDL in the following cases: 1) When RPC-based SOAP messages are used, and 2) When Docum

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. 2. 3. A client invokes a method on the proxy class. A new instance of the SOAP extension is created on the client. 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. The Initialize method is invoked. The ChainStream method is invoked. The ProcessMessage method is invoked with SoapMessageStage set to BeforeSerialize. ASP.NET on the client computer serializes the arguments of the Web service method into XML. The ProcessMessage method is invoked with SoapMessageStage set to AfterSerialize. ASP.NET on the client computer sends the SOAP message over the network to the Web server hosting the Web service.

4. 5. 6. 7. 8. 9.

Server Side Receives a Request Message and Prepares a Response


1. 2. 3. ASP.NET on the Web server receives the SOAP message. A new instance of the SOAP extension is created on the Web server. 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. The Initialize method is invoked. The ChainStream method is invoked. The ProcessMessage method is invoked with SoapMessageStage set to BeforeDeserialize. ASP.NET deserializes the arguments within the XML. The ProcessMessage method is invoked with SoapMessageStage set to AfterDeserialize. 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.

4. 5. 6. 7. 8. 9.

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. 2. 3. 4. 5. 6. ASP.NET on the client computer receives the SOAP message. The ProcessMessage method is invoked with SoapMessageStage set to BeforeDeserialize. ASP.NET deserializes the XML into the return value and any out parameters. The ProcessMessage method is invoked with SoapMessageStage set to AfterDeserialize. ASP.NET passes the return value and any out parameters to the instance of the proxy class. 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 attribut this usage, see ASP.NET Web Site Paths

In This Section
Term Definition

@ Assembly Directive in XML Web Services

Links an assembly to an XML Web service during compilation.

@ WebService Directive in XML Web Services

Defines XML Web service specific (.asmx file) attributes used by 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

Name

The name of the assembly to link to the XML Web service.

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 applic 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.

CodeBehind

Specifies the source file implementing the XML Web service, when the class 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 methods 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 using using using using System; System.Data; System.Data.SqlClient; System.Web.Services; 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.

You might also like