A while back on my old MSDN blog, I demonstrated the concept of “contract first” development in BizTalk through the publishing of schema-only web services using the Web Services Publishing Wizard. However, Paul Petrov rightly pointed out later that my summary didn’t truly reflect a contract-first development style.
Recently my manager had asked me about contract-first development in WCF, and casually asked if we had ever identified that pattern for BizTalk-based development. So, I thought I’d revisit this topic, but start with the WSDL this time. I’m in the UK this week on business, so what better use of my depressing awake-way-to-early mornings than writing BizTalk posts?
So like Paul had mentioned in his post, a true service contract isn’t just the schema, but contains all sort of characteristics that may often be found in a WSDL file. In many cases (including my company), a service is designed first using tools that generate WSDLs and XSDs. Then, those artifacts are shared with service developers who build services that either conform to that service (if exposing an endpoint) or consume it from other applications.
I’ll start with a simple WSDL file that contains a schema definition and a request/response operation called HelloWorld. The schema contains a few constraints such as maxOccurs and minOccurs, and a length restriction on one of the fields.
What I’d like to do is have BizTalk consume the WSDL, and then generate a service that respects that WSDL. How does BizTalk eat a WSDL? Through the use of the dark and mysterious BPEL Import BizTalk project type.
After choosing this project type, a wizard pops up and asks you for the artifacts that make up the service. In my case, I just pointed it to the WSDL which had an embedded schema definition.
After an “import succeeded” message, I’m left with a new project and three files which represent my schema (and base types), and an orchestration that includes the auto-generated port types and schemas.
For simplicity’s sake, I’ll just build out the provided orchestration, with the goal of exposing it as a web service. First, I add a new configured port to the orchestration design surface, careful to choose the generated port type provided to me.
I’m not sure why, but my generated multi-part message isn’t configured right, and I had to manually choose the correct schema type for the message part.
Next, I built two messages (request and response) which used the generated multi-part message types.
Finally, I added send/receive shapes (and a construct) in order to complete the simple orchestration.
I’ll show what happens when using the ASMX Web Publishing Wizard, but first, let’s be forward thinking and use the WCF Service Publishing Wizard. I chose a WCF-BasicHTTP endpoint with metadata so that I can inspect the WSDL generated by my service and compare it against the original. You’ll notice that the “service name” of the service is a combination of the orchestration type name and namespace, and, the “service port” is the name of the orchestration port. Feel free to change those.
I then had to change the target namespace value to reflect the target namespace I used in the original WSDL file.
After completing the wizard (and build a receive location so that my service could be hosted and activated), I compared the WSDL generated by BizTalk with my original one. While all of the schema attributes were successfully preserved (including original restrictions), the rest of the base WSDL attributes did not transfer. Specifically, things like the SOAP action and service name were different, not to mention all the other attribute names.
I went back and repeated this process with the ASMX Web Publishing Wizard, and there were differences. First, the wizard actually kept my original target namespace (probably by reading the Module XML Target Namespace property of the generated orchestration) and also allowed manual choice of “bare” or “wrapped” services. The actual generated WSDL wasn’t much better than the WCF wizard (SOAPAction still not right), and worse, the schema definition was stripped of important restriction characteristics. This is a known problem, but, annoying nonetheless.
At this point, you can argue that this is a moo point since I can take advantage of the ExternalMetadataLocation property on the Metadata Behavior in my generated configuration file. What this does is allow me to point to any WSDL and use IT as the external facing contract definition. This doesn’t change my service implementation, but, would allow me to use the original WSDL file. If I set that configuration attribute, then browsing my BizTalk-generated service’s metadata returns the base WSDL.
One of the key things to remember here is that the SOAPAction value you use is the value set in the BizTalk “MethodName” context attribute. This value is used to match inbound messages to their orchestration subscription (when bound to a SOAP port). If these don’t line up, you get “subscription not found” errors when you call this service. So, if I generate my WCF contract using the original WSDL, and submit that message to my WCF endpoint, the message context looks like this:
And remember that my orchestration port’s generated “operation” property was “HelloWorld” and thus my MessageBox subscription is:
So, if you plan on using an external WSDL, make sure you line these values up. Also note that the orchestration port’s “operation” property doesn’t accept an “http://xxx” style value, so pick something else 😉
I plan on including this topic in the upcoming book, but didn’t feel like squirreling it away until then. It’s an interesting topic, and I’d be curious as to other’s attempts and getting BizTalk to conform to existing service contracts.