Diagnosing and Resolving Duplicate HTTP POST Requests with sc-win32-status=64 in IIS6 ASP.NET Applications


2 views

When working with legacy ASP.NET applications on IIS6 (Windows Server 2003), we sometimes encounter puzzling network-level issues that manifest differently across environments. One such case involves duplicate HTTP POST requests appearing in IIS logs exclusively when accessed through certain client networks.

// Typical IIS log entry showing the duplicate requests
2009-08-11 20:19:45 x.x.x.x POST /File.aspx - 80 - y.y.y.y Mozilla/4.0+... 200 0 64
2009-08-11 20:19:45 x.x.x.x POST /File.aspx - 80 - y.y.y.y Mozilla/4.0+... 200 0 0

The key indicators in our IIS logs are:

  • sc-win32-status=64: "The specified network name is no longer available" (ERROR_NETNAME_DELETED)
  • sc-win32-status=995: "The I/O operation has been aborted" (ERROR_OPERATION_ABORTED)

The fact this occurs only on specific client networks suggests several possible culprits:

// Potential network components to check:
1. Proxy servers or WAN accelerators
2. Network packet inspection devices
3. TCP/IP stack settings (especially keep-alive)
4. Middleboxes modifying HTTP traffic

While the root cause appears network-related, we can implement server-side defenses:

// ASP.NET code to prevent duplicate form submissions
protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        string formToken = Guid.NewGuid().ToString();
        ViewState["FormToken"] = formToken;
    }
}

protected void btnSubmit_Click(object sender, EventArgs e)
{
    string currentToken = ViewState["FormToken"] as string;
    string sessionToken = Session["LastFormToken"] as string;

    if (currentToken == sessionToken)
    {
        // Duplicate submission detected
        lblMessage.Text = "This action was already processed";
        return;
    }

    Session["LastFormToken"] = currentToken;
    // Process the form normally
}

Adding JavaScript protection can help minimize the issue:

// jQuery solution to disable submit button after first click
$(document).ready(function() {
    $('form').submit(function() {
        $(':submit', this).attr('disabled', 'disabled');
        return true;
    });
});

// Alternative: Using Fetch API with AbortController
const controller = new AbortController();
const signal = controller.signal;

document.querySelector('form').addEventListener('submit', async (e) => {
    e.preventDefault();
    const submitBtn = e.target.querySelector('button[type="submit"]');
    submitBtn.disabled = true;
    
    try {
        await fetch(e.target.action, {
            method: 'POST',
            body: new FormData(e.target),
            signal: signal
        });
    } catch (err) {
        if (err.name === 'AbortError') return;
        submitBtn.disabled = false;
    }
});

For IIS6-specific tuning, consider these registry settings:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters]
"EnableAggressiveMemoryUsage"=dword:00000001
"MaxConnectionsPer1_0Server"=dword:0000000a
"MaxConnectionsPerServer"=dword:0000000a
"RequestTimeout"=dword:00000078

When network devices are suspected, Wireshark captures can reveal:

  • TCP retransmissions
  • RST packets from intermediaries
  • Keep-alive negotiation failures
  • MTU mismatches

Example Wireshark filter for troubleshooting:

tcp.port == 80 and ip.addr == x.x.x.x and http.request.method == "POST"

When working with an ASP.NET 2.0 application on IIS6 (Windows Server 2003), we observed an interesting phenomenon where POST requests were being duplicated, but only when accessed from specific client networks. The IIS logs revealed identical POST entries with different win32 status codes:

2009-08-11 20:19:45 x.x.x.x POST /File.aspx - 80 - y.y.y.y [user-agent] 200 0 64
2009-08-11 20:19:45 x.x.x.x POST /File.aspx - 80 - y.y.y.y [user-agent] 200 0 0

The key indicators here are:

  • 64 (ERROR_NETNAME_DELETED): "The specified network name is no longer available"
  • 995 (ERROR_OPERATION_ABORTED): "The I/O operation has been aborted because of either a thread exit or an application request"

Since this only occurs on specific networks, we should examine:

// Example: Network trace analysis pseudocode
1. Capture network traces using Wireshark or NetMon
2. Compare successful vs. problematic requests
3. Check for TCP retransmissions or connection resets
4. Examine keep-alive headers and connection timing

Common network-level culprits might include:

  • Proxy servers or intercepting devices
  • MTU size mismatches
  • TCP window size issues
  • Network latency causing premature timeouts

While fixing the root network cause is ideal, we can implement server-side protections:

// ASP.NET solution: Implement request deduplication
public class AntiDuplicateModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += OnBeginRequest;
    }

    private void OnBeginRequest(object sender, EventArgs e)
    {
        var app = (HttpApplication)sender;
        if (app.Request.HttpMethod == "POST")
        {
            var requestSignature = $"{app.Request.Url}_{app.Request.UserHostAddress}";
            
            if (HttpContext.Current.Cache[requestSignature] != null)
            {
                app.Response.StatusCode = 409; // Conflict
                app.Response.End();
            }
            else
            {
                HttpContext.Current.Cache.Add(
                    requestSignature, 
                    true, 
                    null, 
                    DateTime.Now.AddSeconds(5), // Short expiration
                    Cache.NoSlidingExpiration,
                    CacheItemPriority.Normal, 
                    null);
            }
        }
    }
}

For immediate relief, consider these JavaScript solutions:

// Disable form button after submission
document.addEventListener('DOMContentLoaded', function() {
    const forms = document.querySelectorAll('form');
    forms.forEach(form => {
        form.addEventListener('submit', function() {
            const buttons = this.querySelectorAll('button, input[type="submit"]');
            buttons.forEach(btn => {
                btn.disabled = true;
                btn.value = 'Processing...';
            });
        });
    });
});

Implement transaction checks to prevent duplicate operations:

-- SQL Server example
BEGIN TRANSACTION
DECLARE @operationId UNIQUEIDENTIFIER = '...'
IF NOT EXISTS (SELECT 1 FROM CompletedOperations WHERE OperationId = @operationId)
BEGIN
    -- Perform your operation here
    INSERT INTO CompletedOperations (OperationId, CompletedDate)
    VALUES (@operationId, GETDATE())
    COMMIT TRANSACTION
END
ELSE
BEGIN
    ROLLBACK TRANSACTION
    -- Return appropriate error to client
END

For deeper investigation, consider these approaches:

// IIS Failed Request Tracing configuration
1. Open IIS Manager
2. Navigate to the site
3. Under "Diagnostics", select "Failed Request Tracing Rules"
4. Add a rule for:
   - Status codes: 200-399
   - Event severity: Warning
5. Reproduce the issue and examine the trace logs

Key areas to examine in the trace:

  • Client disconnection timing
  • Request execution duration
  • Any authentication/authorization events
  • Module execution sequence