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

The error “Errors exist for one or more children” can often be tricky to uncover.

Usually, when I get this error, I double click on it, and an orchestration shape will be slightly highlighted or bolder than normal, and it will have a red exclamation point on it. You then open it, look for a tiny red squiggly mark, and try to guess what the syntax error is.

Today, I got this error, but no orchestration shape was highlighted. I was about to pull my hair out, then luckily, out of the corner of my eye, I saw a red exclamation mark in the Orchestration Viewer next to a Multipart Message. Apparently I had added a new one, and either 1) not connected it to any schemas, or 2) not deleted it.

Moral of the story – look in the Orchestration Viewer, not just the orchestration shapes for the error.

ErrorsExistInOneOrMoreChildren_OrchestrationView

Here are the steps I used to setup GoDaddy to use my Amazon EC2 Instance (running Windows 2012 with IIS).

I first tested with an old domain that I was no longer using called Discount-Protein.com.

First I created a new “Elastic IP Address” and assigned it to my EC2 Instance.  After setting it up, it looked like this:

GoDaddyWithAmazonAWS_ElasticIPAddress

 

To get to the above, the steps are: 1) Click “Elastic IPS” on the left side of the EC2 dashboard, 2) Click Allocate New Address, and confirm that you really want to create a new one, 3) Click the select box to the left of it, then click the “Associate Address” button at the top.  From there, you get a screen like the one below, where you can select your instance name from a list of all your instances.  Note: The “Instance” textbox doesn’t look like a normal drop-down or combo-box, but when you click it, a list of your instances will appear below it.

 

GoDaddyWithAmazonAWS_ElasticIPAddressAssociate

The rest of the work is done in Godaddy.  Logon, and go to your domain. If your domain is not using GoDaddy as the DNS server, you might want to click “Setup Type” Standard, which means you will be able to setup the zone file in GoDaddy.  I think Amazon can also act as your DNS, but I haven’t tried that yet.  So earlier, I had GoDaddy posting to one of my shared hosted providers.  When I clicked the “standard” button below, that resets to GoDaddy, and a couple of “standard” GoDaddy Nameservers will automatically appear.  NOTE: There could be several GoDaddy Nameservers, yours may not be identical to mine.

 

GoDaddyWithAmazonAWS1

 

Then on GoDaddy, click on the “DNS ZONE FILE” tab.  Below I’m showing their new interface, if you click you can go back to their “classic DNS Manager Interface”.   Make sure you have two rows here, one with the @ sign and one with the www as the host, then sets the “Points to” address to your Amazon AWS Elastic IP Address and then click the button to save your changes.   As with any time you change GoDaddy, you might have to wait 5 minutes to an hour (or more) for the changes to propogate, then you can test.

 

GoDaddyWithAmazonAWS_ZoneFile

 

To test, I created a simple test.html page that just had <h1>Hello World</h1> in it. So I went to a browser and tested with http;//Discount-Protein/test1.html and made sure it was working.

 

 

Error to Solve

“Cannot locate document specification because multiple schemas matched the message type” as shown in context here:

There was a failure executing the response(receive) pipeline:
“Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”
Source: “XML disassembler” Send Port: “sp_someWebServiceSendPortName”
URI: “http://MyServer/MyDir/MyService.svc.svc?wsdl”
Reason: Cannot locate document specification because multiple schemas matched the message type “http://tempuri.org/#SendMessageResponse”.

One Possible Solution: Set AllowUnrecognizedMessage to True

IBizTalk_AllowUnrecognizedMessage

I’ve never encountered this in the past.  I’ve often worked for clients where I develop the webservice and more of the BizTalk.  I recently started working for a client that had a large existing base of production jobs.  When in Rome, sometimes you have to do like the Romans.

I probably wouldn’t have had this error before, because I typically self-enforced on myself the following procedures:

1) I assign a unique namespace to all webservices, never default to http://tempuri.org.  In my opinion, that is just sloppy. I think when you create a new WCF service, that is the default namespace, but anyone with experience would override it.

2) I probably would have created one application with this schema in it (or an app of common schemas), and I would have referenced it from all the other applications. (In other words, you would run the “Add Generated Item/Consume WCF” wizard just once per webservice. The downside of that is that you build a “dependency stack” that you must remember and document.  Then when you change an underlying schema, you have to roll-off (undeploy) and roll back on (re-deploy) all the other apps.  This is not a big deal when using BizTalk Deployment Framework, but it can result in some downtime (maybe a 5 to 30 minute window, depending on the apps).

For a company that values minimal or no down-time to unaffected applications, then this is what you can do.  You can reconsume the same webservice over and over in each application (resulting in it being deployed multiple times).  This now causes a problem when you have XMLReceive instead of PasThru on the Receive Pipeline of the SendPort that calls the webservice (and by the way, you need XMLReceive there if you want to catch SOAP Faults properly).

So to use the XMLReceive Pipeline and NOT get the error above, you can set “AllowUnrecognizedMessage” to True.

Stephen Thomas points out that you can also set this property in your orchestration.  Not sure why you would want to do it there, maybe for a dynamic SendPort?

OutMessage(XMLNORM.AllowUnrecognizedMessage) = true;

Microsoft documents the field here or here, saying only “Indicates whether to allow messages that do not have a recognized message type to be passed through the disassembler.”  That’s about as clear as crystal (yes, I’m being sarcastic).

Alternate Search Keywords (to help people find this post easier): AllowUnrecognizableMessage , Allow Unrecognized Message, Configure Pipeline XMLReceive

T-SQL Error

IDENTITY_INSERT is already ON for table schema.SomeTableName. Cannot perform SET operation for table Table Name.

Solution

At any time, only one table in a session can have the IDENTITY_INSERT property set to ON.  So when you try to set it ON for another table, without turning if off for the first table, this error is generated.

Enter this command for the first table mentioned in the above error.

SET IDENTITY_INSERT [yourSchema].[yourTable] OFF

Context

This happened to me when moving data from one SQL Server to another using RedGate synchronization script.  The script was too large to run all at once; so I had to cut it into smaller pieces.  That utility turns off IDENTITY_INSERT before each set of inserts for each table, then turns it back on at the end of those inserts.

 

 

In the BizTalk world, the person who publishes the orchestration usually creates a small client program to call the webservice and to test it. This is a good practice before going to another developer (either in your company or to a customer) and telling them the service is “working” when you haven’t even tested it yourself.


MyClient client = new MyClient(); //from WCF Service reference
client.ClientCredentials.UserName.UserName = "TestUser";
client.ClientCredentials.UserName.Password = "TestPass";

 Add New Windows User

From Computer Management, add a new user called “TestUser” with a password “TestPass“.
Depending on your policies, make sure “User must change password’ is unchecked, and “User cannot change pasword” and “Password never expires” are checked. Typically in a B2B scenario, you don’t expire the password, because that would break the business processes. Alternatively, you could add a Domain User account in active directory.

ComputerManagement_Add_New_User    ComputerManagement_Add_New_User2

IIS Changes

Enable Basic Authentication

At that point, you no longer want “Anonymous Authentication” enabled, so disable it.
Screen shots below are from IIS 7.5 on Windows 2008/R2.

BizTalk_WCF_Published_Orchestration_IIS_Authentication

Add Authorization Rule for “TestUser”

Click on “Authorization Rules”, then right-click and select ‘Add Allow Rule’, then add ‘TestUser’. Remove any other users you don’t want there.

BizTalk_WCF_Published_Orchestration_IIS_Authorization_Rules3

I’m not 100% sure if you have to restart your app pool or website in order for these changes to take effect. I would suggest doing so.

BizTalk Receive Location Changes

Go to the Receieve Location bound to your orchestration. Click “Configure” then the third tab over labeled “Security”.

Select “Basic” for the “Transport client credential type”.  This must match what we setup in IIS above.

BizTalk_WCF_Published_Orchestration_WCF-WSHTTP_Transport_Properties

Testing

Run your client with “TestUser” and the correct password, make sure it works.
Run your client with an invalid user or password, make sure if fails. When it fails, you should get this error:


System.ServiceModel.Security.MessageSecurityException: The HTTP
request is unauthorized with client authentication scheme 'Basic'. The authenti
cation header received from the server was 'Basic realm="mydomain.com"'. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpC
hannelRequest.WaitForReply(TimeSpan timeout)

I hope to explain the SSL part in a separate blog.

One of the errors I had to overcome with IIS version 8 was: “IIS8 – The binding “*:80′ is assigned to another site “. I’m upgrading from a Windows 2003 server that I’ve had since about 2007 to Windows 2012/R2 hosted on Amazon EC2 (Elastic Cloud).

I only run three sites on it at this time.  One reason I need IIS is that my original shopping cart was written in “Classic ASP”, and I developed over 480 asp programs that I never felt like rewriting.  Many of them are now obsolete, but my first plan is to get to a new environment, then slowly upgrade the code.

I started selling a Hebrew tutorial on the internet back in about 1999.  I was a Microsoft Certified Trainer and teaching a lot of Visual Interdev classes (that was the Visual Studio tool to edit websites and .asp code).  Because of that, I decided to write my own shopping cart as a learning adventure, and it’s been very stable over the years.   When .NET first came out, i considered a re-write, but I had the attitude that “if it ain’t broke, don’t fix it”.

Anyway, that’s the background.  Here’s one of the fun issues I encountered with IIS8.  Like the code above, usually this is a set and forget operation.  At work, usually other teams configure IIS to domains, so it’s rare I play with real domains on IIS.

Error: “IIS8 – The binding “*:80′ is assigned to another site “.

When I was adding my second site, I got this error.

IIS8_theBinding80IsAssignedToAnotherSite

That basically means that I already had another website with no HostName, the same IP address (which was set to “All Unassigned”, that also uses Port 80.

This orcsweb blog seems to do the best job at explaining how to setup bindings for IIS (regardless of the release).

Once I put in my domain name for the “Host name” it worked fine.

I’m currently experimenting with a subdomain, such  test.Wisdom-Calls.com, so that I can have the same site on both the old and new server until I can make sure it’s working.  I’ll post back later with the results of that test.

The question that still remains is can you put a non-Domain name in the “Host Name”.  I tried “test”, and was able to add the site.  But when I went to an html file and clicked “Browse”, it loaded for just an instant as http://test/mytestprogram.asp, but then it suddenly switches to http;//test.com/mytstprogram.asp.  Test.com is a real domain owned by someone else, and the redirect to the home page: https://www.test.com/index.html.

How to Change Bindings in IIS8

To change the bindings, you mus tright click then select “Edit Bindings…”.  I have no idea why there isn’t an icon in the “Features View” tab for that.

IIS8_Set_Bindings

 

In another blog, I’ll explain how I set up GoDaddy to work with Amazon EC2 and my “Elastic IP Address”.

 

 

 

 

Error:

The document specification <ddlname.schemaName+SchemaRootNode> from assembly <etc…> failed to load.  Verify the schema for this document specification is deployed and is in the Global Assembly Cache.

Solution:

In our case, this happened when we ran a C# client tester program that called an orchestration published as a WCF service.  The Application Pool was not configured correctly, and had .NET v2 instead of .NET v4.  Thus it was looking in the “old GAC”, rather than the new one.  The schema was truly deployed and GAC’ed.  We just changed the app pool and restarted it.

 

I think most blogs talk about requiring that the PortType be “Public” instead of “Internal”.  However, today I learned that not only do you have to build (compile) the orchestration, you must also deploy it.  Even though I compiled, the new port was not appearing in the WCF Publishing Wizard.  I was getting desparate, finally decided to do a Deploy, then it worked fine.

When trying to export an MSI from BizTalk Admin Console for an application, I got this error:

“Unable to serialize web directory… Verify the location exists and it is accessible”

Example of error in BizTalk Admin Console

BizTalkError_UnableToSerializeWebDirecotry

 

In my case, we had SharePoint on the same machine as BizTalk, and thus a coworker set up a special virtual directory for published BizTalk services, and assigned port 9000. Thus, when I ran the wizard to create the webservice, I had to specify port 9000, and now on the export MSI file, I also need to specify the port 9000 (following a colon after the localhost name).

Example of Solution

BizTalkError_MyFix_UnableToSerializeWebDirecotry