Understanding .NET (2nd Edition)

In the last ten years, nothing has had a bigger impact on software development than the World Wide Web. Browser-based applications became the norm as the world adopted this new environment. Yet the Web has also affected applications that don't use browsers through the advent of Web services. Defined by a group of related specifications, Web services provide a way for any kind of software to interact with any other kind of software using standard communication protocols.

Web services let diverse software interact over the Web

ASP.NET Web Services allow .NET Framework applications to use this style of communication. Commonly known as ASMX, after the file extension it uses, this technology provides a straightforward way for developers to create applications that expose and invoke Web services. Given this, understanding ASMX first requires a grasp of Web services basics, described next.

Web Services Fundamentals

The core technologies of Web services can be broken down into three separate areas, each addressing a particular aspect of the problem. Those areas are:

  • Describing information sent over the network. Invoking a remote operation commonly involves passing in information and getting back some kind of result. With Web services, this information is described using XML, today's lingua franca for describing data.

  • Defining Web service capabilities. Some mechanism must exist to allow the provider of a Web service to specify the technical details of exactly what services are offered. As with other types of services, it makes sense to group related operations into interfaces, then provide some way to describe each of those operations. For Web services, this can be done using the Web Services Description Language (WSDL), commonly pronounced "wizdel." Each WSDL-defined interface contains one or more operations, and WSDL itself is defined using XML.

  • Accessing Web services. Once an interface has been defined, clients must use some protocol to invoke the operations in that interface. Although WSDL explicitly allows specifying different protocols for invoking the operations in an interface, the standard choice is SOAP. This universally supported protocol provides a way to identify which operation to invoke, convey that operation's inputs as XML-defined data, and return any outputs, also as XML-defined data. SOAP defines only a simple envelope for conveying this information, one that can be carried in various ways. For example, SOAP calls can be carried on the Hypertext Transfer Protocol (HTTP), directly over TCP, or in other ways.

Web services rely on XML, WSDL, and SOAP

Several other Web services technologies have also been defined. To locate services, for example, developers and applications can potentially rely on Universal Description, Discovery, and Integration (UDDI). Using UDDI, providers of Web services can advertise their offerings in a standard way, allowing clients to learn what services each provider offers and letting creators of client software learn what they need to know to build those clients. UDDI is an interesting idea, but the technology isn't widely used today. Still, Microsoft includes support in Windows for creating a UDDI registry, and developers who create .NET Framework applications can use this or other UDDI implementations if they wish.

UDDI lets developers and software find services

A number of extensions to SOAP have also been defined. Known collectively as the WS-* specifications, each defines how to solve a particular kind of communication problem. The WS-Security specification, for instance, lays the groundwork for secure SOAP-based communication, while WS-AtomicTransaction addresses the challenge of achieving distributed transactions via SOAP. An extension to ASP.NET Web Services known as Web Services Enhancements (WSE) provides an implementation of WS-Security and a few other WS-* specifications. A more complete implementation of these specifications (and much more) is contained in Windows Communication Foundation (WCF), described briefly at the end of this chapter.

The WS-* specs add extensions to SOAP for security and more

Each of these technologies was created by groups of vendors and users working together. XML, for instance, was created by a large group working under the auspices of the World Wide Web Consortium (W3C), while WSDL was created primarily by Microsoft and IBM. SOAP comes from a group somewhere in between in size, with Microsoft, IBM, DevelopMentor, and several others playing a role. The key point to notice about the origin of each Web services technology is that none of them is a single-vendor solution. Because of this broad support, Web services based on XML, WSDL, and SOAP can be used across virtually all platforms, languages, and object models.

All of these technologies have broad vendor support

Perspective: Creating Common Connections: Why COM and CORBA Couldn't

Wouldn't it be nice if all kinds of software on all kinds of systems could snap together like Legos? The technical problems that stand in the way of this goal aren't really all that hard. What has stopped us in the past is will: Users have had it, but vendors haven't. And in this case, vendors rule.

Microsoft, for example, was quite successful in creating snap-together software for Windows platforms. The Component Object Model (COM) made this possible even for software running on different machines. But other major vendors never seriously supported COM, and one could debate whether Microsoft ever really wanted them to. Similarly, the Object Management Group's (OMG) CORBA was intended to connect all kinds of applications on all kinds of systems. Two problems doomed the OMG's efforts, though. First, their standards weren't complete enough, so organizations were all but forced to stick with a single CORBA vendor to make their systems communicate. And second, Microsoft didn't support CORBA.

Today, however, a technology exists with both the right technical merits and, more important, complete vendor agreement. That technology, of course, is Web services. SOAP and its fellow travelers have emerged as the standard mechanism that all software can use to expose its services to the outside world. The decades-long battle over what protocol should be used to connect applications is over: SOAP has won.

ASP.NET Web Services Applications: Basics

Any application that communicates via Web services must expose one or more interface definitions expressed in WSDL, and it must also allow the operations in those interfaces to be invoked using SOAP. A technology that allows creating these applications should make doing these things as natural as possible for developers. Achieving this is a primary goal of ASP.NET Web Services.

ASP.NET Web Services allows creating applications that communicate through Web services

As with most distributed computing technologies, ASP.NET Web Services distinguish between clients and servers. Creating a basic server, the first thing that most developers do, is simple. Because it's part of ASP.NET, the ASP.NET Web Services technology relies on pages to implement services. As shown in Figure 7-1, the files containing those pages have an .asmx extension (rather than the .aspx extension used by browser-oriented ASP.NET applications), and they don't contain any HTML. Apart from an occasional directive, they're just code. No HTML is required because a Web service is accessed by software, not by people, so it doesn't display a user interface. Ultimately, of course, there is often some human being whose request triggered the Web service, but the interface that person uses to accomplish this is outside the scope of the Web service itself. Web services don't define GUIs, and so .asmx pages don't contain HTML.

Figure 7-1. An ASP.NET Web services application is built using .asmx pages, which produce managed objects when they're accessed.

ASP.NET Web Services applications use .asmx pages

Still, the process of accessing an .asmx page is similar to what happens when an .aspx page is accessed. A client makes a request for the page via SOAP (step 1). Note that, unlike an .aspx page, the client for an .asmx page is generally an application rather than a vanilla Web browser. The named file is loaded into an app domain in the ASP.NET worker process[1], then executed (step 2). As with an .aspx page, everything in the .asmx file becomes a managed objectit's a .NET Framework application like any other. The result of executing the page is then returned to the client, again via SOAP (step 3).

[1] It's also possible to run ASP.NET Web Services applications in other processesusing IIS isn't strictly required.

To expose a method contained in an .asmx file as a Web service, all that's required is to insert the attribute WebMethod in front of the method declaration. When the file is compiled, this attribute will be stored in the metadata of the resulting assembly, like all attributes. Its presence signals to the ASP.NET infrastructure that this method should be made accessible as a Web service. To give you a sense of how simple this is to do, think back to the Compute class used in Chapter 4's language examples. An .asmx file that exposed the C# version of that class's two methods as Web services might look like this:

<%@ WebService Language="c#" %> using System.Web.Services; public class Compute { [WebMethod] public int Factorial(int f) { int i; int result = 1; for (i=2; i<=f; i++) result = result * i; return result; } [WebMethod] public double SquareRoot(double s) { return System.Math.Sqrt(s); } }

The WebMethod attribute is used to expose a method in a class as a Web service

The file's contents begin with a WebService directive. Similar in form to the Page directive shown in Chapter 5, this line indicates that the Web service specified in this .asmx page is written in C# and defines a class named Compute. Next appears a using statement for the namespace System.Web.Services, followed by the definition of the Compute class. This class is virtually identical to what was shown in Chapter 4. For simplicity, this version doesn't use an interface, although that's not an important distinction here. What is important is the presence of the WebMethod attribute before both of the class's methods. This attribute is defined in System.Web.Services, hence the using statement that precedes this class, and it's the only addition required to expose these methods as Web services. (Note, however, that only public methods can be marked with the WebMethod attribute.)

Version 2.0 of ASP.NET Web Services also allows applying the WebMethod attribute to methods defined in an interface, then implementing that interface with a class as usual. This option clearly separates the definition of the operations this service exposes, commonly known as its contract, from the implementation of those operations. Whichever option is chosen, ASP.NET automatically generates a WSDL interface expressing the contract in a form that can be read by any Web services client on any system.

Methods marked with the WebMethod attribute can also appear in interfaces

Web services applications are deployed as ASP.NET applications, just like applications built using .aspx pages. As with .aspx pages, an .asmx page is compiled when it is first accessed by a client. The resulting assembly is stored on disk and then reused until the .asmx page that produced it is modified. Changing this page results in an automatic recompile the next time the page is accessed.

Web services applications are ASP.NET applications, too

When an .asmx page is accessed through a browser, ASP.NET uses reflection to learn what Web services it exposes. ASP.NET uses this knowledge to create a Web page that allows learning about these services. The Web page provides a way to invoke the services, examples of what calls to these services look like on the wire, and even a full WSDL definition of the Web services defined in this .asmx page. In reality, of course, the clients for Web services will usually be software other than a browser, but it's still nice to have this Web page generated for you, as it provides an easy way to verify that your methods are available.

ASP.NET allows accessing an .asmx page from a browser

Like browser-focused ASP.NET applications, ASP.NET applications that provide Web services can also use a code-behind option. In this case, the .asmx file contains just the WebService directive with a reference to the assembly that contains the class. The actual code for that class is in a separate file, just as with browser-accessible ASP.NET applications.

ASP.NET Web Services applications can use the code-behind option

Servers are useless without clients. To create a client capable of invoking the Web services in some server, a developer must first create a proxy class that exposes the same methods. This proxy can be created in Visual Studio by adding something called a Web reference to a project or by specifying an .asmx file or a WSDL file. Given this information, Visual Studio will extract the information it needs to build a proxy for the desired Web service. It's also possible to create a proxy manually using wsdl.exe, a command-line tool that reads in a WSDL file and produces a proxy in the desired programming language. Once this proxy exists, the client can create an instance of that class and call its methods just like any other class. The proxy will forward each call to the destination Web service, that method will execute, and any results will be returned though the proxy.

ASP.NET Web Services clients depend on proxies

It's also possible to invoke a Web service asynchronously. Rather than make the call and then block waiting for a response, a client can call the Web service and go about its business. When it gets the chance, the client can check to see what results, if any, the call has returned. To do this, the client uses two methods provided by the proxy along with the normal synchronous method for each Web service it supports. The first of these begins the call, passing in any parameters, and then returns control to the client. The second ends the call, returning any results that have come back. Other options are also possible, allowing the client to avoid repeatedly checking for the call to be completed.

Web services can be called asynchronously

ASP.NET Web Services Applications: Beyond the Basics

Building straightforward Web services such as those just shown could hardly be simpler. Adding one attribute isn't much work, and building a client proxy is also dead easy. But then, the methods in this example's Compute class don't do much either. Web services methods that do real work commonly require a bit more complexity than what's been shown so far. This section describes some of the options ASP.NET Web Services provides for creating more powerful and more useful Web services.

For example, what if an ASP.NET Web Services application needs to maintain state about its client between requests? Just as with the .aspx pages of a browser application, object instances defined via an .asmx page are created, used, and then destroyed for each request. Without some outside help, a Web services application can't store any in-memory information between requests. Fortunately, this outside help is available in the form of the standard objects provided by ASP.NET for this purpose. If a class that includes Web services methods inherits from System.Web.Services.WebService, for example, code in that class can access the Session object, the Application object, and others described in Chapter 5. These objects are also available via a static property called HttpContext.Current. However they're accessed, a Web services application can use these objects to maintain state about its clients, access the User object to learn who the client is, and use other services provided by these objects.

ASP.NET Web Services applications can use built-in objects to manage their state

To use the Session object, although not the others, a method within this class must also specify the EnableSession parameter in its WebMethod attribute. For example, if the Factorial method in the Compute class shown earlier were to do this, its declaration would look like this:

[WebMethod(EnableSession=true)] public int Factorial(int f) { ... }

Using the Session object requires specifying the EnableSession parameter

Here's another concern: What if a method exposed as a Web service needs to group the work it does into a transaction? If the method uses ADO.NET to access a DBMS, it can certainly use the services of the Connection and Transaction objects, described in Chapter 6, to demarcate transaction boundaries, just like any other ADO.NET client. But suppose the method needs to create a transaction that spans multiple DBMSs or includes work done by other components? In the .NET Framework, these services are provided by the classes in System.EnterpriseServices, as described later in this chapter. To access these services, a method exposed as a Web service can use another parameter of the WebMethod attribute called TransactionOption. If a method to transfer money between two bank accounts were exposed as a Web service, for example, that method might be declared like this:

[WebMethod(TransactionOption= TransactionOption.Required)] public bool MoveMoney(int fromAccount, int toAccount, decimal amount) { ... }

ASP.NET Web Services applications can also use transactions

When the method executes, it will automatically run within a transaction managed by code in System.EnterpriseServices. It's important to note that this transaction includes only the work done by the MoveMoney method, which might, say, add to one account and subtract from another. It does not involve the client, whose only role is to call MoveMoney. Addressing the challenge of transactions that span SOAP calls is beyond the scope of ASP.NET Web services.

Transactions don't span SOAP calls

Another issue that might confront the creator of a Web services method is how to deal with SOAP headers. A SOAP message can include various headers, and each of those headers can have a mustUnderstand attribute. Given that SOAP headers are allowed to contain virtually anything, ASP.NET provides quite generic support for working with them. The foundation of that support is the SoapHeader class, contained in the namespace System. Web.Services.Protocols. This class defines common properties found in a SOAP header, including a MustUnderstand property to contain the value of a header's mustUnderstand attribute. By inheriting from this class, a developer can more easily create a class that reflects the specifics of a particular SOAP header.

ASP.NET Web Services supports processing SOAP headers

One more concern stems from every Web service's dependence on XML, the representation for all information sent and received via SOAP. This information, including method names and more, will belong to a default XML namespace unless an explicit alternative is provided. It's a good idea to provide this alternative since XML namespaces are used to differentiate between information carried by different services. The WebService attribute, defined in System.Web.Services, can be applied to the class, with the attribute's Namespace parameter used to specify the XML namespace. For example, if the Compute class shown earlier were provided by the fictitious QwickBank, its declaration might look like this:

[WebService(Namespace= "http://www.qwickbank.com/mathinfo")] public class Compute { . . . }

An ASP.NET Web Services application can define its own namespace

Perspective: The Short Happy Life of .NET My Services

Perhaps the most controversial part of the original .NET technology family was .NET My Services. The codename for this technology was Hailstorm, and it was a well-chosen name: The proposal brought down a storm of criticism on Microsoft.

The idea of .NET My Services was certainly interesting: provide a set of Web services to applications over the Internet that allowed access to useful information. Among the proposed services were network storage of personal calendars and contact lists, a generalized alert service, a user presence service that could determine where to send those alerts, and several more. The goal was to help developers build a new kind of application using .NET My Services as a platform. For example, an application might detect an upcoming meeting on your calendar, use your contact list to discover how to get in touch with all of the participants, then use the alert and presence services to send all of them a meeting reminder wherever they might be via whatever device was appropriate. It was a creative idea, one that had the potential for significant value.

Yet .NET My Services never made it out of beta. For one thing, Microsoft found it challenging to excite potential customers about what this out-of-the-ordinary idea could do for them. Even more problematic, however, were the security and privacy concerns this technology raised. Many people were unsettled by the prospect of storing their personal information on Microsoft-owned servers accessible via the Internet. As a result, Microsoft largely wrote off its investment in creating this technology.

But still, the question remains: Was .NET My Services a good idea? In many ways, I'd argue that the answer is yes. Being able to access useful information from anywhere in the world, especially if that access is only by a controlled set of authorized applications, is a powerful thing. The security and privacy issues this raises can't be minimized, yet neither can the potential benefits. While it might be from some other company and it will certainly be under a different name, I wouldn't be surprised to see something much like .NET My Services rise again. You can't keep a good idea down.

ASP.NET Web Services was Microsoft's first serious attempt to implement this new technology family. Since its original design, Microsoft and the industry as a whole have learned more about how best to use Web services. Accordingly, there are aspects of ASP.NET Web Services, such as its orientation toward a remote procedure call (RPC) model, that don't necessarily reflect current thinking. Still, this technology has become a very popular approach for creating applications that communicate using SOAP. ASP.NET Web Services conforms to the Web Services Interoperability (WS-I) Organization's Basic Profile 1.1, and this ability to interoperate with software written on non-Microsoft platforms is a huge plus. It's probably fair to say that ASP.NET Web Services is the most important option in version 2.0 of the .NET Framework for creating distributed applications.

Категории