how to remove <optional> from Soap request - wcf

I am using SoapUI Pro 4.6.1 for testing my WCF service.
And my request look like this
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:doPaymentRequest>
<!--Optional:-->
<tem:credentials>
<!--Optional:-->
<tem:accountId>?</tem:accountId>
<!--Optional:-->
<tem:userName>?</tem:userName>
<!--Optional:-->
<tem:password>?</tem:password>
</tem:credentials>
</tem:doPaymentRequest>
How to remove --Optional:--> from SOAP
I am using message format to wrap my data contract and i am using isRequired attribute for DataContract.

Do you want to remove any oprional element? Then File -> Preferences -> WSDL Settings -> Include Optional (this is a checkbox). When you add request to your test case it also suggests to select option "Create optional elements".

You need to specify [DataMember(IsRequired = true)] on all of the properties in the data contract class, then they won't be optional.

[DataContract]
public class GetColorsRS
{
DataMember(Name = "Errors", Order = 1, IsRequired=false)]
public List<Error> Errors { get; set; }
}

Related

How can I attach BinarySecurityToken in request header(.net core)

I want to create something like below
<soapenv:Header>
<wsse:Security>
<wsse:BinarySecurityToken EncodingType="XXXX" ValueType="XXX">Token
</wsse:BinarySecurityToken>
</wsse:Security>
</soapenv:Header>
I manage to acheive this by using the below code, which is working (well Kind of!)
using (new OperationContextScope(experianProxy.InnerChannel))
{
DataContractJsonSerializer serializer =new
DataContractJsonSerializer(typeof(BinarySecurityToken));
MessageHeader header = MessageHeader.CreateHeader("wsse:Security", "",
_token,serializer);
OperationContext.Current.OutgoingMessageHeaders.Add(header);
var interactiveResponse = experianProxy.InteractiveAsync(new Root()).Result;
return interactiveResponse.OutputRoot.ToString();
}
and
[XmlRoot(ElementName = "wsse:BinarySecurityToken", Namespace = "")]
public sealed class BinarySecurityToken : IXmlSerializable
{...}
Now the request going out is,
<soapenv:Header>
<wsse:Security><wsse_x003A_BinarySecurityToken ValueType="xxxx"
EncodingType="wsse:Base64Binary"
>XXXXXXXXXXX</wsse_x003A_BinarySecurityToken>
</wsse:Security>
</soapenv:Header>
Converting cdata didn't help.
Can someone please point out what am I missing? Any help is much appreciated.
Thank you.
The scope of OperationContextScope is only valid within the using statement. after the instance of OperationContextScope is released, the OperationContext is restored and the message header is no longer valid. if you try to call the method in the using statement, you will find your custome header.
You can use the IClientMessageInspector interface if you want to permanently add message headers to requests.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/f1f29779-0121-4499-a2bc-63ffe8025b21/wcf-security-soap-header

Apache cxf jax-rs implementation with xml databind

I configured my rest service to implement content negotiation through Variant.
On jersey all works fine but on apache cxf something goes wrong.
No message body writer has been found for class ContentType: application/xml
It seems thath when I construct the response as xml type it cannnot find the correct body writer.
I configured jax-rs with jacksonJaxbJsonProvider and all works great with json databind.
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider" />
</jaxrs:providers>
cxf-rt-frontend-jaxrs version 3.0.3
jackson-databind: 2.4.2
Any idea?
Add a #XmlRootElement(name="order") generated xml cannot be <orderId>data<orderId>, it should have root element. Thus updated code would look like
#XmlRootElement(name="order")
#XmlType(propOrder = { "orderId"})
public class OrderForConfirmationEmail implements Serializable {
#XmlElement
public long getOrderId() {
long orderId = new Random().nextLong();
return orderId;
}
}
Generated xml is
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><order xmlns="http://com.kp.swasthik/so/schema">
<orderId>369317779145370211</orderId>
</order>
and json is
{"orderId":6812414735706519327}

Accidentally sticking SOAP Body inside of SOAP Header attempting to access WSE service with WCF client

I am attempting to hit a WSE secured web service using WCF. The SOAP header I need to generate to do this should contain a username, password, nonce, and created date... Here is a an example of a soap UI header that I use to hit the same service...
<soap:Header>
<wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-2" 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">Hozef94FFwOhuiF5QixaMQ==</wsse:Nonce>
<wsu:Created>2012-08-21T13:26:03.642Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
Now I found a tutorial that was pretty usefull. usefull tutorial
I have successfully implemented it... But I am now sticking the SOAP body into the soap header and there isn't a nonce generated.
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPo9VZylDHg5JMgjsNnWLhATkAAAAA+YtOxHdh0Uqd4a64raX/nIzYz20mPHlBv4Wk5S8d5PsACQAA</VsDebuggerCausalityData>
<wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<Username>------------</Username>
<Password>************</Password>
</UsernameToken>
</wsse:Security>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetOrganizations xmlns="http://------------------------/businessobjects/messaging/">
<personId xmlns="">0</personId>
<typeId xmlns="">
<int>1</int>
<int>2</int>
<int>3</int>
<int>4</int>
</typeId>
</GetOrganizations>
</s:Body>
</s:Header>
</s:Envelope>
Don't know why it is doing this. I followed the tutorial to the letter. My Repository getting everything...
using (DistListServiceReference.DistributionListClient dlc = new DistListServiceReference.DistributionListClient())
{
try
{
PasswordDigestBehavior behavior = new PasswordDigestBehavior("********", "********");
dlc.Endpoint.Behaviors.Add(behavior);
GetDistributionLists gdl = new GetDistributionLists();
gdl.PersonID = 0;
GetDistributionListsResponse gdlr = new GetDistributionListsResponse();
gdlr = dlc.GetDistributionLists(gdl);
return gdlr;
}
catch (Exception e)
{
dlc.Abort();
return null;
}
}
My PasswordDigentInspector
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
// Use the WSE 3.0 security token class
UsernameToken token = new UsernameToken(this.Username, this.Password, PasswordOption.SendPlainText);
WseHeader header = new WseHeader(this.Username, this.Password);
// Serialize the token to XML
XmlElement securityToken = token.GetXml(new XmlDocument());
MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken", securityToken, false);
request.Headers.Add(header);
// complete
return Convert.DBNull;
}
How I apply client behavior
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new PasswordDigestMessageInspector(this.Username, this.Password));
}
Everything is pretty much there. I am not seing where the body is being injected into the header. Any body have any ideas?
UPDATE: Debugging
I am looking at the the actual header that I inject into the soap message and this is what I see...
{<wsse:Security s:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<Username>**********</Username>
<Password>************</Password>
</UsernameToken>} System.ServiceModel.Channels.MessageHeaderInfo {TestDistListApplication.Repository.WseHeader}
Just looking at that, there is no nonce, I could build it programmatically, but I am not sure if that is a good idea. Especially since there is a nonce already and a create date in the securityToken... Not sure why they don't appear in the header though...
<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">MedTrak_Dev</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">uncJUN132012</wsse:Password>
<wsse:Nonce xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">mvy9nUfF+rnT3oTasDBqxg==</wsse:Nonce>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2012-08-28T13:30:42Z</wsu:Created>
I have the debugger stopped and I am watching both those variables. What might cause the header not to have those things and the the WSEHeader to have them?
Looks like I will have to debugg that.
Without running your code myself it is a little tricky to understand why my example doesn't work in your scenario. However, in a attempt to debug this I would try the following:
Stick a breakpoint on this line:
XmlElement securityToken = token.GetXml(new XmlDocument());
And after stepping through this line, see what the securityToken XML looks like. It is this XML which is being injected into the security header. It isn't any more complicated than that. You coudl create this XML manually if you want. I used the WSE 3.0 classes because I didn't want to hand code the XML myself.
I also notice that your security token definition looks slightly different to mine. My example was:
MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityToken, false);
Yours:
MessageHeader securityHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken", securityToken, false);
The namespaces are different. Any reason for this?
If the breakpoint added from the step above isn't hit then it would suggest that the behavior isn't actually being applied. In which case, you'll probably need to double check your configs to make sure that the behavior is correctly applied on the client. Alternatively (as my example shows) you can programatically add the custom behavior before sending the message.
I recommend to anyone dealing with WCF issues, that they first turn on verbose logging and also use fiddler to see what is actually going over the wire.

WCF Service with non .net present client

Instead of creating a WCF service and a client by generated code of WSDL, I must create a WCF service with a given SOAP request.
To help you better understand, I copied the main part of the SOAP request here:
<?xml version="1.0" encoding="windows-1252"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<HeaderContent xmlns="CustomerNamespace.com">
<CallerId>6274</CompanyId>
<Login>mylogin</Username>
<Password>mypassword</Password>
<ResponsibilityType>3</Responsibility>
<ResponsibilityId>189281728</ResponsibilityId>
</HeaderContent>
</soap:Header>
<soap:Body>
<UpdateNutritionalValues xmlns="CustomerNamespace.com">
<NutritionalValues>
<Product id="195739241">
<Created>2011-11-01</Created>
<Owner>8633</Owner>
.
.
.
So, my service will receive this SOAP request. The embedded NutritionalValues XML is very long and I cannot change anything at the soap request at all because our customer use this request for many other companies as well.
And this is my problem.
How do I map the XML NutritionalValues content to my "DataContract"?
How do I access the Header to authenticate the caller?
When I debug my Service with a handcrafted generated SOAP request with Fiddler I receive a null parameter value
[ServiceContract(Namespace="CustomerNamespace.com")]
public interface IWCFService
{
[OperationContract]
ComplexType UpdateNutritionalValues(NutritionalValues nutVal);
}
[DataContract]
public class NutritionalValues
{
[DataMember(Name="Product")]
public ProductSpecification Product { get; set; }
}
[DataContract]
public class ProductSpecification
{
[DataMember(Name="Created")]
public DateTime Created { get; set; }
[DataMember(Name="Owner")]
public int Owner { get; set; }
}
( I can deserialize the XML manually too ) but i dont know how to access the ( raw? ) XML.
I would be very thankful for any help !

WCF MesageContract - customizing outgoing SOAP message - multiple bodies

I have to call a Web service that is extremely demanding (unstandard) regarding the SOAP message format that it chooses to process. I have no control over the server side implementation and there is no WSDL available, all I have is an intercepted message attached bellow.
My first thought was WCF+MessageContract, but whatever I do with the last, I can't seem to get the right result. Outgoing messages should look like the one bellow. The most tricky part seems to be multiple body contents ("ProxyInfo" and "PayloadInfo" bellow). Besides that I also can not get WCF to remove "Action" element from SOAP message header. I realize that it is a vital element to WCF, but I doubt that I could persuade Web service to accept it. The reply will probably be another story, but I will cross that bridge when I get to it.
Currently I am considering custom serialization and post-/pre- processing of outgoing/incoming messages. In the worst case I guess I will have to do Web requests as well as serialization manually. Please help, I am getting realy desperate...
<?xml version="1.0" encoding="UTF-8" ?>
<e:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<e:Header>
<ServiceHeader xmlns="http://services/serviceheader" e:actor="http://services/loadbalancer" >
<ServiceLevel>
<Type>HIGH</Type>
<Method>FIFO</Method>
</ServiceLevel>
</ServiceHeader>
</e:Header>
<e:Body>
<ProxyInfo xmlns="http://services/proxyinfo">
<Server>
<Address>proxy1:8080</Address>
<AppId>case_delegator</AppId>
</Server>
</ProxyInfo>
<PayloadInfo xmlns="http://services/payload">
<GetConfirmation>
<CaseId>
<Id>9728DFC889874CC8B1505D91E33FCFCD</Id>
</CaseId>
</GetConfirmation>
</PayloadInfo>
</e:Body>
</e:Envelope>
If you don't want to use Address header you have to use binding without WS-Addressing. In your case use BasicHttpBinding. It will not use WS-Addressing and Action SOAP header but instead it will use SOAPAction HTTP header.
For your message contract try to use something like this:
[DataContract]
public class ServiceHeader
{
...
}
[DataContract]
public class ProxyInfo
{
...
}
[DataContract]
public class PayloadInfo
{
...
}
[MessageContract(IsWrapped = false)]
public class Request
{
[MessageHeader(Namespace="http://services/serviceheader")]
public ServiceHeader ServiceHeader { get; set; }
[MessageBodyMember(Namespace="http://services/proxyinfo")]
public ProxyInfo ProxyInfo { get; set; }
[MessageBodyMember(Namespace="http://services/payload")]
public PayloadInfo PayloadInfo { get; set; }
}
The strange thing is the actor attribute in ServiceHeader. Your message doesn't define namespace for prefix e so the message is not valid XML.