Thursday, November 4, 2010

On SOAP Action in WCF router (3.x)

In case you set arbitrary SOAP Action via HttpRequestMessageProperty before sending to WCF Router, you might be getting:

“The SOAP action specified on the message, '"/xyz"', does not match the action specified on the HttpRequestMessageProperty, '/xyz'.” in the System.ServiceModel.dll!System.ServiceModel.Channels.HttpOutput.WebRequestHttpOutput.PrepareHttpSend(System.ServiceModel?.Channels.Message message)

Given the hurdles with wcf step into the source thing, Reflector gives a good peek into the incriminated method:

        string action = message.Headers.Action;
 
        if (action != null) {
 

action = string.Format(CultureInfo.InvariantCulture, "\"{0}\"",
new object { UrlUtility.UrlPathEncode(action) });

 
        } 
 
...
 
    if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out obj2)) {
 

HttpRequestMessageProperty property = (HttpRequestMessageProperty) obj2;

this.httpWebRequest.Method = property.Method;

WebHeaderCollection headers = property.Headers;
flag2 = flag2 || property.SuppressEntityBody;
for (int i = 0; i < headers.Count; i++) {

 
            string strA = headers.Keys[i]; string str3 = headers[i]; 
 
...
 
    else if (string.Compare(strA, "SOAPAction", StringComparison.OrdinalIgnoreCase) == 0)
 
        {
 
            if (action != null) {
 
                if ((str3.Length > 0) && (string.Compare(str3, action, StringComparison.Ordinal) != 0)) {
 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new ProtocolException(SR.GetString("HttpSoapActionMismatch", new object { action, str3 })));
 
                } else { action = str3;}
 
            } 

Not sure what the “smart” feature is of putting action into quotes in the beginning, as it is never going to work in the described scenario. But at least fix is obvious here, nullify the action before resending, so it is picked up from the HttpRequestMessageProperty again.

requestMessage.Headers.Action = null; 

No comments: