I am trying to get the method name from the wsdl removed. I refered to many stackoverflow queries and tried using MessageContract(IsWrapped=false) and also set the below on the ServiceContract and OperationContract
[XmlSerializerFormat(Use = OperationFormatUse.Literal, Style = OperationFormatStyle.Document, SupportFaults = true)]
But still no luck, the method name comes in the soap request in SoapUI as below:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:the="http://schemas.datacontract.org/2004/07/xx.xxx.xxxx.xxxx">
<soapenv:Header/>
<soapenv:Body>
<tem:GetResult> <!--need to remove this-->
<!--Optional:-->
<tem:Pet>
<!--Optional:-->
<the:Name>?</the:Name>
</tem:Pet>
</tem:GetResult> <!--need to remove this-->
</soapenv:Body>
</soapenv:Envelope>
[ServiceContract]
[XmlSerializerFormat(Use = OperationFormatUse.Literal, Style = OperationFormatStyle.Document, SupportFaults = true)]
interface IPetService
{
[OperationContract]
[XmlSerializerFormat(Use = OperationFormatUse.Literal, Style = OperationFormatStyle.Document, SupportFaults = true)]
string GetResult(Pet test);
}
[MessageContract(IsWrapped = false)]
public class Pet
{
[MessageBodyMember]
public string Name { get; set; }
}
The project in .net core 3.1 and using soapcore package.
Any advice would be highly appreciated?
Thanks.
Related
Overriding GetWebRequest and accessing the Headers works just fine. Now I need to set an attribute. My goal looks like
<soapenv:Envelope xmlns:urn="urn:company:sap:ds:sales" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<messageId xmlns="http://www.company.com/foo/bar/soap/features/messageId/">urn:uuid:123c155c-3ab4-19ca-a045-02003b1bb7f5</messageId>
</soapenv:Header>
<soapenv:Body>
...
</soapenv:Body>
</soapenv:Envelope>
The problem is how to generate the xmlns="http://www.company.com/foo/bar/soap/features/messageId" attribute in the Header. I just spent a few hours reading documentation, and it seems there simply is no way to set an attribute in the header.
Could I simply quote the quotes and write
request.Headers["messageID xmlns=""http://www.company.com/foo/bar/soap/features/messageId"""] = "urn:uuid:123c155c-3ab4-19ca-a045-02003b1bb7f5";
But this feels somehow wrong to me..
please refer to the below code snippets, wish it is useful to you.
class Program
{
static void Main(string[] args)
{
ServiceReference1.ServiceClient client = new ServiceClient();
using (new OperationContextScope(client.InnerChannel))
{
UserInfo userInfo = new UserInfo();
userInfo.FirstName = "John";
userInfo.LastName = "Doe";
MessageHeader aMessageHeader = MessageHeader.CreateHeader("UserInfo", "http://tempuri.org", userInfo);
MessageHeader bheader = MessageHeader.CreateHeader("messageId", "http://www.company.com/foo/bar/soap/features/messageId/", "urn:uuid:123c155c-3ab4-19ca-a045-02003b1bb7f5");
OperationContext.Current.OutgoingMessageHeaders.Add(aMessageHeader);
OperationContext.Current.OutgoingMessageHeaders.Add(bheader);
var result = client.Test();
Console.WriteLine(result);
}
}
}
public class UserInfo
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Result.
This is an implementation on the client-side, you can also use IClientMessageInspector or IDispatchMessageInspector interface to add the custom header on the client-side and server-side.
Feel free to let me know if there is anything I can help with.
I'm tasked with creating a web service that conforms to a particular wsdl and I haven't used SOAP or asmx before.
When I create a request in SoapUI I get the following structure, which is the same as the client will be using to send requests. (using placeholder names)
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:par="http://www.foo.com/schemas/method">
<soapenv:Header>
<par:SOAPHeaderRequest>
<par:ApplicationID>ID</par:ApplicationID>
</par:SOAPHeaderRequest>
</soapenv:Header>
<soapenv:Body>
<par:Body>
</par:Body>
</soapenv:Body>
</soapenv:Envelope>
However, when I'm trying to create the service I have this structure:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Method xmlns="http://www.foo.com/schemas/method">
<request>
<SOAPHeaderRequest>
<ApplicationID>string</ApplicationID>
</SOAPHeaderRequest>
<body>
<Property>string</Property>
</body>
</request>
</Method>
</soap:Body>
</soap:Envelope>
I'd like to know how to remove the Method node wrapper, and how to move the SOAPHeaderREquest into a soap:Header.
Here's my sample code:
interface and objects
[ServiceContract(Namespace = "http://www.foo.com/schemas/method")]
public interface IServiceContract
{
[XmlSerializerFormat]
[OperationContract]
ResponseObject Method(RequestObject request);
}
[System.Serializable()]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://www.foo.com/schemas/method")]
[MessageContract(IsWrapped = false)]
public class RequestObject
{
[System.ServiceModel.MessageHeader(Namespace = "http://www.foo.com/schemas/method")]
public SOAPHeaderRequest SOAPHeaderRequest;
[System.ServiceModel.MessageBodyMember(Namespace = "http://www.foo.com/schemas/method", Order = 0)]
public Body body;
public RequestObject()
{
}
public RequestObject(SOAPHeaderRequest SOAPHeaderRequest, Body body)
{
this.body = body;
}
}
[System.Serializable()]
[System.Xml.Serialization.XmlType(AnonymousType = true, Namespace = "http://www.foo.com/schemas/method")]
[MessageContract(IsWrapped = false)]
public class ResponseObject
{
[System.ServiceModel.MessageHeader(Namespace = "http://www.foo.com/schemas/method")]
public SOAPHeaderResponse SOAPHeaderResponse;
[System.ServiceModel.MessageBodyMember(Namespace = "http://www.foo.com/schemas/method", Order = 0)]
public Body body;
}
[System.Serializable()]
public class Body
{
public string Property { get; set; }
}
asmx
[WebService(Namespace = "http://www.foo.com/schemas/method")]
[WebServiceBinding(ConformsTo = WsiProfiles.None)]
public class M5NapaPartUpdateService : WebService, IServiceContract
{
[WebMethod]
[SoapMethod(SoapAction = "method")]
public ResponseObject Method(RequestObject request)
{
return new ResponseObject();
}
}
Let me know if there's anything else you'd need.
Thanks!
WSDL distinguishes between two message styles:
document and RPC.
The message style affects the contents of the SOAP Body:
Document style: The SOAP Body contains one or more child elements called parts. There are no SOAP formatting rules for what the body contains; it contains whatever the sender and the receiver agrees upon.
**RPC style:**RPC implies that SOAP body contains an element with the name of the method or operation being invoked. This element in turn contains an element for each parameter of that method/operation.
Your wsdl is written in Document Literal style.
If you are using service contract then I believe you are using WCF framework to write service code.
You can specify below parameters to make WSDL as you expect.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples"), XmlSerializerFormat(Style = OperationFormatStyle.Document,
Use = OperationFormatUse.Literal)]
Reference- https://www.ibm.com/support/knowledgecenter/en/SSB27H_6.2.0/fa2ws_ovw_soap_syntax_lit.html
Hope this helps.
I need to send a createShipmentRequest() to DHLWebSerivces and my problem is to add a security header to the soap request.
Edited to add the DHL documentation:
I'm trying the last solution proposed here How To Pass Soap Header When WSDL Doesn't Define It?.
public partial class SecurityHeader : SoapHeader
{
public string Username { get; set; }
public string Password { get; set; }
}
public partial class gblExpressRateBook
{
public SecurityHeader securityHeader = new SecurityHeader() {
EncodedMustUnderstand = "1", Username = "*****", Password = "*****" };
protected override XmlWriter GetWriterForMessage(SoapClientMessage message,
int bufferSize)
{
message.Headers.Add(securityHeader);
return base.GetWriterForMessage(message, bufferSize);
}
}
Here is the result in Fiddler:
Edited to add the entire first line "soap:Envelope".
soap:Envelope [ xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:xsd=http://www.w3.org/2001/XMLSchema ]
soap:Header
SecurityHeader [ xmlns=http://scxgxtt.phx-dc.dhl.com/euExpressRateBook/ShipmentMsgRequest ]
...
And here is what I should have according to a code sample of DHL:
Edited to add the indentation of the code.
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:glob="http://scxgxtt.phx-dc.dhl.com/glDHLExpressLabel/providers/globalLabel">
<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">
<wsse:UsernameToken wsu:Id="UsernameToken-5" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>*****</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">*****</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">*****************</wsse:Nonce>
<wsu:Created>2010-02-12T17:40:39.124Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
Edited to add SOAPUI request done via Fiddler:
Sent request via Fiddler:
Received response via Fiddler:
Can someone please help me build this "wsse:Security" header?
I'm trying to replicate an old soap service, which is in production at the moment. The contract, requests and responses has to be the exact same so that we dont need to update all dependent systems which is using this service. The thing with this old soap service, is that one of the responses are pretty weird. It has the following structure:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://something" xmlns:ns1="http://something1">
<soap:Body>
<ns:MyResponse>
<ns:GetInfo>
<ns1:IdNumber>12345</ns:IdNumber>
<ns1:PersondataList>
<ns1:FirstName>John</ns1:FirstName>
<ns1:LastName>Travolta</ns1:LastName>
</ns1:PersondataList>
</ns:GetInfo>
</ns:MyResponse>
</soap:Body>
</soap:envelope>
This immiditaly makes me thinking of the following structure in code:
public class GetInfo
{
public string IdNumber {get; set;}
public PersonData[] PersondataList {get; set;}
}
public class PersonData
{
public string FirstName {get; set;}
public string LastName {get; set;}
}
When testing this in SoapUI, my response are the following:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://something" xmlns:ns1="http://something1">
<soap:Body>
<ns:MyResponse>
<ns:GetInfo>
<ns1:IdNumber>12345</ns:IdNumber>
<ns1:PersondataList>
<ns1:Persondata>
<ns1:FirstName>John</ns1:FirstName>
<ns1:LastName>Travolta</ns1:LastName>
<ns1:Persondata>
</ns1:PersondataList>
</ns:GetInfo>
</ns:MyResponse>
</soap:Body>
</soap:envelope>
As you can see, the difference between the original soap response and my replication is the Persondata tag before FirstName and LastName. In my opinion this is the correct structure, but as mentioned before, I need to replicate the response in the exact same way...
How can I produce the same structure as the original response? Do I need to write my own Serializer? Is there any attributes that I can mark my properties with?
Thanks in advance.
For those of you stumbling upon this type of problems. Add the following attribute to your property:
[MessageBodyMember(Namespace = "Some namespace"), XmlElement]
The end result:
public class GetInfo
{
public string IdNumber {get; set;}
[MessageBodyMember(Namespace = "Some namespace"), XmlElement]
public PersonData[] PersondataList {get; set;}
}
I am building a client to some STS service and for more than one day now I am trying to add a Header to a WCF message. In my call to RequestSecurityToken I have to include a UsernameToken.
I'm not sure how to accomplish that. For the moment I defined an endpoint behavior and a message inspector (took me long enough to discover those...). In the BeforeSendRequest() of the latter I create an object of the custom class 'Security' which derives from MessageHeader. Security includes an instance of UsernameToken.
public class MessageInspector : IClientMessageInspector {
public object BeforeSendRequest(ref Message request, IClientChannel channel) {
Security uns = new Security();
uns.UsernameToken = new UsernameToken();
// ...
var Header = new MessageHeader<Security>(uns);
var untyped = Header.GetUntypedHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
request.Headers.Add(untyped);
return null;
}
}
public class Security : MessageHeader {
public UsernameToken UsernameToken = new UsernameToken();
public override string Name {
get { return "Security"; }
}
public override string Namespace {
get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
}
}
public class UsernameToken {
public String Username = "";
public Password Password = new Password();
}
This is what is being serialised
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:RequestSecurityToken</Action>
<Security xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken xmlns="http://schemas.datacontract.org/2004/07/Tarifrechner.Kfz">
<Password>
<Type>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText</Type>
<password>******</password>
</Password>
<Username>******</Username>
</UsernameToken>
</Security>
</s:Header>
<s:Body />
</s:Envelope>
Especially the namespace of UsernameToken seems to be wrong. I know it comes from the data contract serialization but i need a different namespace.
This is what I would like the serialised data to look like
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="...">
<soap:Header>
<Security xmlns:q1="http://www.bipro.net/namespace" xsi:type="q1:UserNameSecurity"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>******</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">******</Password>
</UsernameToken>
</Security>
<wsa:Action>urn:RequestSecurityToken</wsa:Action>
<wsse:Security>
<wsu:Timestamp wsu:Id="Timestamp-b9dd599d-5901-451d-8321-6a309091f273">
<wsu:Created>2012-03-11T16:02:56Z</wsu:Created>
<wsu:Expires>2012-03-11T16:07:56Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
<soap:Body>
<RequestSecurityToken xmlns="http://schemas.xmlsoap.org/ws/2005/02/trust">
<TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</TokenType>
<RequestType>
http://schemas.xmlsoap.org/ws/2005/02/trust/Issue
</RequestType>
</RequestSecurityToken>
</soap:Body>
</soap:Envelope>
Is my approach about right? And how can I manipulate things like the namespace of a header detail or whether data is being serialised as attribute or element?
Update
As Ladislav already noted, I don't have to implement classes like UsernameToken myself. I did that only because my knowledge of WCF is so limited.
By now, I discovered, that WS2007HttpBinding, configured to use SecurityMode.TransportWithMessageCredential and with EstablishSecurityContext set to false produces almost the XML I am looking for. How should I have known that?
But there's one problem left: My request has an empty body element, where the request I want to produce, features a RequestSecurityToken element inside the body element. Does anyone know, how I can achieve that?
Using EstablishSecurityContext = true helps but at the same time changes my Soap-Action from the desired "urn:RequestSecurityToken" into the non-working "http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/SCT".
I appreciate any answer!
Thanks a lot!
Björn
One alternative way is to define a MessageContract type for your request, which allows you to define what shows up in the header and body of the SOAP message and adjust the namespace used. For example, consider the following service definition:
[ServiceContract]
public interface IMyService
{
[OperationContract]
MyResponse DoSomething(MyRequest request);
}
public class MyService : IMyService
{
public MyResponse DoSomething(MyRequest request)
{
return new MyResponse()
{
Details = "Service did something awesome.",
Timestamp = DateTime.Now
};
}
}
[MessageContract(IsWrapped = true, WrapperNamespace = "http://myservice/messages/")]
public class MyRequest
{
[MessageHeader(Namespace = "http://myservice/security")]
public string TokenThingy
{
get;
set;
}
}
[MessageContract(IsWrapped = true, WrapperNamespace = "http://myservice/messages")]
public class MyResponse
{
[MessageBodyMember]
public string Details
{
get;
set;
}
[MessageBodyMember]
public DateTime Timestamp
{
get;
set;
}
}
Sending a request produces the following SOAP:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IMyService/DoSomething</Action>
<h:TokenThingy xmlns:h="http://myservice/security">fda</h:TokenThingy>
</s:Header>
<s:Body>
<MyRequest xmlns="http://myservice/messages/" />
</s:Body>
</s:Envelope>
And a response from the service looks like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<MyResponse xmlns="http://myservice/messages">
<Details xmlns="http://tempuri.org/">Service did something awesome.</Details>
<Timestamp xmlns="http://tempuri.org/">2012-05-04T17:04:36.5980424-04:00</Timestamp>
</MyResponse>
</s:Body>
</s:Envelope>
There are a few different ways to add headers to a message depending on how you need to control the header content and where you need to insert the header.
In your application code you can create an OperationContextScope around the request in order to change some of the request properties. Inside an OperationContextScope, you have a valid instance of OperationContext.Current, which allows manipulation of the message headers through the OutgoingMessageHeaders collection. Use of this method deeply bakes control of the headers into the application code. You would have to be responsible for copying the appropriate code wherever it was needed.
These two links (from someone on the WCF team) talk about this in greater detail with a ton of code samples: