Export (0) Print
Expand All
Expand Minimize
16 out of 26 rated this helpful - Rate this topic

How To: Configure MachineKey in ASP.NET 2.0

 
Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

patterns & practices Developer Center

J.D. Meier, Alex Mackman, Blaine Wastell, Prashant Bansode, Andy Wigley

Microsoft Corporation

July 2005

Applies To

  • ASP.NET version 2.0

Summary

This How To explains the <machineKey> element in the Web.config file and shows how to configure the <machineKey> element to control tamper proofing and encryption of ViewState, forms authentication tickets, and role cookies. ViewState is signed and tamper proof by default. You can request encryption for pages that contain sensitive items in their ViewState by using the ViewStateEncryptionMode attribute. Forms authentication and role cookies are signed and encrypted by default. You do not need to modify the default settings unless your application is in a Web farm or if you need to share authentication tickets across applications. In these cases, you need to manually generate encryption and hashing keys.

Contents

Objectives
Overview
What's New in 2.0
Machine Key Explained
ViewState
Forms Authentication Tickets
Membership
Anonymous Identification
Role Cookies
Web Farm Deployment Considerations
Sharing Authentication Tickets Across Applications
Upgrading ASP.NET Versions
Additional Resources

Objectives

  • Learn key changes in ASP.NET version 2.0.
  • Verify ViewState is configured to be tamper proof.
  • Configure the <machineKey> to encrypt ViewState.
  • Verify forms authentication tickets are configured to be tamper proof.
  • Configure <machineKey> to encrypt forms authentication tickets.
  • Learn to configure the membership feature to use an encrypted password instead of a hashed password by using machineKey.
  • Learn to protect an anonymous identification cookie by using machineKey.
  • Learn to protect role cookies by using machineKey.
  • Generate random key values for use in a Web farm.

Overview

The default ASP.NET settings ensure that forms authentication tickets are tamper proof and encrypted, and that ViewState is tamper proof. This ensures that any modification of the ViewState or authentication tickets either on the client's computer or over the network is detected when the server processes the data.

To provide tamper proof ViewState, a hashed message authentication code (HMAC) is generated from the ViewState content and the hash is compared on subsequent requests. The validation attribute of the <machineKey> indicates which hashing algorithm to use, and it defaults to SHA1, which uses the HMACSHA1 algorithm. Valid choices for hashing include SHA1 or MD5, although SHA1 is preferable because it produces a larger hash and is considered cryptographically stronger than MD5. The validationKey attribute of <machineKey> is used in conjunction with the ViewState content to produce the HMAC. If your application is installed in a Web farm, you need to change the validationKey from AutoGenerate,IsolateApps to a specific manually generated key value.

If you need to use round trips for potentially sensitive data, you can force encryption of ViewState for a specific page. To do this, set ViewStateEncryptionMode="Always" on the @Page directive for that page. Alternatively, you can use a control to request that the page's ViewState be encrypted by calling the Page.RegisterRequiresViewStateEncryption method. Using this method in conjunction with the default setting of ViewStateEncryptionMode="Auto" ensures that ViewState is only encrypted for those pages that need it.

To encrypt ViewState in a Web farm, you need to manually set the validationKey value. The encryption algorithm is determined by the validation attribute of the <machineKey>. The validation attribute defaults to SHA1, which provides tamper proofing but not encryption. To support ViewState encryption, you should set the validation attribute to AES, the recommended symmetric encryption algorithm.

Forms authentication tickets are tamper proof and encrypted by default. The decryption and decryptionKey attributes control the encryption. The validationKey controls the hashing. If your application is in a Web farm, you need to manually set the validationKey and decryptionKey. Also, if you need to share forms authentication tickets across applications in separate virtual directories, you need to manually set the keys to ensure that they match in each application's Web.config file.

If you use the Role Manage feature, and choose to cache roles, a roles cookie is created. The roles cookie is also signed and encrypted by default, using the same mechanisms as forms authentication tickets.

What's New in 2.0

ASP.NET version 2.0 introduces the following new features:

  • Decryption attribute. The decryption attribute of the <machineKey> element is introduced in ASP.NET version 2.0. It specifies the symmetric encryption algorithm used to encrypt and decrypt forms authentication tickets. Previously, the validation attribute was overloaded and used to specify the hashing algorithm used to generate HMACs to provide tamper proofing for ViewState and forms authentication tickets, and also to specify the encryption algorithm to use for ViewState and forms authentication encryption. Now, the validation attribute only determines the algorithm used for ViewState encryption and ViewState HMAC generation.
  • AES symmetric encryption. ASP.NET 2.0 introduces support for AES symmetric encryption.
  • Role cookie protection. ASP.NET now uses the <machineKey> settings to protect the role cookie, if you enable the Role Manager feature and if you elect to cache role names in a roles cookie. The role cookie is signed and protected by default.
  • Anonymous identification. If this feature is enabled, the anonymous identification cookie can be signed and encrypted using values from the <machineKey>. If you use anonymous identification in cookieless mode, the data on the URL is also signed using <machineKey> settings,
  • Cookieless forms authentication. The cookieless ticket is protected by using values from the <machineKey>.
  • Encrypted password storage. The membership system uses the <machineKey> encryption settings if you choose to store passwords in encrypted format. By default, the membership system stores password hashes.
  • viewStateEncryptionMode attribute. This is a new attribute on the <pages> element, and is used to control how ViewState is encrypted. To specify ViewState encryption settings for an individual page, you can use an equivalent ViewStateEncryptionMode attribute on the @Page directive.

Machine Key Explained

The default settings for the <pages> and <machineKey> elements are defined in the machine-level web.config.comments file. The relevant default settings are shown here for reference.

<pages enableViewStateMac="true" viewStateEncryptionMode="Auto" ... />

<machineKey validationKey="AutoGenerate,IsolateApps"  
            decryptionKey="AutoGenerate,IsolateApps" 
            validation="SHA1" decryption="Auto" />

When you configure ViewState, the <pages> element is used in conjunction with the <machineKey> element.

The <machineKey> attributes are as follows:

  • validationKey. This specifies the key that the HMAC algorithm uses to make ViewState tamper proof. The ViewState MAC is checked at the server when either the enableViewStateMAC attribute of the <pages> element or the EnableViewStateMac attribute of the @Page directive is set to true.
    <pages enableViewStateMAC="true" ... /> 
    or
    <%@Page EnableViewStateMac="true" ... %>
    

    Forms authentication also uses this key for signing the authentication ticket. Role manager and anonymous identification if enabled also uses this key for signing their cookies. If you use anonymous identification in cookieless mode, the data on the URL is also signed with this value,

  • decryptionKey. This specifies the key used to encrypt and decrypt data. Forms authentication, role manager and anonymous identification features use this key to encrypt and decrypt the authentication ticket, roles cookie and anonymous identification cookie. ASP.NET uses the key to encrypt and decrypt ViewState, but only if the validation attribute is set to AES or 3DES.
  • decryption. This specifies the symmetric encryption algorithm used to encrypt and decrypt forms authentication tickets.
  • validation. This specifies the hashing algorithm used to generate HMACs to make ViewState and forms authentication tickets tamper proof. This attribute is also used to specify the encryption algorithm used for ViewState encryption. This attribute supports the following options:
    • SHA1–SHA1 is used to tamper proof ViewState and, if configured, the forms authentication ticket. When SHA1 is selected for the validation attribute, the algorithm used is HMACSHA1.
    • MD5–MD5 is used to tamper proof ViewState and, if configured, the forms authentication ticket.
    • AES–AES is used to encrypt ViewState with the key specified in the decryptionKey attribute.
    • 3DES–3DES is used to encrypt ViewState with the key specified in the decryptionKey attribute. This is the only way to encrypt ViewState in ASP.NET 1.1. Both the forms authentication ticket and the ViewState are tamper-proofed using SHA-1 and the key specified in the validationKey attribute. Because the validation attribute is overloaded in ASP.NET 1.1, ASP.NET 2.0 introduces a new decryption attribute.

In general, you should choose SHA1 over MD5 for tamper-proofing because this produces a larger hash than MD5 and is considered cryptographically stronger.

Forms authentication defaults to SHA1 for tamper proofing (if <forms protection="validation" or "All"). When <forms protection="All"> or <forms protection = "Encryption">, then forms authentication hashes the forms authentication ticket by using either MD5 or HMACSHA1 (HMACSHA1 is used even if validation is set to AES or 3DES). Forms authentication then encrypts the ticket using the algorithm specified in the decryption attribute. (The decryption attribute was introduced in ASP.NET 2.0.)

ViewState

You can protect ViewState in the following ways:

  • Use an HMAC to make ViewState tamper proof.
  • Use encryption to turn ViewState into unintelligible cipher text. This ensures that any sensitive data in ViewState cannot be viewed.

To enable hashing of ViewState, you must use one of the following configurations.

<pages enableViewStateMAC="true" ... /> 

or

<%@Page EnableViewStateMac="true" ... %>

To enable encryption of ViewState, you must use one of the following configurations.

<pages viewStateEncryptionMode="Auto" ... />
<pages viewStateEncryptionMode="Always" ... />

or

<%@Page ViewStateEncryptionMode="Auto" ... %>
<%@Page ViewStateEncryptionMode="Always" ... %>

With viewStateEncryptionMode set to Auto, the page is only encrypted if a control has specifically asked for it by calling the Page.RegisterRequiresViewStateEncryption method to request encryption. If it set to Always, this forces encryption even if a control does not request it.

Note: Do not encrypt ViewState unless it contains sensitive data. To avoid the performance overhead of encryption, consider storing sensitive data on the server and not in ViewState.

Verifying that ViewState Is Tamper Proof

ViewState is tamper proof by default. ViewState tamper proofing is enabled by the enableViewStateMac attribute on the <pages> element and the validationKey and validation attributes on the <machineKey> element.

Note: You can see the default <machineKey> setting in the Machine.config.comments file.

To verify that tamper proofing is enabled for ViewState

  1. Verify the enableViewStateMac attribute of the <pages> element is set to true, as shown in the following example.
    <pages enableViewStateMac="true" ... />
    
    Note: You can override the machine's enableViewStateMac setting at the application or page level.
  2. Verify that the validation attribute of the <machineKey> element is set to SHA1, as shown in the following example.
    <machineKey ...  validation="SHA1" ... />
    

    The validation attribute specifies the hashing algorithm used to tamper proof ViewState. The default value is "SHA1", and you should use this rather than MD5 because it produces a larger hash than MD5 and is cryptographically stronger.

  3. Review the validationKey setting of the <machineKey> element.
    <machineKey validationKey="AutoGenerate,IsolateApps" ... />
    

    In the default settings shown above, the AutoGenerate setting instructs ASP.NET to generate a random key. The IsolateApps modifier causes ASP.NET to generate a unique key for each application on your server by using the application ID of each application.

    The default value is correct for a single server deployment. You do not need to change the default settings unless your application is deployed in a Web farm. In a Web farm, you must manually generate the validationKey value and make sure that it is the same on all servers in the farm. For more information, see the section, Web Farm Deployment Considerations in this document.

Configuring <machineKey> to Encrypt ViewState

By default, information in ViewState is encoded, but not encrypted. A user could decode and view the ViewState data.

To encrypt ViewState, either a control on a page needs to explicitly request ViewState encryption or the viewStateEncryptionMode attribute of the <pages> element must be set to Always. To request encryption, a control must call the RegisterRequiresViewStateEncryption method of the Page class.

The viewStateEncryptionMode attribute can take one of three possible attributes:

  • Auto. This is the default setting, which means the ViewState on the page is only encrypted if a control has specifically asked for it.
    Note: If a control on the page requests encryption, then the entire ViewState is encrypted (not just the ViewState for the control).
  • Always. This forces encryption even if a control does not ask for it.
  • Never. This disables encryption even if a control does ask for it.

Ideally, you should not store sensitive data in ViewState and thereby avoid the need to encrypt it. If you do need to encrypt ViewState, then you need to specify the encryption algorithm to use on the validation attribute.

To encrypt ViewState

  1. Check that the viewStateEncryptionMode attribute of the <pages> element is set to Always, as shown in the following example.
    <pages ... viewStateEncryptionMode="Always" ... />
    

    If you do not want every page to used encrypted ViewState, check that the viewStateEncryptionMode attribute of the <pages> element is set to Auto, as shown in the following example.

    <pages ... viewStateEncryptionMode="Auto" ... />   
    

    Then, from within your code, call the RegisterRequiresViewStateEncryption method as shown in the following example.

    Page.RegisterRequiresViewStateEncryption();
    
  2. Specify the encryption algorithm to use on the validation attribute, as shown in the following example.
    <machineKey ... validation="AES" ... />
    

    The validation attribute is overloaded and can be used to specify either the hashing algorithm or the encryption algorithm. You can specify either 3DES or AES. (ASP.NET 2.0 introduces support for AES.) Because AES offers larger key sizes (128 bits, 192 bits, or 256 bits) than 3DES (56 bits), it is considered more secure and should be used.

  3. Review the decryptionKey attribute of the <machineKey> element:
    <machineKey decryptionKey="AutoGenerate,IsolateApps" ... />
    

    Unless your application is installed in a Web farm, you should leave the decryptionKey attribute with the default values shown in the example. In a Web farm, you must manually generate the decryptionKey value and ensure that the value is the same across all servers in the farm. For more information, see the section, Web Farm Deployment Considerations in this document.

For ViewState encryption, your <machineKey> configuration should resemble the following example

<machineKey 
    validationKey="AutoGenerate,IsolateApps"   
    decryptionKey="AutoGenerate,IsolateApps" 
    validation="AES" 
    decryption="Auto" />
Note: By default, ViewState is transmitted as a Base64 encoded string. Although at first glance it is unintelligible, Base64 encoding provides no security because it is easily decoded. If you need to ensure that ViewState contents remain confidential, you must use encryption.

Forms Authentication Tickets

You can protect forms authentication tickets in two ways:

  • Use an HMAC to make the ticket tamper proof.
  • Use encryption to turn the ticket contents into unintelligible cipher text. This ensures that the data stored in the ticket, such as user names, cannot be viewed on the client or between the browser and server if the ticket is sent in a cookie.

To ensure that forms authentication tickets are encrypted and protected against tampering, set the protection attribute of the <forms> element to All, as shown in the following example.

<system.web>
  <authentication mode="Forms">
    <forms name=".AuthCookie" loginUrl="login.aspx" protection="All"/>
  </authentication>
</system.web>

Verifying that Forms Authentication Tickets Are Tamper Proof

By default, forms authentication tickets are configured for tamper proofing by using the validationKey and validation attributes of the <machineKey> element.

To review forms authentication ticket configuration for tamper proofing

  1. Check that the protection attribute of the <forms> element to All, as shown in the following example.
    <forms ... protection="All" ... />
    

    You can override the protection attribute setting for all Web applications on the server by using the machine-level Web.config file or, for a specific application, by using its Web.config file.

  2. Review the validation attribute of the <machineKey> element, as shown in the following example.
    <machineKey ... validation="SHA1" ... />
    

    The validation attribute specifies the hashing algorithm used by the HMAC algorithm used to tamper proof the forms authentication ticket. You should use the default SHA1 setting because this produces a larger hash than MD5 and is cryptographically stronger.

    You do not need to change the default settings unless your application is deployed in a Web farm. In a Web farm, you must manually generate the validationKey value and make sure that the same value is used across all servers in the farm. For more information, see the section, Web Farm Deployment Considerations in this document.

  3. Review the validationKey attribute of the <machineKey> element , as shown in the following example.
    <machineKey validationKey="AutoGenerate,IsolateApps" ... />
    

    The example configuration shows the default settings. The AutoGenerate setting instructs ASP.NET to generate a random key. The IsolateApps modifier causes ASP.NET to generate a unique key for each application on your server by using the application ID of each application.

Configuring <machineKey> to Encrypt Forms Authentication Tickets

To encrypt forms authentication tickets, ASP.NET 2.0 uses the decryptionKey and the new decryption attribute of the <machineKey> element. The decryption attribute lets you specify the encryption algorithm to use. ASP.NET 1.1 and 1.0 use 3DES encryption, which is not configurable.

To encrypt Form authentication tickets

  1. Check that the protection attribute of the <forms> element is set to All, as shown in the following example.
    <forms protection="All" ... />
    
  2. Use the decryption attribute of the <machineKey> element to specify the encryption algorithm as shown in the following example.
    <machineKey decryption="Auto" ... />
    

    With the default Auto setting, if the value of the decryptionKey attribute is 8 bytes long (16 characters) then Auto defaults to DES. Otherwise, Auto defaults to AES. ASP.NET 2.0 supports AES, 3DES and DES algorithms. You should use AES because it offers larger key sizes (128 bits, 192 bits, 256 bits) than 3DES (56 bits).

  3. Review the decryptionKey attribute of the <machineKey> element.
    <machineKey decryptionKey="AutoGenerate,IsolateApps" ... />
    

    Unless your application is installed in a Web farm or you need to share authentication tickets across two or more applications, you should leave the decryptionKey attribute with the default values shown in the example. In a Web farm or if you need to share authentication tickets across applications, you must manually generate the decryptionKey value and make sure that the same value is used for all servers in the farm. For more information, see the sections, Web Farm Deployment Considerations and Sharing Authentication Tickets Across Applications in this document.

For forms authentication ticket encryption, the <machineKey> settings should resemble the following example.

<machineKey 
  validationKey="AutoGenerate,IsolateApps" 
  decryptionKey="AutoGenerate,IsolateApps" 
  validation="AES" 
  decryption="Auto" />

Membership

If you use the membership feature, password hashes are stored in the membership database by default. The membership system also supports encrypted passwords. If you select encrypted password format, then the <machineKey> settings are used when encrypting and decrypting the data. If you want to store encrypted passwords, use the following configuration in the Web.config file. Notice that passwordFormat is set to "Encrypted".

<membership defaultProvider="AspNetSqlMembershipProvider"
            userIsOnlineTimeWindow="15" hashAlgorithmType="">
  <providers>
    <clear />
    <add connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" 
         enablePasswordReset="true" requiresUniqueEmail="false"
         passwordFormat="Encrypted" .../>
  </providers>
</membership>
Note: The default setting for the passwordFormat attribute is "Hashed".

Anonymous Identification

ASP.NET 2.0 supports anonymous identification, and you can encrypt the anonymous identification cookie. Encryption of the cookie uses the <machineKey> configuration. To enable anonymous identification, set enabled="true" on the <anonymousIdentification> element in your Web.config file. To enable the cookies to be encrypted, set cookieProtection="Encrypted", as shown here.

<anonymousIdentification enabled="true" cookieName=".ASPXANONYMOUS"
cookieTimeout="100000" cookiePath="/" cookieRequireSSL="false"
cookieSlidingExpiration="true" cookieProtection="Encrypted"
cookieless="UseCookies" domain="" />

The cookieProtection attribute can take any of the following values:

  • "All" (to perform both validation and encryption)
  • "Encryption"
  • "Validation" (the default)
  • "None"

Role Cookies

ASP.NET version 2.0 also uses the <machineKey> settings to protect role cookies. The Role Manager can use role cookies to cache role names for a particular user. If you enable the Role Manager feature and elect to cache role names in the roles cookie, the default configuration in the Machine.config.comments file ensures that the roles cookie is tamper proof and encrypted. The cookieProtection attribute on the <roleManager> element is set to All.

If you enable the Role Manager and cache role names, you can ensure that the cookie is protected by setting cookieProtection="All" as shown in the following code example.

<roleManager enabled="true" 
             cacheRolesInCookie="true"
             cookieProtection="All" ... />

Web Farm Deployment Considerations

If you deploy your application in a Web farm, you must ensure that the configuration files on each server share the same value for validationKey and decryptionKey, which are used for hashing and decryption respectively. This is required because you cannot guarantee which server will handle successive requests.

With manually generated key values, the <machineKey> settings should be similar to the following example.

<machineKey  
validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7
               AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"           
decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation="SHA1"
decryption="AES"
/>

If you want to isolate your application from other applications on the same server, place the <machineKey> in the Web.config file for each application on each server in the farm. Ensure that you use separate key values for each application, but duplicate each application's keys across all servers in the farm.

Generate Cryptographically Random Keys

To generate cryptographically random keys:

  • Use the RNGCryptoServiceProvider class to generate a cryptographically strong random number.
  • Choose an appropriate key size. The recommended key lengths are as follows:
    • For SHA1, set the validationKey to 64 bytes (128 hexadecimal characters).
    • For AES, set the decryptionKey to 32 bytes (64 hexadecimal characters).
    • For 3DES, set the decryptionKey to 24 bytes (48 hexadecimal characters).

The following code shows how to generate random key values. Compile the code to create a console application, and then pass the required key size as a command line argument expressed as the desired number of hexadecimal characters. Each byte is represented by two hexadecimal characters; therefore, to request a 32-byte key, pass 64 as a command line argument. If you do not specify an argument, the code returns a 128 hexadecimal character (64-byte) key.

C# Example

using System;
using System.Text;
using System.Security;
using System.Security.Cryptography;

class App {
  static void Main(string[] argv) {
    int len = 128;
    if (argv.Length > 0)
      len = int.Parse(argv[0]);
    byte[] buff = new byte[len/2];
    RNGCryptoServiceProvider rng = new 
                            RNGCryptoServiceProvider();
    rng.GetBytes(buff);
    StringBuilder sb = new StringBuilder(len);
    for (int i=0; i<buff.Length; i++)
      sb.Append(string.Format("{0:X2}", buff[i]));
    Console.WriteLine(sb);
  }
}

Visual Basic Example

Imports System
Imports System.Text
Imports System.Security
Imports System.Security.Cryptography

Module App
    Sub Main(ByVal argv() As String)
        Dim len As Integer = 128
        If argv.Length > 0 Then
            len = Integer.Parse(argv(0))
        End If
        Dim buff(len / 2) As Byte
        Dim rng As New RNGCryptoServiceProvider()
        rng.GetBytes(buff)
        Dim sb As New StringBuilder(len)
        Dim i As Integer
        For i = 0 To buff.Length - 1
            sb.Append(String.Format("{0:X2}", buff(i)))
        Next i
        Console.WriteLine(sb)
        Console.ReadLine()

    End Sub 'Main
End Module

Run the application two times, and then copy and paste the resulting keys into the <machineKey> element—one time for validationKey and the other time for decryptionKey.

Sharing Authentication Tickets Across Applications

If you need a single logon to work across multiple applications located in separate virtual directories, you need to share a common authentication ticket. To configure a common authentication ticket, you must manually generate validationKey and decryptionKey values and ensure that each application shares these values.

If you want to share tickets across all applications on your server you can set these manual values on the <machineKey> element in the machine level Web.config file. To share tickets across specific applications, you can use a <machineKey> element with common validationKey and decryptionKey values in the relevant application's Web.config files.

For information about how to generate manual key values, see the section, "Web Farm Deployment Considerations," in this document.

Upgrading ASP.NET Versions

There is another important reason to explicitly set the <machineKey>. Each time you upgrade to a new version of ASP.NET, the key material used to automatically generate keys changes. Therefore, even if your application runs on a single Web server, if the keys need to remain stable over time, you should explicitly set the values for both validation and decryption.

Additional Resources

For more information about protecting forms authentication, see How To: Protect Forms Authentication in ASP.NET 2.0

Feedback

Provide feedback by using either a Wiki or e-mail:

We are particularly interested in feedback regarding the following:

  • Technical issues specific to our recommendations
  • Usefulness and usability issues

Technical Support

Technical support for the Microsoft products and technologies referenced in this guidance is provided by Microsoft Support Services. For support information, please visit the Microsoft Support Web site at http://support.microsoft.com.

Community and Newsgroups

Community support is provided in the forums and newsgroups:

  • MSDN Newsgroups: http://msdn.microsoft.com/newsgroups/default.asp
  • ASP.NET Forums: http://forums.asp.net

To get the most benefit, find the newsgroup that corresponds to your technology or problem. For example, if you have a problem with ASP.NET security features, you should use the ASP.NET Security forum.

Contributors and Reviewers

  • External Contributors and Reviewers: Andy Eunson; Jason Taylor, Security Innovation; Rudolph Araujo, Foundstone Professional Services
  • Microsoft Services and PSS Contributors and Reviewers: Aaron Margosis, Denny Dayton, Tom Christian, Wade Mascia, Adam Semel
  • Microsoft Product Group Contributors and Reviewers: Stefan Schackow, Vikas Malhotra
  • Test team: Larry Brader, Microsoft Corporation; Nadupalli Venkata Surya Sateesh, Sivanthapatham Shanmugasundaram, Infosys Technologies Ltd.
  • Edit team: Nelly Delgado, Microsoft Corporation; Tina Burden McGrayne, Linda Werner & Associates, Inc.
  • Release Management: Sanjeev Garg, Microsoft Corporation

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.