I am in the process of creating a Send Port in Biztalk, that uses the Wcf-Custom adapter for sending SOAP requests.
So far I have been testing the SOAP requests in Visual Studio, using C# code from the System-ServiceModel namespace. See code below:
/ CODEGEN: Generating message contract since the operation transferPayments is neither RPC nor document wrapped.
[System.ServiceModel.OperationContractAttribute(Action="urn:CorporateService:transferPayment", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
transferPaymentsResponse transferPayments(transferPayment1 request);
[System.ServiceModel.OperationContractAttribute(Action="urn:CorporateService:transferPayment", ReplyAction="*")]
System.Threading.Tasks.Task<transferPaymentsResponse> transferPaymentsAsync(transferPayment1 request);
I need to add this "transferPayment" action to the SOAP Action Header field in the adapter.
Using the provided example, I've come up with this
<BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Operation Name="TransferPayment" Action="http://bankconnect.dk/schema/2014/CorporateService/TransferPayment" />
</BtsActionMapping>
Where "http://bankconnect.dk/schema/2014" is the namespace, "CorporateService" is the service, and "TransferPayment" is the action. I'm unsure if this is the correct way to go about implementing this.
My question how I should format the SOAP Action Headers, so that they correspond to the c# code used.
I'd suggest you use the BizTalk WCF Service Consume Wizard to generate the schema's inside BizTalk. This would make all the possible Actions for you.
Related
i am currently building a Client to communicate with a Gateway of a Charge Point.
The communication is build with OcppV1.5 over Soap & Http.
The Server doesn't accept my request. I get a Http Response 500 with the Error Reason:
"XML Request is not well formed, Action does not exist."
I looked into the wsdl files but I just don't understand why it doesn't accept my action.
My Request looks something like this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="https://www.w3.org/2005/08/addressing" xmlns:cs="urn://Ocpp/Cp/2012/06/">
<SOAP-ENV:Header>
<cs:chargeBoxIdentity>0000.0000</cs:chargeBoxIdentity>
<wsa:From>
<wsa:Address>http://000.000.000.000:0000</wsa:Address>
</wsa:From>
<wsa:To>http://000.000.000.001:0001</wsa:To>
<wsa:Action>/ChangeConfiguration</wsa:Action>
<wsa:MessageID>00000.000000000000</wsa:MessageID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<cs:changeConfigurationRequest>
<cs:key>MeterValueSampleInterval</cs:key>
<cs:value>60</cs:value>
</cs:changeConfigurationRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Update:
As Bogdan suggested I tried to send the same message using SoapUi and it worked. The generated Request from SoapUi looks like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="urn://Ocpp/Cp/2012/06/">
<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<ns:chargeBoxIdentity>000000.00000</ns:chargeBoxIdentity>
<wsa:Action>/ChangeConfiguration</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>http://000.000.000.000:0000</wsa:Address>
</wsa:ReplyTo>
<wsa:MessageID>uuid:00000000-0000-0000-0000-000000000000</wsa:MessageID>
<wsa:To>http://000.000.000.000:00000/</wsa:To>
</soap:Header>
<soap:Body>
<ns:changeConfigurationRequest>
<ns:key>MeterValueSampleInterval</ns:key>
<ns:value>300</ns:value>
</ns:changeConfigurationRequest>
</soap:Body>
</soap:Envelope>
It's hard to tell from what you posted why you are getting an error, so I can only add some information that can hopefully allow you to troubleshoot the issue.
Your message has WS-Addressing headers, <wsa:Action> being one of them. The value of this field should be specified in the WSDL if your WSDL also includes WS-Addressing Metadata information, or should be specified in the documentation of the web service you are invoking. Your error message "XML Request is not well formed, Action does not exist" seems to indicate that there might be an issue with this field, but there is another action that SOAP services have which is a SOAP action. I asked about it in the comment above to make sure it's eliminated as a source of problems. In SOAP 1.1 it's called SOAPAction and is a separate HTTP header, while in SOAP 1.2 it's an action parameter on the HTTP Content-Type header. Based on the http://www.w3.org/2003/05/soap-envelope namespace, you have a SOAP 1.2 message.
With these explanations layed out, I suggest you take the WSDL and feed it to SoapUI who can generate sample requests that you can use to invoke the web service. If the WSDL also contains WS-Addressing Metadata, SoapUI should be able to pick it up and help you fill in the values you need. If not, look again through the WSDL for Action elements (make sure you differentiate between the SOAP Action and the WS-Addressing Action using their XML namespaces) or through the service documentation.
Once you get a succesfull call using SoapUI, then try to duplicate it with your code. At that point you can again use SoapUI to troubleshoot things and inspect your code built message to see it resembles the one you can successfully send with SoapUI.
Hope this helps get you closer to a resolution.
I have several SOAP web services that have the same interface but have different URLs' and namespaces'.
URL 1 http://badservice.com/one has a namespace "one-ns"
URL 2 http://badservice.com/two has a namespace "two-ns"
When I generate a web service client via svcutil from http://badservice.com/one?wsdl, I can only use it for http://badservice.com/one. Once I try to send a request to http://badservice.com/two SOAP service says
namespace mismatch require http://nanopetdbs.driver.maestro.ibtech.com found http://ozkaraslanpetroldbs.driver.maestro.ibtech.com
I can generate clients for each web service URLs at the worst scenario.
I need an idea to prevent code duplication in this case. I have tried altering namespace while sending requests, could not make it.
I need to change the highlighted place of the envelope at the runtime.
No, we can’t specify these values at the runtime. During SOAP communication, this field will be used for addressing the method to be called.
Here is a communication telegram captured by Fiddle.
The SOAPAction field will specify the method to be called.
If these values can be changed at the runtime, the addressing method becomes confusing. This is the meaning of a service contract with its namespace and name properties.
[ServiceContract(Namespace ="http://mycommany.com")]
public interface IService
{
[OperationContract(Name ="Mymethod")]
Int32 Add(Int32 Num1, Int32 Num2);
}
Besides the BasicHttpbinding, some other bindings, such as wshttpbinding using ws-addressing. They use these properties(namespace, name) in Action SOAP header to specify the addressing method.
In summary, It is these attributes that determine the addressing mode at the runtime, so we cannot modify these attributes(namespace, name) at the runtime.
Feel free to let me know if there is anything I can help with.
I have a WCF service based on BizTalk, I'm not sure how it was deployed or generated but as far as I know it was made using the BizTalk wizard for publishing WCF services. The problem is the BizTalk server installation was removed and now the service still here but it doesn't work, when i invoke the URL the service responses an exception: The BizTalk receive location may be disabled. I need to generate a WCF service in order to replace that service. I have one example request and response and the folder with the service, with a lot of stuff, XML, definitions, etc but there are no DLLs. The SVC markup has a reference to a BizTalk logic.
<%# ServiceHost Language="c#" Factory="Microsoft.BizTalk.Adapter.Wcf.Runtime.WSHttpWebServiceHostFactory, Microsoft.BizTalk.Adapter.Wcf.Runtime, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
So here goes my question, does anybody know how to generate a service based on request or response to supplant the service.
If you only have the request and response xml then it's a bit tricky. Even if you manage to recreate the service there is no guarantee that existing service consumers will be able to continue to call the service without any change. However, if you want to have a go, this rough guide will help:
Extract the operation signature from the soap request and response
This should be simple. Just look at the part of the request xml which defines the SOAP body. As an example:
<soap:Body xmlns:m="http://www.bookshop.com/prices">
<m:GetBookPrice>
<param1 xsi:type="xs:string">Metro 2033</param1>
</m:GetBookPrice>
</soap:Body>
This shows that the operation name was called GetBookPrice, and that it takes a string as an argument. Now look at the soap body for the response, for example:
<soap:Body xmlns:m="http://www.bookshop.com/prices">
<m:GetBookPriceResponse>
<return xsi:type="xs:decimal">5.99</return>
</m:GetBookPriceResponse>
</soap:Body>
This tells us that the return type of the operation was decimal:
public decimal GetBookPrice(string bookName);
So now you can recreate the service operation in a vanilla WCF service.
It's possible that the service definition included complex types rather than primitives, in which case you need to infer the types from the request/response xml. If the types are too large, you can try to automatically infer them by:
Infer XSD from XML - you'll need to extract just the request and response types from the request/response files, then run them through xsd.exe, which will try to generate the XSD schemas for your request/response types.
Infer CS from XSD - once you have the XSD files, again use xsd.exe to infer the classes for these files. You can then annotate these classes with the DataContract and DataMember attributes and then you can use them in your service definition.
In conclusion, it's not a task I envy you for - even if you manage to faithfully reconstruct the service and type definitions, you may still find that existing clients cannot call the service based on having missed some optional data which was not present in the request/response files you have.
If you create a client for the service in a blank project using Visual Studio (References > "Add Service Reference") you will get the interface that you need to implement (as well as POCOs for all the parameters).
Then create a new WCF project and use that interface and those classes as your contract.
This way you will honour the existing schema without having to manually interpret it.
Look for WcfServiceDescription.xml file in your service folder, its under \App_Data\Temp folder of your service physical folder (you can check IIS virtual directory where its pointing to find the physical path).
Use this file to publish the service again. Based on the definition in it, make sure, you deploy required assemblies to GAC (e.g. schema or orchestration assemblies) before publishing the service again.
Then you can use BtsWcfServicePublishing.exe tool which you can download from http://www.microsoft.com/en-us/download/details.aspx?id=21973 from command prompt. On this exe pass the WcfServiceDescription.xml file along with its full path
In the end, I used an ashx handler for procesing the request (cambined with the other responses were very helpfull) xml-> generate xsd -> parse and read request. The only problem is the .ashx termination.
I do not understand when I should put the [MessageHeader] instead of the [MessageBodyMember]?
I have read that it's used to conform some protocol like Soap, but still, what does it change at the end?
SOAP is a protocol in which each message (request or response) is made up of two parts: the Header and the Body, inside an Envelope:
<s:Envelope xmlns:s='the namespace for the soap version'>
<s:Header>
<!-- SOAP headers will come here -->
</s:Header>
<s:Body>
<!-- SOAP body members will come here -->
</s:Body>
</s:Envelope>
You normally wouldn't use [MessageContract] (and MessageHeader or MessageBodyMember) in WCF services, only if you really need to interop with some 3rd party which expects the data in a certain format.
I think when I want to put something independent of message content, I will put it in the message header.
And if you want another party to read something from your message, it should be put in the header, because sometimes you may allow someone to read the message header not message body as it contains confidential contents.
You can think about it as difference between message data (MessageBodyMember) and message metadata (MessageHeader). There is plenty of build in standardized headers provided by WCF which deals with addressing, security, reliable messaging, etc. In default WCF implementation it is related only to SOAP.
There is also general rule that in complex messaging architecture there can be intermediaries who read metadata and use them to some processing and message routing (they can even add additional metadata) but they should never interfere with message body (data). In case of security they can even not be able to read message body or some metadata (headers).
In case of WCF you are able to set different security requirements (none, signed, signed and encrypted) for each message header and for whole message body (WCF doesn't support separate security requirements for different body parts). That can also lead to some decision about using body member or header.
For example if you decide to make some custom authentication, or transferring some client information in each message you will probably create custom header for that but real data payload related to the operation will be part of message body.
There is a series of SOAP services which I wish to call (across a series of services), and while the end points are well defined & documented, there is no WSDL data... so I decided to build my own.
In order to do so, I built a test WCF service which matches the known interface of the service I wish to call.
I then saved the WSDL it exposed, changed the base address the WSDL references, created my proxy (with wsdl.exe), added it to a test client project, and can successfully create a proxy and make calls which causes the SOAP service to send the expected response... only this expected response is not picked up by the proxy and returned to the calling code.
When looking at the back and forth traffic... I can clearly see that the service is replying with what I want.
Any suggestions as to how I might troubleshoot this and get the proxy to pickup the data?
Given the replies are effectively identical, I'm forced to look back at the differences between what my client is sending and another sends.
A known working app sends it's XML blob starting with the following:
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
While my client immediately starts with the envelope (without the xml tag, and with one less namespace):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
The other difference is that the message within the body is prefixed by a namespace in theirs, while mine it is not... though both define this namespace within the tag.
Ala:
<s:Body>
<u:DoSomething xmlns:u="urn:http://some.namespace.org" />
</s:Body>
VS:
<s:Body>
<DoSomething xmlns="urn:http://some.namespace.org" />
</s:Body>
This is not a namespace:
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
It's setting the encoding style for the envelope which, even though it's not required per the SOAP spec, may be required by the specific implementation you're talking to. Do you have enough control over what you're sending from the client to get that put on there?
Other than that, the XML PI is not required and I think you're definitely on the right track looking at the body XML. This is almost always the case of some kind of namespace mismatch somewhere. Are you 100% positive the namespace URIs are identical?
The most likely problem is the VS version using a "default" XML namespace. There are soap parsers that I've worked which don't work correctly when using an un-aliased (default) namespaces. If you know using the u: alias works with the service, your proxy should also generate it even when every tag inside the s:Body element is prefixed with the alias.