Web Services (ASMX 1.1) Performance Guidelines - Design Considerations

From Guidance Share

Jump to: navigation, search

- J.D. Meier, Srinath Vasireddy, Ashish Babbar, and Alex Mackman


Design Chunky Interfaces to Reduce Round Trips

Design chunky interfaces by exposing Web methods that allow your clients to perform single logical operations by calling a single Web method. Avoid exposing properties. Instead, provide methods that accept multiple parameters to reduce roundtrips.

Do not create a Web service for each of your business objects. A Web service should wrap a set of business objects. Use Web services to abstract these objects and increase the chunkiness of your calls.

Prefer Message-Based Programming Over RPC Style

You can design Web services by using either of two programming models: messaging style and RPC style. The RPC style is based on the use of objects and methods. Web methods take object parameters to do the processing, and then return the results. This style generally relies on making multiple Web method calls to complete a single logical operation, as shown in the following code snippet.

  //client calling a Web service
  Serv.SendItemsToBePurchased(Array[] items);
  Serv.ShippingAddress(string Address);

The messaging style does not focus on objects as parameters. It is based on a data contract (schema) between the Web service and its clients. The Web service expects the message to be XML that conforms to the published data contract.

  string msg = "<Items>…</Items>";
  void MyMethod(string msg){ . . . }

This approach allows you to package and send all parameters in a single message payload and complete the operation with a single call, thus reducing chatty communication. The Web service may or may not return results immediately; therefore, the clients do not need to wait for results.

Use Literal Message Encoding for Parameter Formatting

The encoded formatting of the parameters in messages creates larger messages than literal message encoding (literal message encoding is the default). In general, you should use literal format unless you are forced to switch to SOAP encoding for interoperability with a Web services platform that does not support the literal format.

Prefer Primitive Types for Web Services Parameters

There are two broad categories of parameter types that you can pass to Web services:

  • Strongly typed. These include .NET types such as double and int, and custom objects such as Employee, Person, and so on. The advantage of using strongly typed parameters is that .NET automatically generates the schema for these types and validates the incoming values for you. Clients use the schema to construct appropriately formatted XML messages before sending them.
  • Loosely typed. These parameters use the string type. Note that you should not pass XML documents as string parameters because the entire string then needs to be XML encoded. For example, < and > needs to be converted to &lt and &gt and so on. Instead, you should use either an XmlElement parameter or implement IXmlSerializable. The latter is the most efficient and works well for large data sizes, regardless of which encoding style you use, you should prefer simple primitive types like int, double, and string for Web services parameters. Use of primitive types leads to reduced serialization and automatic and efficient validation by the .NET Framework.

Avoid Maintaining Server State Between Calls

Maintaining per-caller state in memory on the server limits scalability because the state consumes server resources. As an alternative, you can pass state back and forth between the client and Web service. Although this approach enables you to scale your service, it does add performance overhead — including the time taken to serialize, transmit, parse, and de-serialize the state with each call.

Consider Input Validation for Costly Web Methods

If you have a Web method that performs costly and time-consuming processing, consider validating the Web method input before processing it. It can be more efficient to accept the validation overhead to eliminate unnecessary downstream processing. However, unless you are likely to receive invalid input frequently, you should probably avoid schema validation due to the significant overhead that it introduces. You need to assess your specific situation to determine whether or not schema validation is appropriate.

You can validate input data either by using SOAP extensions or by using separate internal helper methods that your Web methods call. The advantage of using SOAP extensions is that they permit you to separate your validation code from your business logic. If there is any schema change in the future, the extension can change independently of the Web method.

Another option is to use the XmlValidatingReader class to perform schema-based validation, as shown in the following code snippet.

  public void ValidateCreditCard(string xmlCardInfo){
      // Create and load a validating reader
      XmlValidatingReader reader = new XmlValidatingReader(xmlCardInfo,
     XmlNodeType.Element, null);
      // Attach the XSD schema to the reader
      // Set the validation type for XSD schema.
      // XDR schemas and DTDs are also supported
      reader.ValidationType = ValidationType.Schema;
      // Create and register an event handler to handle validation errors
      reader.ValidationEventHandler += new ValidationEventHandler(
                                                       ValidationErrors );
      // Process the input data
      while (reader.Read())
      . . .
      // Validation completed successfully
    { . . .}
  // Validation error event handler
  private static void ValidationErrors(object sender, ValidationEventArgs args)
    // Error details available from args.Message
    . . .

Consider Your Approach to Caching

You can greatly enhance Web services performance by caching data. With ASP.NET Web services, you can use many of the same caching features that are available to ASP.NET applications. These include ASP.NET output caching, HTTP response caching, and ASP.NET application caching.

In common with any caching solution, your caching design for a Web service must consider issues such as how frequently the cached data needs to be updated, whether or not the data is user-specific or application-wide, what mechanism to use to indicate that the cache needs updating, and so on. For more information about caching with Web services, see the "Caching" section later in this chapter.

Consider Approaches for Bulk Data Transfer and Attachments

You can use the following approaches to optimize the performance of bulk data transfer:

  • Chunking. With this approach, you use fixed-size byte arrays to send the data one chunk at a time.

Offloading the transfer. With this approach, you return a URL from your Web service which points to the file to be downloaded.

  • Compression. You can use a SOAP extension to compress the SOAP messages before transmitting them. This helps when you are constrained primarily by network bandwidth or latency.

To handle attachments, your options include:

  • WS-Attachments
  • Base 64 encoding
  • SOAP Message Transmission Optimization Mechanism (MTOM)

Avoid Calling Local Web Services

Web services located on the same computer as a client ASP.NET application share the same thread pool with the ASP.NET application. Therefore, the client application and the Web service share the same threads and other related resources, such as CPU for request processing. Calling a local Web service also means that your request travels through the entire processing pipeline and incurs overhead, including serialization, thread switching, request queuing, and de-serialization.

In addition, the maxconnection attribute of Machine.config has no affect on the connection limit for making calls to local Web services. Therefore, local Web services always tend to give preference to the requests that come from the local computer over requests that come from other machines. This degrades the throughput of the Web service for remote clients.

There are two main approaches to solving this problem:

  • Factor out the Web services business logic into a separate assembly, and call the assembly from the client application as well as the Web service.
  • Load the Web services assembly directly and call its methods. This approach is not as intuitive as the first.
Personal tools