This project is read-only.
3
Vote

SoapHeadersClientHook builds incorrect action key which results in SoapHeaders not being found when namespace has a trailing /

description

SoapHeadersClientHook.cs
internal static void Hook(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
 
This line creates a key that is used to map headers to an operation in a Dictionary
              string action = contractDescription.Namespace + "/" + contractDescription.Name + "/" + op.Name;
 
The problem is that if the namespace contains a trailing slash "/" then a double slash is added.
 
However when SoapHeadersClientHook.cs : object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel)
is invoked it uses request.Headers.Action to lookup the headers in the dictionary but the key does not contain the double slash.
 
I've fixed this in my environment by replacing
              string action = contractDescription.Namespace + "/" + contractDescription.Name + "/" + op.Name;
 
with
                string action = contractDescription.Namespace.TrimEnd(new char[]{'/'});
                action += "/" + contractDescription.Name + "/" + op.Name;

file attachments

comments

jeanfran78 wrote May 27, 2009 at 5:08 PM

I had a related issue that was being caused by namespace mismatches when a services inherits from multiple data contracts.

For example

[ServiceContract(Namespace = "http://mynamespace.com/webservices/")]
[SoapHeaders]
public interface IParentContract {
   [OperationContract]
void Method1(string value1);
}

[ServiceContract(Namespace = "http://mynamespace.com/webservices/")]
[SoapHeaders]
public interface IChildContract : IParentContract {
[OperationContract]
void Method2(string value2);
}

When I invoke method1 on IChildContract the action being called as defined by the operation contract is

http://mynamespace.com/webservices/IParentContract/Method1

The action stored in the lookup dictionary is

http://mynamespace.com/webservices//IChildContract/Method1

therefore the header is never embedded in the request because the action lookup fails.

I modified the code to use the actual operation contract attribute on the method to get the action when constructing the action lookup dictionary. This solved both the trailing slash issue and the namespace mismatch when using inheritance in your contract definitions.

Modified code...

File: SoapHeadersClientHook.cs
Method: Hook

Instead of building the action like this

string action = contractDescription.Namespace + "/" + contractDescription.Name + "/" + op.Name;

Use the OperationContractAttribute on the method and get the exact action definition

OperationContractAttribute operationContract = ((OperationContractAttribute[])op.SyncMethod.GetCustomAttributes(typeof(OperationContractAttribute), false)).FirstOrDefault();

.
.
.

headersFromAction.Add(operationContract.Action, headers);

See attached file...

wrote May 27, 2010 at 11:53 AM

wrote Oct 18, 2010 at 11:54 PM

jeanfran78 wrote Oct 18, 2010 at 11:54 PM

Adding my solution… I updated my local version of the project and had to re-solve this issue. I forgot that I had ever modified the source. Hoping it gets adopted by the official contributors.

wrote Oct 18, 2010 at 11:54 PM

wrote Feb 21, 2013 at 11:53 PM