This blog explains how to pass userid/password using Basic Authentication to a SOAP 1.1 web service. It took me about 2 1/2 days of trying different things to get it working. SOAP-UI was working, and I couldn’t get any of the Basic-HTTP, WS-HTTP, or WCF-Custom SendPorts to work, even after creating a “behaviorEnhancement” plug-in.

Since SOAP-UI was working, I finally followed advice of blogs and coworkers to use Fiddler to capture the request with SOAP Headers. Then it only took an hour or two to properly format the request for a message assignment shape in an orchestration.

This was the error I was getting when it wasn’t working, i.e. trying to configure the user/pass in the ports. I knew from SOAP-UI that if I passed a bad password, I would get “Not Authenticated” instead of “Unauthorized”.

<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <faultcode>soap:Server</faultcode>
  <faultstring>Unauthorized</faultstring>
</soap:Fault>

Fiddler provided the following capture:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://somesite.com/serviceOrder/service/types">
   <soapenv:Header>
   <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
   <wsse:UsernameToken wsu:Id="UsernameToken-E4E3CB1F68472DCF2914369675811859">
	   <wsse:Username>myuser</wsse:Username>
	   <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">mypass</wsse:Password>
	   <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NgLGMIejoGGLznG/+Qma5g==</wsse:Nonce>
	   <wsu:Created>2015-07-15T13:39:41.185Z</wsu:Created>
   </wsse:UsernameToken>
   </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <typ:serviceJobListRequest>
         <!--Various Parms Here:-->
      </typ:serviceJobListRequest>
   </soapenv:Body>
</soapenv:Envelope>

The code below worked for me. It goes in a Message Assignment shape (usually after your map) before the Send shape to the web service (as shown in the red box below):

MessageAssignment_Set_Custom_SoapHeaders_Example

xmlDocSoapHeader.LoadXml(
   "<headers>" + 
   "<wsse:Security mustUnderstand=\"1\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" + 
   "<wsse:UsernameToken wsu:Id=\"UsernameToken-E4E3CB1F68472DCF2914369675811859\">" +   
   "  <wsse:Username>" + strUserFromSSO + "</wsse:Username>" + 
   "  <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" + strPasswordFromSSO + "</wsse:Password>" + 
   "  <wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">NgLGMIejoGGLznG/+Qma5g==</wsse:Nonce>" +
   "  <wsu:Created>" + System.DateTime.UtcNow.ToString("s") + "Z" + "</wsu:Created>" + 
   "</wsse:UsernameToken>" +
   "</wsse:Security>" + 
   "</headers>"  
);

msgListNewCallRequest(WCF.OutboundCustomHeaders) = xmlDocSoapHeader.OuterXml;

This also has a big advantage for our specific application. We might need to pass a different user/password for different regions. For example, the same app might run for USA and for Europe; so we can dynamically switch out the user based on some region or country code.

Here’s another trick. To test the XML Load in C#, rather than having to run the orchestration, I created a small console program and tested like this:


        static void Main(string[] args)
        {
            testSyntax(); 
            Console.WriteLine("Press enter to end:");
            Console.ReadLine();
        }

        public static void testSyntax()
        {
            System.Xml.XmlDocument xmlDocSoapHeader = new System.Xml.XmlDocument(); 
            string strUserFromSSO = "test"; 
            string strPasswordFromSSO = "test"; 
            Console.WriteLine("TestDate=" + System.DateTime.UtcNow.ToString("s") + "Z"); 
            // 02/10/2015 12:21 with Richard - remove soapenv:Header   THIS ONE WORKS!  
xmlDocSoapHeader.LoadXml(
   "<Header xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" + 
   "<wsse:Security soapenv:mustUnderstand=\"1\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" + 
   "<wsse:UsernameToken wsu:Id=\"UsernameToken-E4E3CB1F68472DCF2914369675811859\">" +   
   "  <wsse:Username>" + strUserFromSSO + "</wsse:Username>" + 
   "  <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" + strPasswordFromSSO + "</wsse:Password>" + 
   "  <wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">NgLGMIejoGGLznG/+Qma5g==</wsse:Nonce>" +
   "  <wsu:Created>" + System.DateTime.UtcNow.ToString("s") + "Z" + "</wsu:Created>" + 
   "</wsse:UsernameToken>" +
   "</wsse:Security>" + 
   "</Header>" 
    );

//msgListNewCallRequest(WCF.OutboundCustomHeaders) = xmlDocSoapHeader.OuterXml;
        }

This was my original MSDN social forum post on this issue. Most of the answers were of little value, which why I posted a full blog here.

I found the following links useful in my research of this issue:
1) Showed how to wrap or not wrap the soap headers: Forum Post
2) Similar: Forum Post
3) Similar problem, but from C# not BizTalk: Blog Post
4) Good overview and discussion (but from C# not BizTalk): StackOverflow
5) MSDN – over simplified way to add SoapHeaders: MSDN SoapHeaders
6) Related: Blog Post

Now, below are the blogs that lead me down the path of a custom WCF behavior extension, which still get me the “Unauthorized” result – so that was a loss of almost one day. I’m not saying it would never work, but I didn’t get it working. It required writing a C# program, putting it in the GAC, registering it to BizTalk, then magically it appears in the Behavior tab of the WCF-Custom SendPort. However, it was an interesting learning experience, but rather tedious.

1) Forum Post
2) Blog Post
3) Blog Post
4) How to Register Extensions: Blog Post

When you publish a BizTalk schema or a BizTalk orchestration as a webservice, you may find you have left the warm comfort of BizTalk and now have to become an IIS and WCF expert.

MEX, WSDL, Endpoints

From what I have gleaned from the sites below, you really don’t need “MEX” endpoints. “MEX” stands for Metadata Exchange. However, they will return the WSDL to you with one call, instead of several.

Ido Flatow – WSDL vs MEX

MEX and WSDL are two different schemes to tell potential clients about the structure of your service.So we can choose to either make the service contracts public as “metadata exchance format” (MEX) or in the “web service description language” (WSDL) — the latter being accessible via HTTP(s). There’re 2 ways to expose metadata.One with MEX endpoint and one with . The first one will expose metadata using WS-MetadataExchange and second one will use WSDL
Above quoted from: Saurabh Somani’s blog – Http Get vs Mex End Point

One forum post said that “WSDL” is the “legacy method” and “MEX” is the “new improved version”. But he was corrected by a follow-up post, saying that WSDL is still used by many service platforms, and MEX and WSDL delivery the same output. (Ido’s blog above actually compares the results from the two.)

Mex is designed to support non-HTTP protocols. A client can add a reference in VS only if httpGetEnabled/httpsGetEnabled is enable or if you have define a mex endpoint in the configuration of your service. The best practice is to expose metadata on dev environnement but not on production. MEX are more configurable, while WSDL is more interoperable with older versions of clients and non-.net clients that work with WSDLs.

To disable MEX and expose your service via WSDL, then 1) do not specify a MEX endpoint, and 2) specify httpGetEnabled=”true”.

StackOverflow btween WSDL and MEX Endpoints

BizTalk and Error “Could not find a base address that matches scheme http for the endpoint with binding MetadataExchangeHttpBinding”

The MSDN forum posts weren’t coming up in Google, I only found them when I posted in the MSDN forum for BizTalk. So I decided to post them here to give them some “google love”. None of them actually helped me solve my issue, but when you are getting this error you probably need to read all of them to see which one fits your case.

My issue – WCF Published Orch – BizTalk could not find a base address that matches scheme http for the endpoint with binding wshttpbinding MetadataExchangeHttpBinding
Solution: Added port 80 to Bindings for website. Something in the WSDL/MEX needed http instead of https.

biztalk https wcf error could not find a base address that matches scheme https for the endpoint

BizTalk – WCF error could not find a base address that matches scheme https for the endpoint with binding
Solution: referred to another WCF (Non-BizTalk) post WCF Security using custom username and password

BizTalk – could not find a base address that
matches scheme http for the endpoint with binding webhttpbinding

Solution: 1) Under bindings tag make sure you have set

<security mode="Transport" />

2) Also please try to use the mexHttpsBinding:

     <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>

3) Add base address

<baseAddresses>
      <add baseAddress=https://localhost:10201/Service />
</baseAddresses>

BizTalk could not find a base address that matches scheme http for the endpoint with binding wshttpbinding
Solution: This is working fine after i have changed my configuration file. i forgot to include binding configuration and changed mexHttpBinding to mexHttpsBinds and changed httpGetEnabled = false.

BizTalk could not find a base address that matches scheme http for the endpoint with binding wshttpbinding – Registered base address schemes are [https]

Solution for that issue: This is working fine after i have changed my configuration file. i forgot to include binding configuration and changed mexHttpBinding to mexHttpsBinds and changed httpGetEnabled = false.

BizTalk could not find a base address that matches scheme http for the endpoint with binding – Registered base address schemes are [https]
Solution: Just wondering whether you have configurd you application directory with HTTP protocol supports. Sometimes ppl tends to delete that and get the above exception. I have the following config for a test calcservice and it all works fine.

Moving to https = Could not find a base address that matches scheme
Solution: I’m not sure what was wrong but I simply took the certificate off and peeled the whole thing back to using basic http. I then carefully reapplied everything and it just worked. I think it was some sort of quirk or missed step in IIS.

How to Pass Custom WCF Soap Headers from BizTalk using WCF.OutboundCustomHeaders

I needed to call a WCF webservice from BizTalk that required three SOAP fields. In addition to Username and Password (standard), they had one custom field called ApplicationID.

Code in Message Assignment Shape

xmlDocSoapHeader.LoadXml(
"<headers>" +
" <Username>" + strSOAPUserFromSSO + "</Username>" +
" <Password>" + strSOAPPasswordFromSSO + "</Password>" +
" <ApplicationID>" + strSOAPAppIDFromSSO + "</ApplicationID>" +
"</headers>"
);

msgRcvdEquipReq(WCF.OutboundCustomHeaders) = xmlDocSoapHeader.OuterXml;

I used the standard “Add Generated Schema” and “Consume WCF Service” wizard, but that didn’t provide any help with the SOAP Headers. I read some blogs that talked about creating a custom SOAP schema, promoting fields, and so-on, and perhaps that would work, but ultimately the above is what worked fine.

PassingCustomWCFSoapHeadersFromBizTalk