WebMethod and WebService Attributes


Although the WebMethod attribute will be used most often when authoring ASP.NET Web services, there are other attributes at your disposal that provide additional functionality.Apart from marking a method or property with an attribute, you can set some attribute properties that influence the behavior of attributes, and which in turn affect the target of the attribute. We'll use the following syntax to set attribute properties. Using VB.NET, you would write:

  ... <AttributeName(PropertyName:="Value")> ...  

Note the colon after PropertyName:="Value" . This syntax is only required for VB.NET. Using C#, you would write:

  [AttributeName(PropertyName="Value")]  

We won't discuss all the available attributes here “ we'll concentrate on the WebMethod and WebService attributes. Let's take a detailed look at the WebMethod attribute.

The WebMethod Attribute

The WebMethod attribute is used to mark a method or property as Web-callable, and is represented by the WebMethodAttribute class. There are six properties on the WebMethod attribute that you can manipulate:

  • Description

  • EnableSession

  • MessageName

  • TransactionOption

  • CacheDuration

  • BufferResponse

Let's examine each of these in turn.

Commenting the WebMethod

The Description property is used to provide a brief description of the functionality of the Web-callable method or property. Using VB.NET, you could write:

  ...<WebMethod(Description:="[string]")>...  

Using C#, you could write:

  [WebMethod(Description="[string]")]  

The value of the Description property is added to the WSDL and to the web service Help page.

Using the Description Property

If you add a Description property to the Fibonacci example and then request this through the browser, the description shows up under the link for the Web-callable method:

 <%@ WebService Language="C#" class="Fibonacci" %> using System.Web.Services; public class Fibonacci : WebService{  [WebMethod(Description="Returns value of index into Fibonacci series")]  public int GetSeqNumber(int fibIndex){            if (fibIndex < 2)          return fibIndex;            int[] FibArray = {0,1};            for (int i = 1; i< fibIndex; i++){          FibArray[1] = FibArray[0] + FibArray[1];          FibArray[0] = FibArray[1] - FibArray[0];       }            return FibArray[1];    } } 

When the .asmx file is requested by a browser, the screen shown in Figure 19-7 appears:

click to expand
Figure 19-7:

If you view the Service Description (WSDL), you can also see the description as shown in Figure 19-8:

click to expand
Figure 19-8:

The entries in the Description property may contain HTML formatting. This formatting is then used to display a description in the Help page. However, keep in mind that the description text is entered into the WSDL. Other applications may consume the WSDL, and they might not understand the HTML tags found in the description.

Enabling Session State

Classes that inherit from the WebService base class or use the HttpContext can take advantage of session state to maintain state between calls. Session state, however, involves additional overhead, and is bound to the HTTP protocol since it uses HTTP cookies. Although SOAP is theoretically transport- independent, it relies on the transport protocol for application functionality when HTTP cookies are used. If you moved the SOAP message to SMTP, you wouldn't have the HTTP cookies functionality available.

By default, session state is disabled. To enable session state support, you can use one of the WebMethod properties, EnableSession . Using VB.NET, you would write:

  ...<WebMethod(EnableSession:="[true/false]")>...  

Using C#, you would write:

  [WebMethod(EnableSession="[true/false]")]  

To enable session state, EnableSession is set to true (it is false by default).

One caveat is that the session state is only valid as long as the caller presents the same session ID . In the next chapter, when we build proxies to use against our web services, session state is available only for the duration of the existence of the proxy instance. The HTTP cookie is never stored on disk, and a new session is created for each new proxy instance, since the proxy, by default, doesn't persist the session cookie containing the ID . We'll also look at an example of how to persist and reuse the session cookie.

Aliasing Web Method Names

The MessageName property is used to alias method or property names. The most common use of the MessageName property is to uniquely identify polymorphic methods within a class that is to be marked as web-callable. Using VB.NET, you would write:

  ...<WebMethod(MessageName:="[string]")>...  

Using C#, you would write:

  [WebMethod(MessageName="[string]")]  
Using the MessageName Property

Here's a snippet of C# code that has two Add methods that differ only by method signature:

  ...   [WebMethod]   public int Add(int a, int b){   return a+b;   }   [WebMethod]   public int Add(int a, int b, int c){   return a+b+c;   }   ...  

This generates an exception when requested through the browser. Both Int32 Add(Int32, Int32, Int32) and Int32 Add(Int32, Int32) use the message name Add . You can use the MessageName property of the custom WebMethod attribute to specify unique message names for the methods. The problem is that ASP.NET cannot differentiate between the two methods, and requires the use of the MessageName property to differentiate between the method names:

 ... [WebMethod] public int Add(int a, int b){    return a+b; }  [WebMethod(MessageName="Add2")]  public int Add(int a, int b, int c){    return a+b+c; } ... 

Additionally, the WSDL that is generated must also be able to uniquely identify the element name when it is used to construct a message. When you use the MessageName property, this is reflected in your WSDL, as shown in Figure 19-9:

click to expand
Figure 19-9:

The MessageName property simply aliases our method name.

Building Transacted Web Services

ASP.NET Web services support transactions, but only ones that the web service originates. A transaction cannot be started by another application and then flow into a web service.

Using VB.NET, you would write:

  ...<WebMethod(TransactionOption:="[TransactionOption]")>...  

Using C#, you would write:

  [WebMethod(TransactionOption="[TransactionOption]")]  
Using the TransactionOption Property

Suppose you had a banking transaction, in which the client makes a web service remote call to a method named DebitAccount , the transaction started by the client cannot be stretched through the web service remote call. The schematic diagram is shown in Figure 19-10:

click to expand
Figure 19-10:

In this diagram, a Bank Application begins a transaction (Tx1). It then calls a web service, which begins another transaction (Tx2). The transaction (Tx1) started by the Bank Application does not flow through the web service.

If the web service transaction (Tx2) succeeds, it will allow the application's transaction (Tx1) to continue. However, failure of the DebitAccount call will fail the application's transaction. The DebitAccount call, which provides the web service, can also choose to participate in a transaction, but it is a new transaction context, not the transaction context started by the calling application.

The options for using transacted web methods are:

  • Disabled : We cannot control automatic transactions on the object.

  • NotSupported : The object does not run within the scope of a transaction, irrespective of whether a transaction already exists or not.

  • Supported : If a transaction exists, the object runs in the context of that transaction. If there is no existing transaction, the object runs without one.

  • Required : The object requires a transaction in order to execute. It will either use an existing transaction, or create a new one if none exists. Required is the default.

  • RequiresNew : The object requires a new transaction, so a new transaction is created for each request.

Calling SetComplete or SetAbort in code is no longer necessary. Simply raising an exception is considered as a SetAbort , and successful completion of the call is considered a SetComplete .

Note

The SetAbort and SetComplete methods are used to indicate to MTS or COM+ whether a transaction completed or failed.

Caching Web Services

Like ASP.NET pages, ASP.NET Web services support output caching. Output caching allows for the result of a particular resource to be saved to a cache rather than executed on each request. High traffic resources whose data changes infrequently can take advantage of caching for better scalability and performance.

The use of caching for web services is configured on a method-by-method basis through the use of the WebMethod attribute's CacheDuration property. Using VB.NET, you would write:

  ...<WebMethod(CacheDuration:=[int])>...  

Using C#, you would write:

  [WebMethod(CacheDuration=[int])]  
Using the CacheDuration Property

The following is a VB.NET example use of CacheDuration ( WebMethodCacheDuration.asmx ):

  <%@ WebService class="CacheDurationExample" %>     Imports System   Imports System.Web.Services     Public Class CacheDurationExample   <WebMethod(CacheDuration:=30)> Public Function TimeLastCached As String   Return DateTime.Now.ToString("r")   End Function   End Class  

This simple sample returns the value of the current time on its first execution. This result is then cached for 30 seconds, and the same result is returned until the cached entry has expired (30 seconds after the initial call), at which time the code will execute again.

Although this simple example highlights that caching is working, what would happen in a more complex example in which the WebMethod had parameters? You obviously wouldn't want to serve the same response for all requests ; you'd rather vary the response on the basis of the request.

For example, if the result that the web service returned from a SQL Server database was dependent on one of the parameters of the WebMethod , you might not only want to cache the result (for the performance gain), but would also want different variations of that cached result based on the supplied parameters. This is supported by default.

Let's take a look at a VB.NET code sample to illustrate this better ( WebMethodCacheData.asmx ):

  <%@ WebService class="DataExample" %>     Imports System.Web.Services   Imports System.Data   Imports System.Data.SqlClient   Public Class DataExample : Inherits WebService   <WebMethod(CacheDuration:=30)> Public Function _   GetDataSet(City As String) As DataSet   If (Application("ProductData" + City) Is Nothing) Then   Application("ProductData" + City) = LoadDataSet(City)   End If     Return CType(Application("ProductData" + City), DataSet)   End Function     Private Function LoadDataSet(City As String) As DataSet   Dim dsn As String   Dim sql As String     dsn = "server=localhost;uid=sa;pwd=;database=pubs"   sql = "SELECT * FROM Authors WHERE City = '" + City + "'"   Dim myConnection As New SqlConnection(dsn)   Dim myCommand As New SqlDataAdapter(sql, myConnection)     Dim products As New DataSet     myCommand.Fill(products, "products")     Return products   End Function   End Class  
Note

You might have to alter the server name in the preceding code to reflect your own database.

Here, a GetDataSet WebMethod accepts a single parameter: City . The result from the request will be output cached. The ASP.NET Web service is executed once and served statically on subsequent requests for 30 seconds, and the cache will vary based on the different value for City . If you have a request where the value of City is Dallas , the web service will execute once and the result will be cached. If there is another request for Dallas within the allotted time period of 30 seconds, it will be served from the cache “ the ASP.NET Web service does not need to execute and query the database.

This can be a serious performance enhancement, but should be used wisely “ only items that vary by a few parameters are good candidates for web services output caching.

Buffering the Server Response

Buffering allows the server to buffer the output from the response, and transmit it only once the response is completely buffered. This might not be optimal for long running methods “ you'd rather want to send the response as you receive it rather than wait for the complete response.

By default, ASP.NET Web services buffer the response before sending it, as this is usually most optimal for the server. However, the BufferResponse property allows you to configure ASP.NET Web services to not buffer the response. By default, this property is set to true .

Using VB.NET, you would write:

  ...<WebMethod(BufferResponse:="[truefalse]")>...  

Using C#, you would write:

  [WebMethod(BufferResponse="[truefalse]")]  

The other attribute we'll look at, the WebService attribute, gives additional control over the class that contains the Web-callable methods rather than the individual methods .

The WebService Attribute

The WebService attribute is used to configure properties for the class “ rather than the method or property “ named in the WebService directive. These properties apply to the web service Help page as well as the WSDL. It does not , however, mark the methods within the class as Web-callable.

There are three properties of the WebService attribute that you can manipulate:

  • Description

  • Namespace

  • Name

Commenting the Web Service

The Description property is used to provide a brief description of the functionality of the class that contains Web-callable methods and properties. It's similar to the Description property of the WebMethod attribute, but it's a description for the entire class, not individual methods and properties. Using VB.NET it would be written as:

  <WebService (Description:="[string]")> Public Class [Class Name]  

Using C# it would be written as:

  [WebService(Description="[string]")]   public class [  Class Name  ]  
Using the Description Property of the WebService Attribute

The value from the Description property is added to the WSDL, and is also added to the output generated when the ASP.NET Web service is requested by the browser. For example, you can add a Description property to the Fibonacci example ( WebServiceDescription.asmx ):

 <%@ WebService Language="C#" class="Fibonacci" %> using System.Web.Services;  [WebService(Description=   "This class contains methods for working with Fib series")]  public class Fibonacci : WebService{    [WebMethod]    public int GetSeqNumber(int fibIndex){            if (fibIndex < 2)          return fibIndex;       int[] FibArray = {0,1};       for (int i = 1; i< fibIndex; i++){          FibArray[1] = FibArray[0] + FibArray[1];          FibArray[0] = FibArray[1] - FibArray[0];       }       return FibArray[1];    } } 

The output would be as shown in Figure 19-11:

click to expand
Figure 19-11:

In the WSDL, it would appear as shown in Figure 19-12:

click to expand
Figure 19-12:

Controlling the Namespace

XML uses namespaces to uniquely identify sections of an XML document. Multiple documents can share markup vocabularies to describe particular regions of information. For example, in the case of two XML documents that both contain an <Add> element, how can software differentiate between the two elements in the composite document?

Organizations may qualify their markup vocabulary with a universal name that is unique to their markup vocabulary through the use of XML namespaces.

The default namespace that ASP.NET assigns to ASP.NET Web services is http://tempuri.org. tempuri.org will be discussed in the WSDL section of the next chapter. For now, the Namespace property of the WebService attribute can be used to change the namespace value to a value of your choosing.

Using VB.NET, it would be written as:

  <WebService(Namespace:="[string]")> Public Class [Class Name]  

Using C#, it would be written as:

  [WebServiceNamespace="[string]")] public class [Class Name]  
Using the Namespace Property

If you viewed the WSDL from either the VB or C# Fibonacci Web service, you would see http://tempuri.org/ used for the value of the namespace. To change the namespace to http://rhoward/Fibonacci / , you could make the following change to the code ( WebServiceNamespace.asmx ):

 <%@ WebService Language="C#" class="Fibonacci" %> using System.Web.Services;  [WebService(Namespace="http://rhoward/Fibonacci/")]  public class Fibonacci : WebService{         [WebMethod]    public int GetSeqNumber(int fibIndex){            if (fibIndex < 2)          return fibIndex;       int[] FibArray = {0,1};            for (int i = 1; i< fibIndex; i++){          FibArray[1] = FibArray[0] + FibArray[1];          FibArray[0] = FibArray[1] - FibArray[0];       }            return FibArray[1];    } } 

Now the WSDL appears as shown in Figure 19-13:

click to expand
Figure 19-13:

This affects what our SOAP message looks like, as shown in Figure 19-14:

click to expand
Figure 19-14:

Changing the Name of the Web Service

When the WSDL is generated for an ASP.NET Web service, the name of the class is used for the service name value within the WSDL. When a proxy uses the WSDL and builds a proxy class, the name of the class generated corresponds to the name value of service . The Name property of the WebService attribute allows you to override the default value.

Using VB.NET, you would write:

  <WebService(Name:="[string]")> Public Class [  Class Name  ]  

Using C#, you would write:

  [WebService(Name="[string]")]  
Using the Name Property

If you viewed the WSDL of the Fibonacci class, you would see the output as shown in Figure 19-15:

click to expand
Figure 19-15:

If you set the Name value to WebServiceExample in the WebService attribute (as in WebServiceName.asmx ):

  [WebService(Name="WebServiceExample")]  

You would see the change in the WSDL as shown in Figure 19-16. All instances of Fibonacci in the WSDL have been replaced with WebServiceExample .

click to expand
Figure 19-16:

This property is useful if you want to control the name of the class that proxies generate, as tools that consume the WSDL to build the proxy will now build a WebServiceExample class as the proxy instead of building a class with the name Fibonacci .

Now that we've seen the two attributes used most often to build ASP.NET Web services, let's discuss how to go about designing web services, and look at some more advanced issues involved.




Professional ASP. NET 1.1
Professional ASP.NET MVC 1.0 (Wrox Programmer to Programmer)
ISBN: 0470384611
EAN: 2147483647
Year: 2006
Pages: 243

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net