Professional ASP.NET 1.1 [Electronic resources]

Alex Homeret

نسخه متنی -صفحه : 244/ 143
نمايش فراداده

Coding ASP.NET Web Services

The

.asmx file format is very straightforward. You have two options for exposing application logic as an ASP.NET Web service. Both options involve creating a file with a

.asmx extension:

Inline:The application logic exists within the

.asmx file.

Code-behind:The application logic exists outside the

.asmx file.

Using Inline Code

The first option (and the one used for our examples) is to code the application logic within the

.asmx file. This is similar to inline ASP.NET pages – we take the Fibonacci VB.NET or C# code, and create the corresponding

Fibonacci_vb.asmx and

Fibonacci_cs.asmx .

Using Code-Behind

We have a code-behind option for ASP.NET Web services just as that for ASP.NET pages. Code-behind is the default behavior for ASP.NET Web services created with Visual Studio.NET. Rather than the application logic existing within the

.asmx file, the application logic is stored in an external assembly.

To be able to reference an external assembly, the assembly must reside in the ASP.NET application's

bin directory. The

bin directory is a special directory used by the ASP.NET application, to which assemblies can be deployed and automatically registered.

To use the code-behind option, simply create a small ASP.NET Web service

.asmx file (which we'll call

Fibonacci_Codebehind.asmx ) that contains a single line:

<%@ WebService Codebehind="Fibonacci.vb" Class="Fibonacci" %>

You need an implementation of the

Fibonacci class in a separate assembly, either compiled and deployed in the ASP.NET application's

bin directory, or as part of an assembly named directly in the configuration file. Here's what the source would look like for the VB.NET version of the Fibonacci example (

Fibonacci.vb ):

Imports System

Imports System.Web

Imports System.Web.Services

Public Class Fibonacci

<WebMethod()> Public Function GetSeqNumber(fibIndex As Integer) As Integer

If (fibIndex < 2) Then

Return fibIndex

End If

Dim FibArray(2) As Integer

Dim i As Integer

FibArray(0) = 0

FibArray(1) = 1

For i = 2 To fibIndex

FibArray(1) = FibArray(1) + FibArray(0)

FibArray(0) = FibArray(1) - FibArray(0)

Next

Return FibArray(1)

End Function

End Class

You can simply use the following command line to compile the source into a .NET assembly:

vbc /t:library /r:System.Web.dll /r:System.Web.Services.dll Fibonacci.vb

The result of this is a single file,

Fibonacci.dll , which you need to place in a

bin directory that is located below the root directory of the application. You can easily deploy the assembly (

Fibonacci.dll ) so that both ASP.NET pages and web services may use it – it's simply a component with a

WebMethod attribute.

For example, if you decide that the functionality encapsulated within a class would make a great web service, you can simply make some minor changes to the assembly's application logic and create a one- line ASP.NET Web service

.asmx file (as shown), to enable the application logic as a SOAP-based endpoint.

As code-behind is the default behavior, the use of the

Codebehind statement in

Fibonacci.asmx is optional. Visual Studio .NET will use the

Codebehind attribute, but you can just as easily remove it and still achieve the same functionality, so long as the assembly contains the class the ASP.NET Web service references. Also, there is no difference in performance between using inline code or code-behind.

Further discussion of web services will use the inline style, unless otherwise noted. The only tangible benefits of using code-behind over the inline style are:

Code is compiled, and the source cannot be viewed once deployed.

Since the code-behind option is an assembly, the assembly can also be used in ASP.NET pages.

Both the inline and code-behind options share a common set of directives that are used to give ASP.NET special instructions when handling ASP.NET Web service requests.

The WebService Directive

Like ASP.NET pages, ASP.NET Web services support directives that instruct ASP.NET how to process the request. For example, when the Fibonacci examples were converted to ASP.NET Web services, we first added a directive at the top of the

.asmx file.

Using VB.NET, we wrote:

<%@ WebService Class="Fibonacci" %>

And using C#:

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

The

WebService directive is a required addition for all ASP.NET Web services. We'll look at the directive syntax, and then at the attributes we'll use most often.

Syntax

The directive syntax is identical to that of ASP.NET pages. The declaration is contained within

<%@ and

%> tags, contains a single directive, and may contain multiple attributes that apply to that directive:

<%@ DirectiveName Attribute="Value" %>

Or:

<%@ WebService Attribute="Value" Attribute="Value"%>

An ASP.NET Web service may contain multiple classes. However, only one of the classes can contain methods marked with

WebMethod attributes. This relationship is enforced with a

WebService directive attribute named

Class .

The Class Attribute

The

Class attribute is special, since it is required and forces us to always declare the

WebService directive within a

.asmx file. Fortunately, it's not complicated. The

Class attribute simply names the .NET class, whether inline or code-behind, that contains exposed methods or properties:

<%@ WebService Class="[Namespace.Class | Class]" %>

Using the Class Attribute

The

Fibonacci class must be named in the

Class attribute as the class contains the logic to be exposed:

<%@ WebService Class="Fibonacci" %>

If the

Fibonacci class existed within a namespace, you'd need to further qualify it:

<%@ WebService Language="C#" Class="MyMath.Fibonacci" %>

namespace MyMath{ public class Fibonacci{ // implementation }

}

In addition to the class attribute, you need to use the language attribute if you use a language other than the ASP.NET default language, VB.NET. To use C# as the language for the Fibonacci implementation, add a

Language directive:

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

That's all you need for coding simple ASP.NET Web services. Next, we'll look at the changes to be made to the application logic.

Application Code

Whether the application code for an ASP.NET Web service exists inline or in an assembly named through the code-behind support, the requirements for both resources remain the same. You must:

Include a reference to the

System.Web.Services namespace

Use attributes found within the

System.Web.Services namespace to identify those methods and properties that should be Web-callable

Optionally inherit from the

WebService base class

The System.Web.Services Namespace

The

System.Web.Services namespace contains classes that ASP.NET relies upon to enable ASP.NET Web services. Declare the use of this namespace in your ASP.NET Web service file differently depending upon the language you code the logic with. Using VB.NET, you would write:

Imports System.Web.Services

Using C#, you would write:

using System.Web.Services;

Importing the

System.Web.Services namespace is required, as this namespace contains the

WebMethod attribute.

The WebMethod Attribute

The

WebMethod attribute is the declarative code used to enable the application logic to be Web-callable. Thus, you'd be able to support serialization and deserialization of XML, mapping of XML values to correct types, and transporting of requests and responses – the 'infrastructure' that enables web services.

Again, the syntax of the attribute declaration varies from language to language. For VB.NET, declare the attribute inline with the function or property declaration:

<WebMethod> Public Function GetSeqNumber (fibIndex as Integer) as Integer

For C#, declare the attribute on the line preceding the method or property declaration:

[WebMethod]

public int GetSeqNumber(int fibIndex)

Using the WebMethod Attribute

The following is an example of using

WebMethod in VB.NET (

WebMethod1.asmx ) that returns the sum of two integers provided by the user:

<%@ WebService class="WebMethod1" %>

Imports System.Web.Services

Public Class WebMethod1

<WebMethod> Public Function Add(a As Integer, b As Integer) As Integer

Return a + b

End Function

End Class

Once the

WebMethod attribute is added, the

Add method is Web-callable, and when the

.asmx is requested through a browser, the method is available to select as shown in Figure 19-5:

Figure 19-5:

The last change you might need to make to the application code is to inherit from the

WebService base class (also contained in the

System.Web.Services namespace). You only need to do this if the web service requires the properties that the base class make available, as discussed next.

WebService Base Class

An ASP.NET Web service is part of the ASP.NET application it resides in. Just as we have application-specific configuration, session, and data for ASP.NET pages, we have the same capabilities for ASP.NET Web services.

You have a couple of choices for how you gain access to the ASP.NET-intrinsic objects, such as

Application or

Session . The easiest way to enable access to ASP.NET intrinsic objects within a web service is to inherit from the

WebService base class.

Using the WebService Base Class

In the following VB.NET code, we use the

Inherits keyword to inherit from the

WebService base class. This base class for example, gives access to an

Application property, just as we would expect to find when coding an ASP.NET page:

<%@ Webservice class="WebServiceBaseClass" %>

Imports System.Web.Services

Public class WebServiceBaseClass

Inherits WebService

<WebMethod> Public Sub SetApplicationState(state As String)

Application("state") = state

End Sub

<WebMethod> Public Function GetApplicationState() As String

Return Application("state").ToString()

End Function

End Class

This code (

WebServiceBaseClass1.asmx ) exposes two Web-callable methods:

SetApplicationState : Accepts a string value and sets an application key/value pair to the value passed in

GetApplicationState : Simply retrieves the value of the data set in

SetApplicationState

It's important to note that an ASP.NET page has access to the same application state memory that ASP.NET Web services do (the same is also true with

Cache and

Session ). Therefore, items added to application state memory, or to the cache, can be shared between the page and web services. This allows for powerful reuse. For example, an e-commerce site can load the store catalog into

Application state memory from the database a single time, and then both the ASP.NET pages and web services can share that data.

The

WebService base class adds five public (not Web-callable) properties that you are already familiar with from ASP.NET pages:

Application : Application state memory

Context : Instance class passed throughout the life of the request

Server : Server-intrinsic, provides us with access to methods such as

CreateObject

Session : Session state memory

User : Identity of the user making the request (security feature)

Classes do not need to inherit from the

WebService base class in order to be a functional web service – it is only for convenience. In fact, since an ASP.NET Web service is simply another ASP.NET resource, the

HttpContext , which contains the raw information for the request and response, is already available by default. So, classes that do not inherit from the

WebService base class can still implement similar functionality – for example, accessing the

Application intrinsic object.

Accessing Application State without Inheriting from the WebService Base Class

Let's take, for example, the same code as before, but without inheriting from

WebService :

<%@ Webservice class="WebServiceBaseClass" %>

Imports System.Web Imports System.Web.Services Public class WebServiceBaseClass <WebMethod()> Public Sub SetApplicationState(state As String)

Dim Application As HttpApplicationState

Application = HttpContext.Current.Application Application("state") = state End Sub <WebMethod()> Public Function GetApplicationState() As String

Dim Application As HttpApplicationState

Application = HttpContext.Current.Application Return Application("state").ToString() End Function End Class

In this example (

WebServiceBaseClass2.asmx ), we're using the web service's instance of the

HttpContext to retrieve the intrinsic

Application object. This means we have to import the

System.Web namespace in the code, since

HttpContext is defined in the

System.Web namespace.

The

HttpContext instance can then be used to access the intrinsic

Application object, which is set to a local variable of type

HttpApplicationState named

Application . The code then uses the intrinsic

Application object in an identical manner to the code that inherited from the

WebService base class.

Since a class can only inherit from a single base class, the advantage of not using the

WebService base class can be seen when inheriting from a different class.

You now have all the basic knowledge necessary for building ASP.NET Web services. You could now skip directly to consuming ASP.NET Web services. However, there are more options available in building ASP.NET Web services. For example, the

WebMethod attribute has configurable properties, and it's not the only attribute you can use.

Before looking at these options, we need to talk a little about the protocols and data types supported by web services.