Consuming Web Services in BizTalk Without Web Reference

Twice last week, I received WSDLs to consume that BizTalk didn’t like. That is, when I would try and load the WSDL via Add Web Reference, I’d get an error like the following:

Could not generate BizTalk files. Unable to import WebService/Schema. Unable to import
binding ‘WebServiceBinding’ from namespace
http://xmlns.company.com/interface/project/SubmitSubjectImpl’. Unable to import operation
‘SubmitSubject’. The element ‘http://xmlns.company.com/project/subject:subjectrequest’ is
missing.

I also tried from a “regular” .NET project, and no luck. One of the WSDLs used “imports” (a no-no for importing the web reference), and I’m convinced that the other WSDL’s problem was indeed namespace based. Now in both cases, I didn’t have the luxury of telling the WSDL owner to make changes. So how to get around this? Inspired a bit by Jon’s blog, I decided to try using the .NET Framework tool wsdl.exe. For the WSDL using “imports”, I executed WSDL.exe passing in the WSDL, and parameters for each schema used. Sure enough, I was able to generate a valid C# proxy class. The other offending WSDL was also successfully processed using WSDL.exe. As a result, I now had a proxy class needed to consume this service.

Next I added that proxy class to a .NET class library, built, and GAC’ed it. Next I used the provided schema files to create messages in a BizTalk orchestration corresponding to the request and response message. Finally, I connected this to a “two way” port in the orchestration.

After deploying the BizTalk project, I had to configure the necessary SOAP send port. Unlike a “regular” SOAP send port, I was not using an orchestration port as the proxy. Instead, I am now pointing to the proxy class generated by WSDL.exe. On the Web Service tab of the SOAP port, I chose the assembly and method I needed.

Now assuming everything was set up right, I should have been able to call the web service with no problem. But, if we stick with the base assumption that I’m a total meatball, of COURSE it didn’t work the first time. Instead I got this …


A message sent to adapter “SOAP” on send port “Company.Dept.Project.SendTibcoSvc.SOAP” with URI “http://machinename:1234/ProcessDefinitions/WebService” is suspended.
Error details: Failed to serialize the message part “subjectrequest” into the type “subjectrequest” using namespace “http://xmlns.company.com/project/subject”. Please ensure that the message part stream is created properly.

Obviously the proxy couldn’t serialize my XML message. So, I output the message I was sending to the port, and tried validating it against my schema. Sure enough, I got validation errors like The string ” is not a valid XsdDateTime value. and The string ” is not a valid Integer value.. So, I fixed the source problems, and validation succeeded. Finally, when calling the service again, everything worked perfectly.

Moral of story: you can consume web services WITHOUT using a “web reference” as long as you can build the proxy class. Good stuff.

Technorati Tags: ,

Author: Richard Seroter

Richard Seroter is currently the Chief Evangelist at Google Cloud and leads the Developer Relations program. He’s also an instructor at Pluralsight, a frequent public speaker, the author of multiple books on software design and development, and a former InfoQ.com editor plus former 12-time Microsoft MVP for cloud. As Chief Evangelist at Google Cloud, Richard leads the team of developer advocates, developer engineers, outbound product managers, and technical writers who ensure that people find, use, and enjoy Google Cloud. Richard maintains a regularly updated blog on topics of architecture and solution design and can be found on Twitter as @rseroter.

25 thoughts

  1. The technique in this article may help me solve a problem I’m having, but as a BizTalk newbie, there are a couple of things that aren’t quite clear. I’m with you up through running wsdl.exe and building/gac-ing an assembly with the proxy class(es). After that…

    – You used which provided schema files to create request / response messages in an orchestration? Did these come from the same place that provided the wsdl URL? Or was it something you optionally had wsdl.exe dump out?

    – You connected what to a two-way port in the orchestration? A construct message of the appropriate type for the request (using the inbound message as the source)?

    I think part of my confusion is that it’s not clear why an orchestration is needed at all since the whole point is to wind up using a SOAP port assigned directly to a web service instead of to an orchestration.

    Any details you could add to clarify this would be great. Thanks,

    Donnie

  2. Good questions.

    Point #1. I used schemas provided by the same group that gave me the WSDL. If they built a WSDL, there’s most likely a schema either embedded or external.

    Point #2. I was unclear. I connected send and receive shapes (with the request and response message type) to a two-way port in the orchestration.

    You can definitely use a web service with no orchestration, but when you have request/response scenarios, often you need an orchestration to process the response. For one-way scenarios, you can use this mechanism to avoid orchestrations completely.

    Let me know if that helps.

  3. Hi

    Thanks for this trick. It saves a big hassle of rereferencing the stufff everytime its built.
    Although what happens if we’ve a map based on generated schema? How do we get these maps working?

    Thanks

    Vishy

  4. Hey Vishy,

    Map should be fine, assuming you have a schema for the downstream system. The map gets applied before the proxy class gets called, so assuming you are mapping TO the output format, everything’s cool.

    Is that what you were thinking?

  5. Hey Sérgio,

    The example above (and what I do in production solutions) actually is a complex type. Simple types might actually be a challenge, but this concept is ready-made for complex types.

  6. Hi,

    Have you tried to consume web service that has only schema and method name given but no wsdl?

    Any clue on this ?

    Thanks.

  7. Great article! I was fighting with this for a couple of days now!

    I have one problem, I have a complex document that i want to push into a single string that the other server will expand and use. Any good ideas to do this?

  8. Hi Mike,

    I think you’ll have to do that via a custom pipeline component. Since you can’t map from a complex to simple type, the only solution I’m aware of is within a pipeline.

  9. Hi
    I have the wsdl file for the webservice.
    Using this I have created a web proxy and added to biz talk project.
    When I drop the message for the web service request iam getting the parameter error.
    I dont have schema what kind of schema should use for Web service request.
    Any help will be appreciated.

    Thanks

  10. Hari,
    If your web operation input is a simple type (which it sounds like since you can’t find a schema under your web reference), then it’s a bit tricky to call your service without an orchestration. You’d have to use a custom pipeline to build the appropriate web message since you don’t have a schema to map to.

  11. Thanks for your reply.
    Iam using an orchestration.
    Is there a sample where custom pipeline is used for message creation.
    Iam assuming the message to be similar to the structure found in the wsdl file.

    Thanks

  12. How did you fix your proxy serialisation error? I am consuming a method that has no XSD and the only limited info I get is in the WSDL. Coudl you please add what your message looked like before and after fixing?

    Thanks
    Q

  13. Q,
    If you’re referring to the last error mentioned, the “pre” message had an empty “date” node and empty “integer” node, neither of which was allowed. So, to fix it, I added default values. Look at your proxy class and observe the input parameter type and make sure that any dates or ints have non-null values.

  14. This is a very informative article. I have a similar issue, where I am trying to call a web service which accepts string as its only parameter. I too do not have any received message, so I want to construct message on my own in Expression shape in orchestration. The string is in fact XML. I am getting an error that “Failed to serialize the message part “MaterialXML” into the type “String” using namespace “. I greatly appreciate any suggestions you may have.

  15. If your service only takes a string, and you are calling from an orchestration, you will still need to construct the message using a “construct” shape. And, you’ll have a message type auto-generated by the web/service reference.

  16. Hi Richard

    I have published a Biztalk Orchestration as a WCF service. The orchestration takes in a message of type “System.String” and returns a message of type “System.String”. I have a test client(A windows application) where I added this service as a “Service Reference”. When I try calling the method from the object instantiated from the proxy class, I realised that the method takes in just one reference parameter of string type. But the service always returns null as the output value.
    All I do in the orchestration is assign some text to the string message before sending it out.
    Just to confirm if the message is being constructed properly, I tried writing this value to a file through a send port and I get my message intact there.

    When I published this orchestration as a web service (.asmx), it worked perfectly fine.

    Any help in resolving this will be greatly appreciated.

  17. Hey Pradeep,

    I seem to recall while writing my recent article series on WCF that the WCF services didn’t work the same as ASMX services with regards to simple types (http://www.topxml.com/code/cod-491_10213_biztalk-and-wcf-part-v-publishing-operations-patterns.aspx).

    However, it doesn’t appear impossible, as simple types can be returned by the service. That said, I can’t know for sure why your scenario isn’t working, but you may want to consider switching to a complex type instead.

Leave a reply to Richard Seroter Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.