CoreWCF: Failing miserably to get Postman to POST a SOAP envelope to a Method

Firstly, let me start by saying, I have absolutely no idea what I’m doing really! I’m new to .NET Core and I’ve never touched MVC. I AM familiar with high-level WCF, creating services and bindings but nothing anywhere near as low-level as this project. So I am delving into things quickly trying to learn as I go along.

So my aim, for this test project, is to build an application that leverages Controllers, but also SOAP. (Yes it’s not normal I know, but I just want to give myself an architectural foundation whereby rather than having relatively undocumented web methods into the application, there’s a self-describing endpoint that can be maintained/utilised when I’m gone)

Following the examples, I have successfully managed to build and embed CoreWCF into a test project that has it’s roots in a standard .NET Core Console Application.

My program startup (for what it’s worth) is:

            WebHost.CreateDefaultBuilder(args)
            .UseKestrel(options => { options.ListenLocalhost(8080); })
            .UseUrls("http://localhost:8080")
            .UseNetTcp(8808)
            .UseStartup<Startup>();

The middleware is doing its job, and I’m able to trace requests through to certain points in the CoreWCF project. I’m not really following what’s going on, and I’m not going to insult anyone’s intelligence by pretending that I do. I realise this is a new project, and that a lot of it probably isn’t ready - but I want to do what I can to help move things forward by learning and understanding.

For this issue though, I’ve been trying to get Postman to return a message from an Operation Contract that has been made to work through a console application.

I’m aware that out-of-the box, the SOAP version is tied to 1.1 (after many hours of trawling through various message samples and error messages, and finding the code in HTTPBinding!)

The service contract I have created, is as follows:

    [ServiceContract]
    public interface ISOAPService
    {
        [OperationContract]
        string GetToken(string username, string passwordHash);
    }

Nothing strenuous at this point!

An example version 1.1 SOAP Message I have made to work ‘the best’ so far:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
 <soapenv:Header></soapenv:Header>
 <soapenv:Body>
 <GetToken>
	<Username>VorTechS</Username>
	<PasswordHash>abcdefghijkl</PasswordHash>
 </GetToken>
 </soapenv:Body>
</soapenv:Envelope>

I’m assuming the above is a correctly formatted message, with the appropriate request header set to text/xml to specify SOAP 1.1.

The problem is, that the message never gets mapped to associated operation contract. Tracing down as far as I can through the code stack, it’s because the message filtering is explicitly trying to find the Action from the Headers collection at this point:

if (pairs[i].filter.Filter2.Match(message)) (line 258 of AndMessageFilterTable.cs)

Okay, so, perhaps I can just add an action?

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
 <soapenv:Header>
 		<Action>http://localhost:8080/wcf/GetToken</Action>
</soapenv:Header>
 <soapenv:Body>
 <GetToken>
	<Username>VorTechS</Username>
	<PasswordHash>abcdefghijkl</PasswordHash>
 </GetToken>
 </soapenv:Body>
</soapenv:Envelope>

But this also fails to read an Action element. Tracing through the code again, the code reading the headers, is return 255 at this point:

kind = (HeaderKind)reader.IndexOfLocalName(localNames, version.Addressing.DictionaryNamespace); (line 1317 of MessageHeaders.cs) for the Action element.

So for giggles I modified the Enum, and some associated code to deal with array sizes to get beyond this point only to be met with:

“The incoming message contains a SOAP header representing the WS-Addressing ‘Action’, yet the HTTP transport is configured with AddressingVersion.None. As a result, the message is being dropped. If this is not desired, then update your HTTP binding to support a different AddressingVersion.” which makes sense given the HTTP Binding is explicitly implementing this.

For even more giggles, I implemented a new shell MessageVersion for SOAP11 and Anonymous addressing.

Which was fine, but then this meant the To header was missing, and that’s because the code reading the header type for the To element is still returning 255, and so adding it as another Action header.

Is there a way I can construct a SOAP message that will correctly invoke my method out of the box? Or should I keep digging?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 18 (17 by maintainers)

Most upvoted comments

There is an Order property on DataMember so you can explicitly specify the order. The xsd schema which correlates to DataContract classes expresses using a sequence element which requires an order to be defined. The alternative would be to define the schema using an all element. If you need to support any order, you need to use XmlSerializer instead, but there’s a performance penalty as it’s generally slower.

In classic WCF alphabetical order of properties is always required. I think the reason was performance while still being forward and backward compatible between different versions of a data contract.