WCF Service with non .net present client - wcf

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 !

Related

Protect WCF from fiddler (MITM) (PCL XAMARIN FORMS)

I have xamarin forms project using portable class library.
In that PCL I reference my WCF service which is hosted in some server.
The wcf binding is Basichttpbinding with security transport as PCL does not support wshttpbinding.
Also the wcf is use https and i have a valid certificate for that.
I want to secure the messages because now if i install some kind of application fiddler or packed monitor in my android every call to my service i can see the xml data in readable format.
I thought by using https i was protecting that.
I try use wcf TransportWithMessageCredential but it failed to login to my service because xamarin does not yet support this combination
So: ( after research i found out that )
PCL does not support wshttpbinding only basicHttpBinding
Xamarin.Forms basicHttpBinding does not support message security but only
TransportCredentialOnly
And
Xamarin does not support TransportWithMessageCredential but only
transport security but transport security not protecting the data from MITM.
How others working with xamarin forms and protect these data?
Do i missed anything?
Any suggestions?
EDITED
I am trying to encrypt the xml request before send to service but fails every time i change the message e.g from xml to encoded characters (i guess because the server fails to recognize the schema )
I have implement IClientMessageInspector at the client Side as also IDispatchMessageInspector at the server side.
I need some help how i can send the xml request encrypted to the server.. if i do it here then i can decode it from service side ( server)
At the client side i have the following
Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
Dim Binding As New BasicHttpBinding(BasicHttpSecurityMode.Transport)
Dim ms As MemoryStream = New MemoryStream(System.Text.Encoding.UTF8.GetBytes(EncryptedData(request.ToString)))
Dim RQuotas As Xml.XmlDictionaryReaderQuotas = Binding.ReaderQuotas
Dim reader = Xml.XmlDictionaryReader.CreateTextReader(ms, RQuotas)
request = Message.CreateMessage(reader, Int32.MaxValue, request.Version)
Return Nothing
End Function
I am not sure if i do it correctly. Any help welcome.
Fiddler only decrypts Https Traffic if you accept its certificate, it basically acts a man in the middle and handles all the calls from the service to your app, there is some useful info here https://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/DecryptHTTPS ,
On your second update of the question, you would need to create a container that will house all your messages,
that way you can decrypt and encrypt the data as you see fit,
A simple example can be found at https://misaxionsoftware.wordpress.com/2011/07/29/secure-restful-web-service-by-wcf-web-api-no-https-seriously/
You can customise it as much as possible
Here is the message that is defined in the link above
Message
public class Message
{
public string AppId { get; set; }
public string Data { get; set; }
public string Id { get; set; }
public string TimeStamp { get; set; }
public byte[] GenerateFingerprint();
public bool ValidateHash(byte[] fingerprint);
}
Encrypted Message
public class EncryptedMessage
{
public string AppId { get; set; }
public byte[] Fingerprint { get; set; }
///<summary>
/// The 3DES key used to encrypt/decrypt the message
/// </summary>
public byte[] Key { get; set; }
///<summary>
/// Encrypted message
/// </summary>
public byte[] Message { get; set; }
}
IEncryptionHelper
public interface IEncryptionHelper
{
EncryptedMessage Encrypt(Message message);
Message Decrypt(EncryptedMessage encryptedMessage);
}

how to remove <optional> from Soap request

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; }
}

NServiceBus allows control over deserialization?

I am trying to integrate a legacy application with NServiceBus by wrapping XML exports from the application with a NServiceBus "wrapper" which basically strips out namespaces and adds the envelope and NSB namespace.
I have the basic solution working but only if the root element of the XML export exactly matches the NServiceBus message type name.
For example if the xml is:
<?xml version="1.0"?>
<Messages xmlns="http://tempuri.net/MyMessagesNamespace">
<!-- Note: the "V1" -->
<PolicyEndorsedV1>
...
</PolicyEndorsedV1>
</Messages>
then my handler code can happily deserialize:
namespace MyMessagesNamespace
{
public class PolicyEndorsedV1Handler : IHandleMessages<PolicyEndorsedV1>
{
public void Handle(PolicyEndorsedV1 message)
{
// All work fine!
...
}
}
}
However, if the export XML is
<?xml version="1.0"?>
<Messages xmlns="http://tempuri.net/MyMessagesNamespace">
<!-- Note: the "V1" has been removed -->
<PolicyEndorsed>
...
</PolicyEndorsed>
</Messages>
this will not be deserialised. NServiceBus tells me System.TypeLoadException: Could not handle type 'Beazley.Messages.Risks.Events.PolicyEndorsed', which is understandable as the only information it's got to go on is the name of the root node on the incoming xml.
I have tried to control the deserialization behaviour by adding some of the .Net Serialization attributes to my message definition:
[XmlRoot(ElementName = "PolicyEndorsed", Namespace = "", IsNullable = false)]
public partial class PolicyEndorsedV1
{
...
}
but this is ignored because NServiceBus uses it's own serializer (called XmlMessageSerializer) and not .Net's own XmlSerializer.
So does anyone know how I can do this? I think it would be nice to have the option to decouple the Xml names with their NSB messaging counterparts.
Many thanks
Does PolicyEndorsedV1 inherit from PolicyEndorsed?
If so, use IHandleMessages<PolicyEndorsed>, and PolicyEndorsedV1Handler will handle both types of objects.
For example:
public class PolicyEndorsedV1Handler : IHandleMessages<PolicyEndorsed>
{
public void Handle(PolicyEndorsed message)
{
// Handles both PolicyEndorsed and PolicyEndorsedV1 messages
}
}

View SOAP message body generated by WCF

How to view SOAP message to check the IsWrapped in MessageContract attribute, as the example below:
[MessageContract]
public class HelloGreetingMessage
{
private string localGreeting;
[MessageBodyMember(
Name = "Salutations",
Namespace = "http://www.examples.com"
)]
public string Greeting
{
get { return localGreeting; }
set { localGreeting = value; }
}
}
How to view this:
/*
The following is the request message, edited for clarity.
<s:Envelope>
<s:Header>
<!-- Note: Some header content has been removed for clarity.
<a:Action>http://GreetingMessage/Action</a:Action>
<a:To s:mustUnderstand="1"></a:To>
</s:Header>
<s:Body u:Id="_0" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<HelloGreetingMessage xmlns="Microsoft.WCF.Documentation">
<Salutations xmlns="http://www.examples.com">Hello.</Salutations>
</HelloGreetingMessage>
</s:Body>
</s:Envelope>
*/
You can use tools like Fiddler or FireShark to inspect your request and response. You can also debug Https traffic.

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.