This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.
The Programmable Web: Web Services Provides Building Blocks for the Microsoft .NET Framework
ne of today's most pressing challenges is application integration: taking different applications running on different operating systems built with different object models using different programming languages and turning them into easy-to-use Web applications. The Microsoft vision of Web Services, based on open Web standards such as HTTP and XML, addresses this challenge.
A Look at Web ServicesBroadly speaking, a Web Service is simply an application delivered as a service that can be integrated with other Web Services using Internet standards. In other words, it's a URL-addressable resource that programmatically returns information to clients who want to use it. One important feature of Web Services is that clients don't need to know how a service is implemented. In this section, I'll explain how Web Services combine the best aspects of component-based technologies and the Web, and introduce the infrastructure needed to communicate with Web Services.
Like components, Web Services represent black-box functionality that can be reused without worrying about how the service is implemented. Web Services provide well-defined interfaces, called contracts, that describe the services provided. Developers can assemble applications using a combination of remote services, local services, and custom code. For example, a company might assemble an online store using the Microsoft Passport service to authenticate users, a third-party personalization service to adapt Web pages to each user's preferences, a credit-card processing service, a sales tax service, package-tracking services from each shipping company, an in-house catalog service that connects to the company's internal inventory management applications, and a bit of custom code to make sure that their store stands out from the crowd. Figure 1 shows a model that illustrates how Web Services can be linked to create distributed Web applications.
Unlike current component technologies, however, Web Services do not use object model-specific protocols such as DCOM, RMI, or IIOP that require specific, homogeneous infrastructures on both the client and service machines. While implementations tightly coupled to specific component technologies are perfectly acceptable in a controlled environment, they become impractical on the Web. As the set of participants in an integrated business process changes, and as technology changes over time, it becomes very difficult to guarantee a single, unified infrastructure among all participants. Web Services take a different approach; they communicate using ubiquitous Web protocols and data formats such as HTTP and XML. Any system supporting these Web standards will be able to support Web Services.
The Microsoft .NET FrameworkThe goal of the Microsoft .NET Framework is to make it easy to build Web applications and Web Services. Figure 2 shows the Microsoft .NET Framework architecture. Built on top of operating system services is a common language runtime that manages the needs of running code written in any modern programming language. This runtime supplies many services that help simplify code development and application deployment while also improving application reliability. The .NET Framework also includes a set of class libraries that developers can use from any programming language. Above that sit various application programming models that provide higher-level components and services targeted specifically at developing Web sites and Web Services. Now I'll describe each of these layers.
Common Language RuntimeThe runtime loads and runs code written in any runtime-aware programming language. Code that targets the runtime is called managed code. Managed code simply means that there is a defined contract of cooperation between natively executing code and the runtime itself. Responsibility for tasks like creating objects, making method calls, and so on is delegated to the runtime, which enables the runtime to provide additional services to the executing code.
The runtime features cross-language integration, self-describing components, simple deployment and versioning, and integrated security services. Let's take a quick look at each of these features.
The runtime makes use of a new common type system capable of expressing the semantics of most modern programming languages. The common type system defines a standard set of types and rules for creating new types. The runtime understands how to create and execute these types. Compilers and interpreters use runtime services to define types, manage objects, and make method calls instead of using tool or language-specific methods.
The primary design goal for the type system is to enable deep multilanguage integration. Code written in one language can now inherit implementation from classes written in another language; exceptions can be thrown from code written in one language and caught in code written in another; and operations such as debugging and profiling work seamlessly regardless of the languages used to write the code. This means that developers of reusable class libraries no longer need to create versions for each programming language or compiler, and developers using class libraries are no longer limited to libraries developed for the programming language they are using.
Self-describing components, which are now possible on the Microsoft .NET Framework, simplify development and deployment and improve system reliability. Let me explain how this works. Many services provided by the runtime are driven by metadata, information that supplements the executable code. Since all the information is stored together, the executables are referred to as self-describing components.
A key advantage of self-describing components is that no other files are needed to use the components. Separate header files are not required for class definitions; the definitions can be obtained from the component itself by inspecting the metadata. Separate IDL files, type libraries, or proxy/stubs are not required to access a component across language or process boundaries; the necessary information is located in the component's metadata. Separate configuration information does not need to be deployed to identify developer requested service attributes. And best of all, since the metadata is generated from the source code during the compilation process and stored with the executable code, it is never out of sync with the executable.
In addition to improvements in deploying individual components, the Microsoft .NET Framework defines an application deployment model that addresses customer issues with the complexities of application installation and DLL versioning (commonly known as "DLL Hell"). Services to support this model are provided by the runtime.
The Microsoft .NET Framework introduces the notion of an assembly. An assembly is a group of resources and types, along with metadata about those resources and types, that is deployed as a unit. The metadata is called an assembly manifest and includes information such as a list of types and resources visible outside the assembly. The manifest also includes information about dependencies, such as the version of the assemblies used when the assembly was built. Developers can specify versioning policies to indicate whether the runtime should load the latest version of a dependent assembly installed on the system, a specific version, or the version used at build time.
It has always been possible for multiple copies of a software component to reside on the same system. In general, however, only one of these copies can be registered with the operating system or loaded for execution. The policy for locating and loading components is global to the system. The .NET Framework common language runtime adds the infrastructure necessary to support per-application policies that govern the locating and loading of components, which is generally referred to as side-by-side deployment.
Assemblies can be private to an application or shared by multiple applications. Multiple versions of an assembly can be deployed on a machine at the same time. Application configuration information defines where to look for assemblies, thus the runtime can load different versions of the same assembly for two different applications that are running concurrently. This eliminates issues that arise from incompatibilities between component versions, improving overall system stability. If necessary, administrators can add configuration information, such as a different versioning policy, to assemblies at deployment time, but the original information provided at build time is never lost.
Because assemblies are self-describing, no explicit registration with the operating system is required. Application deployment can be as simple as copying files to a directory tree. (Things are slightly more complicated if unmanaged components must be installed for the application to work.) Configuration information is stored in XML files that can be edited by any text editor.
Finally, the runtime also supplies integrated, pervasive security services to ensure that unauthorized users cannot access resources on a machine and that code cannot perform unauthorized actions. This improves overall system safety and reliability. Since the runtime is used to load code, create objects, and make method calls, the runtime can perform security checks and enforce security policy as managed code is loaded and executed.
The Microsoft .NET Framework provides both code access security and role-based security. With code access security, developers can specify the required permissions their code needs to accomplish work. For example, code may need permission to write a file or access environment variables. This information is stored at the assembly level, along with information about the identity of the code. At load time and on method calls, the runtime verifies that the code can be granted the permissions it has asked for. If not, a security violation is reported. Policies for granting permissions, known as trust policies, are established by system administrators, and are based on evidence about the code such as who published the code and where it was obtained from, as well as the identity and requested permissions found in the assembly. Developers can also specify permissions they explicitly don't want, to prevent malicious use of their code by others. Programmatic security checks can be written if the permissions required depend on information that isn't known until runtime.
In addition to code access security, the runtime supports role-based security. Role-based security builds on the same permissions model as code access security, except that the permissions are based on user identity rather than code identity. Roles represent categories of users and can be defined at development or deployment time. Policies for granting permissions are assigned to each defined role. At runtime, the identity of the user on whose behalf the code is running is determined. The runtime determines what roles the user is a member of and then grants permissions based on those roles.
Before looking at programming models in the Microsoft .NET Framework, let's look at the services it provides.
The Services FrameworkAs you may recall from Figure 2, on top of the common language runtime is the services framework. This framework provides classes that can be called from any modern programming language. All classes comply with a set of naming and design guidelines to further reduce the learning curve for developers.
Some of the key class libraries in the services framework are shown in Figure 3. The framework includes a base set of class libraries that developers would expect in a standard language library, such as collections, input/output, string, and numerical classes. In addition, the base class library provides classes to access operating system services such as graphics, networking, threading, globalization, and cryptography. The services framework also includes a data access class library, as well as classes that development tools can use, such as debugging and profiling services. There isn't room in this article to discuss all the classes in detail, so I'll focus on the data access classes since most Web Services need access to data. Of course, you can find additional information about the services framework class libraries in the Microsoft .NET Framework SDK.
Data Access ServicesNearly all Web Services need to query or update persisted data, whether in simple files, relational databases, or any other type of store. To provide data access, the services framework includes the ActiveXÂ® Data Objects+ (ADO+) class library. As the name implies, ADO+ evolves from ADO. ADO+ is designed to provide data access services for scalable Web-based applications and services. ADO+ provides high-performance stream APIs for connected, cursor-style data access, as well as a disconnected data model more suitable for returning data to client applications, as I will explain later. Figure 4 illustrates the ADO+ architecture and shows that any dataâ€"regardless of how it is actually storedâ€"can be manipulated as XML or relational data, whichever is most appropriate for the application at a given point in time.
Just like its native counterpart, ADO+ defines classes for connecting to, issuing commands against, and retrieving results from data stores. These classes are implemented by managed data providers. The ADO+ Connection and Command objects look nearly identical to those in ADO, and a new class called a DataReader provides the ability to retrieve results through a high-performance stream API. The DataReader is functionally equivalent to a forward-only, read-only ADO Recordset, but DataReaders are designed to minimize the number of in-memory objects created to avoid garbage collection and improve performance. The .NET Framework includes managed data providers for Microsoft SQL Serverâ„¢ and any data store that can be access via OLE DB.
Win Forms Application ModelConceptually, on top of the services framework sit two application models: the WindowsÂ® application model and the Web application model. Although I've focused on the Microsoft .NET Framework as a way to develop Web Services and Web applications, the framework can also be used to develop more traditional Windows-based applications (of course, these applications can use Web Services, too).
Developers writing client applications for Windows can use the Win Forms application model to take advantage of all the rich user interface features of Windows, including existing ActiveX controls and new features of Windows 2000, such as transparent, layered, and floating windows. Either a traditional Windows or Web appearance can be selected. Developers will find the Win Forms programming model and design-time support very intuitive, given its similarities to existing Windows-based forms packages.
Win Forms also takes advantage of the Microsoft .NET Framework runtime to reduce total cost of ownership for Windows-based client applications. The framework security model can safely execute applications and components on client machines provided they are written using the Win Forms model or used from a Win Forms application. If implemented or used in this way, the cute game someone got off the Internet won't corrupt configuration information and data, or automatically send e-mail to everyone in the user's address book.
The Microsoft .NET Framework assembly model simplifies application deployment and versioning. Applications can be configured to use the versions of shared components they were built and tested with, rather than using whatever component versions happen to be installed on the client machine, improving application reliability and eliminating one of the major causes of application support calls: incompatible versions of user interface controls and other shared components.
A Model for Web ApplicationsWeb applications built on the Microsoft .NET Framework share a common application model. In this model, a Web application is a set of URLs rooted at some base URL. Thus it encompasses both Web applications that generate pages for display in a browser and Web Services. In this section, I'll detail the Web application programming model called Active Server Pages+ (ASP+), which is illustrated in Figure 5.
As you might guess from the name, ASP+ evolves from Active Server Pages. ASP+ takes advantage of the common language runtime and services framework to provide a reliable, robust, scalable hosting environment for Web applications. ASP+ also benefits from the common language runtime assembly model to simplify application deployment. In addition, it provides services to simplify application development (such as state management services) and higher-level programming models (such as ASP+ Web Forms and ASP+ Web Services).
ASP+ Web FormsWeb Forms bring the productivity benefits of Visual BasicÂ®-based forms to Web application development. Web Forms support traditional ASP syntax that mixes HTML content with script code, but it also promotes a more structured approach that separates application code from user interface content. Web Forms controls are being introduced to provide a mechanism for encapsulating common user interface elements. These new features enable tools to support a design-time model along the lines of Visual Basic, enabling WYSIWYG tool support for Web page layout.
Web Forms controls are responsible for generating the user interface, typically in the form of HTML. ASP+ comes with a set of Web Forms controls that mirror the typical HTML user interface widgets (including listboxes, text boxes, and buttons), and an additional set of Web controls that are more complex (such as calendars and ad rotators). One important feature of these controls is that they can be written to adapt to client-side capabilities; the same pages can be used to target a wide range of client platforms and form factors. In other words, Web Forms controls can "sniff" the client that is hitting a form and return an appropriate user experienceâ€"maybe HTML 3.2 for a down-level browser and Dynamic HTML for Internet Explorer 5.0.
Given the stateless communication model of the Web, one of the more complex issues facing Web application developers is responding to user interaction with Web-based interfaces. Web Forms take advantage of the ASP+ infrastructure to provide a rich set of services to help developers build interactive Web pages. The net effect of these services is to enable a component-based, event-driven programming model much like client-side forms programming for application developers. The complexities of state management across user interaction with a page are hidden by ASP+ Web Forms and Web Forms controls. Rich data-binding services are also supplied, making it very easy for application developers to display data retrieved through the data access services.
The separation of code and content enables ASP+ pages to be dynamically compiled into managed classes for fast performance. Each incoming HTTP request is delivered to a new page instance so that developers do not need to be concerned about thread safety in their code.
ASP+ Web ServicesThe ASP+ Web Services infrastructure provides a high-level programming model for building Web Services with ASP+. While not required for building a Web Service using the Web Services Platform, it provides several benefits that simplify development and uses a programming model that will be very familiar to developers who have worked with ASP or Visual Basic. Developers don't need to understand HTTP, SOAP, SCL, or any other specifications for Web Services to use this programming model. The ASP+ Web Services programming model is shown in Figure 6.
Developers can create a Web Service with ASP+ by authoring a file with the extension .asmx and deploying it as part of a Web application. The ASMX file either contains a reference to a managed class defined elsewhere or the class definition itself. The class is derived from the WebService class supplied by ASP+. Public class methods are exposed as Web Service methods by marking them with the WebMethod attribute. These methods can be invoked by sending HTTP requests to the URL of the ASMX file. You don't need to handcraft a contract for your Web Service. ASP+ inspects the class metadata to automatically generate an SCL file when requested by the caller.
ConclusionWeb Services provide a simple, flexible, standards-based model for binding applications together over the Internet that takes advantage of existing infrastructure and applications. Web applications can be easily assembled with locally developed services and existing services, irrespective of the platform, development language, or object model used to implement any of the constituent services or applications.
The Microsoft .NET Framework provides an application model and key enabling technologies to simplify the creation, deployment, and ongoing evolution of secure, reliable, scalable, highly available Web Services while building on existing developer skills.
|For related articles see:
Develop a Web Service: Up and Running with the SOAP Toolkit for Visual Studio
For background information see:
The SOAP spec
|Mary Kirtland is part of the MSDN Architecture team, where she helps create practical guidance for developers who design applications using Microsoft technologies. She is the author of Designing Component-based Applications (Microsoft Press, 1998).
From the September 2000 issue of MSDN Magazine.