ASP.NET

Creating an ASP.NET Web Service

Let's say that an online brokerage firm wants to provide a Web service to its customers. It could accomplish this by writing an ASP.NET Web application. However, the firm wants to extend the reach of its services so that they can be leveraged from other applications. For example, a portal site such as MSN or Yahoo! might want to provide these services but might lack the expertise or the desire to take on the burden of building the services themselves.

Instead, the portal site can provide a UI to the customer and use the brokerage firm's Web service as the back end. At worst, the portal will retain the customer within its site and potentially increase its ad revenue. At best, the portal can charge an incremental amount on top of the fees provided by the brokerage firm. Either way, it is potentially a win-win situation for the portal company and the brokerage firm.

In this chapter, I build the Securities Web service, which allows the client to perform actions such as obtaining a quote for a particular stock, bond, or mutual fund. The individual methods will contain skeleton implementations that let you focus on the mechanics of building Web services using ASP.NET.

The first thing I need to do is define the endpoint for the Securities Web service. A Web service is defined by an .asmx file, which serves as the endpoint for the Web service. Calls made to .asmx files are intercepted and processed by the ASP.NET runtime.

The implementation of the Web service is encapsulated within a class. The class definition can either appear inline within the .asmx file or be contained in a separate dynamic link library (DLL). The .asmx page needs to contain information that the runtime can use to locate the class.

Each .asmx page contains a directive at the top of the page that specifies where and in what form the implementation of the Web service can be found. This directive is used by the ASP.NET runtime to bind the Web service to a class that contains the implementation.

Here is an example in which the implementation of the Web service is contained within the .asmx file:

<%@ WebService Language="c#"  %> namespace BrokerageFirm {     // Inline definition of the Securities class     public class Securities     {         Implementation...     } }

The Class attribute contains the fully qualified name of the class that implements the Web service. If the code resides within the .asmx file, you must set the Language attribute, which specifies the language in which the code was written.

The first time the Web service is accessed, the ASP.NET runtime will use the Language attribute to compile the code with the appropriate compiler. Thus, even if the code implementing the Web service is contained within the .asmx file, it will always be executed as compiled machine code.

Out of the box, ASP.NET is configured to dynamically compile code written in C#, Visual Basic, Visual Basic .NET, and JScript .NET. You can configure additional languages within the web.config file or the machine.config file. The following is the compilation section of the machine.config file found in the C:\WINNT\Microsoft.NET\Framework\version\CONFIG directory:

<!-- compilation Attributes:   tempDirectory="directory"   debug="[true false]"   strict="[true false]"   explicit="[true false]"   batch="[true false]"   batchTimeout="timeout in seconds"   maxBatchSize="max number of pages per batched compilation"   numRecompilesBeforeAppRestart="max number of recompilations    before appdomain is cycled"   defaultLanguage="name of a language as specified    in a <compiler/> tag below" --> <compilation debug="false" explicit="true" defaultLanguage="vb">   <compilers>     <compiler language="c#;cs;csharp" extension=".cs"      type="Microsoft.CSharp.CSharpCodeProvider, System,      Version=1.0.xxxx.0, Culture=neutral,      PublicKeyToken=1234567890abcde1" />     <compiler language="vb;visualbasic;vbscript" extension=".vb"      type="Microsoft.VisualBasic.VBCodeProvider, System,      Version=1.0.xxxx.0, Culture=neutral,      PublicKeyToken=1234567890abcde1" />     <compiler language="js;jscript;javascript" extension=".js"      type="Microsoft.JScript.JScriptCodeProvider, Microsoft.JScript" />   </compilers>   <assemblies>     <add assembly="mscorlib"/>     <add assembly="System, Version=1.0.xxxx.0,      Culture=neutral, PublicKeyToken=1234567890abcde1"/>     <add assembly="System.Web, Version=1.0.xxxx.0,      Culture=neutral, PublicKeyToken=1234567890abcde1"/>     <add assembly="System.Data, Version=1.0.xxxx.0,      Culture=neutral, PublicKeyToken=1234567890abcde1"/>     <add assembly="System.Web.Services, Version=1.0.xxxx.0,      Culture=neutral, PublicKeyToken=1234567890abcde1"/>     <add assembly="System.Xml, Version=1.0.xxxx.0,      Culture=neutral, PublicKeyToken=1234567890abcde1"/>     <add assembly="System.Drawing, Version=1.0.xxxx.0,      Culture=neutral, PublicKeyToken=1234567890abcde1"/>     <add assembly="*"/>   </assemblies> </compilation>

As you can see, the default language is Visual Basic .NET (vb), so my C# example must set the Language attribute to c#, cs, or csharp.

The compilation section also includes a list of assemblies that are referenced by code within the .asmx file. If the Securities Web service were to reference entities from an assembly other than those listed in the preceding code, I could add a new machine-wide reference to my machine.config file or an application-wide reference to my web.config file.

The last add element specifies a wildcard for the assembly name. If an assembly is referenced within an .asmx file that was not previously listed, the ASP.NET runtime will search for the assembly. (See the product documentation for the exact search order.)

The class implementing the Web service can also reside within a compiled assembly. By convention, the assembly is placed in the Web application's bin directory because this directory is always included in the search path of the runtime. This is the default configuration for Web services created using Visual Studio .NET. The following is the WebService directive that Visual Studio .NET creates automatically:

<%@ WebService Language="c#" Codebehind="Service1.asmx.cs"  %>

As is typical in the Visual Studio product line, most of the attributes defined in the WebService directive are used by the editor and are ignored by the runtime. As I mentioned, you must specify the Language attribute only if the implementation of the Web service resides within the .asmx file. In addition, the code-behind file is always ignored by the ASP.NET runtime and is used by Visual Studio .NET to bring up the appropriate source code file when you select View Code within the IDE.

One other potential gotcha is that Visual Studio .NET will only partially maintain this file. When you rename the .asmx file to something more meaningful, Visual Studio .NET will automatically rename the associated code-behind file and update the WebService directive accordingly. As a common practice, I also rename the class that implements the Web service to match the name of the .asmx file.

Unfortunately, Visual Studio .NET will not automatically update the Class attribute. If you rename the class, you have to manually update this attribute yourself. Furthermore, double-clicking the .asmx file to update this attribute will display the design surface, not the file text. Visual Studio .NET does not provide the same buttons shown on an .aspx file's design surface that allow you to switch between the design view and the underlying text of the file. You have to right-click the file, choose Open With, and then select Source Code (Text) Editor.

Now that I have discussed the two options—placing the implementation for your Web service within the .asmx file or within its own assembly—I am sure you are wondering which one you should use. Well, as with most design decisions, it depends. Placing the code within the .asmx file provides the simplest means of deployment because ASP.NET will compile the code dynamically for you. However, deploying the implementation within an assembly ensures that your code will not contain compilation errors. Also, if you are deploying the Web service outside the confines of your data center, others will not have access to the source code.

Another potential advantage of having the implementation of your Web service reside within an assembly is that it can be directly referenced by other applications hosted on the same machine. For example, suppose I provide an HTML-based UI that allows my customers access to the functionality of the Securities Web service. If the class containing the implementation of the Web service is in its own assembly, the Web application can reference the assembly and directly access the Web service class. This avoids the unnecessary overhead of accessing the functionality remotely.

You should take this approach with caution, however. Some Web services rely on services provided by the ASP.NET runtime to function correctly. For example, a Web method might set an attribute stating that the ASP.NET runtime must create a new transaction on its behalf. Because ASP.NET is responsible for ensuring that a transaction is created, no transaction will be created if the class implementing the Web service is accessed directly.

Regardless of which option you choose, the code for implementing the Web service will be the same. For starters, I will implement one method within my Securities Web service, InstantQuote. Plenty of services on the Web give quotes on the price of a company's stock. However, these quotes are often time delayed and can be more than 20 minutes old. InstantQuote will use an extremely complex algorithm to obtain the price a security is trading at on the floor. Following is the implementation.

using System; using System.Web.Services; namespace BrokerageFirm {     public class Securities : WebService     {         [WebMethod]         public double InstantQuote(string symbol)         {             double price = 0;             switch(symbol)             {                 case "MSFT":                     price = 197.75;                     break;                 case "SUNW":                     price = 2.50;                     break;                 case "ORCL":                     price = 2.25;                     break;             }             return price;         }     } }

All right, so the algorithm is not that complex. What do you expect with an example? The important thing to note is that the implementation of the Web service is a standard public class declaration with a WebMethod attribute decorating the InstantQuote method. This class declaration can be either compiled into an assembly or placed as is within the .asmx file, and it is the same whether it is contained within the .asmx file or compiled into a separate DLL.

Each method that is intended to be exposed by the Web service must be public and must be decorated with the WebMethod attribute. This tells the ASP.NET runtime to expose the method as publicly accessible. From this point on, I will refer to a method of a class decorated with the WebMethod attribute as a Web method.

When you decorate a method with the WebMethod attribute, you can also set various properties that modify the behavior of the ASP.NET runtime. Table 6-1 lists the properties exposed by the WebMethod attribute.

Table 6-1  Properties of the WebMethod Attribute

Property

Description

BufferResponse

Specifies whether the response to the client should be buffered.

CacheDuration

Specifies the amount of time, in seconds, that a response will be cached in memory by the Web server for a given response. The default is 0.

Description

Specifies the value of the description element under each operation element within each type definition within the ASP.NET-generated WSDL document.

EnableSession

Specifies whether the ASP.NET session state services will be available for the implementation of the method.

MessageName

Specifies the name of the method exposed by the Web service. Specifically, it sets the name of the element within the body of the SOAP message that contains the parameters as well as the suffix of the SOAP action. It also specifies the prefix of the names of the message, input, and output elements within the ASP.NET-generated WSDL document.

TransactionOption

Specifies the transactional support that should be provided for the implementation of the method. The method can serve only as the root of a transaction and cannot participate in the caller's transaction.

The ASP.NET page framework also provides the WebService attribute. This attribute is set at the class level and is used to modify properties of the Web service as a whole. Changes made via the WebService attribute will be reflected in the Web service's WSDL document. Table 6-2 lists the properties exposed by the WebService attribute.

Table 6-2  Properties of the WebService Attribute

Property

Description

Description

Specifies the description element under the service element within the ASP.NET-generated WSDL document.

Name

Specifies the name of the service element within the ASP.NET-generated WSDL document. It also specifies the prefix for the names of the portType, binding, and port elements.

Namespace

Specifies the target namespace for the WSDL document as well as the schema document that defines the structures for encoding the parameters within the body of a SOAP message. It also specifies the prefix of the namespace for the schema that contains any custom types defined by the Web service and the value of the SOAP action.

Now that I have defined the Securities Web service, let's talk about how clients can access it.



Building XML Web Services for the Microsoft  .NET Platform
Building XML Web Services for the Microsoft .NET Platform
ISBN: 0735614067
EAN: 2147483647
Year: 2002
Pages: 94
Authors: Scott Short

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