WCF MesageContract - customizing outgoing SOAP message - multiple bodies - wcf

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.

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

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

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: how to choose which type an interface will be serialize into?

When using WCF,
how can you choose which type an interface will be serialized into?
for example, the CarA type is used in the server, and they are sent to client over WCF as ICars, and the client should receive them as CarBs.
public interface ICar
{
int Size { get; set; }
int Price { get; set; }
}
public class CarA : ICar
{
//ICar implementations...
}
public class CarB : ICar
{
//ICar implementations...
}
[ServiceContract]
public interface ICarManager
{
[OperationContract]
ICar GetMyCar(int userID);
}
"which type an interface will be serialized into" - this makes zero sense. If you send CarA's to your client the client will receive CarA's.
I think you may be asking about how to tell WCF that your service contract contains types which are derived from another type. To do this you can use ServiceKnownTypeAttribute.
UPDATE
If you want to return a type of ICar in your service operation you need to specify the concrete types which will be available on your endpoint. You do this by using the ServiceKnownTypeAttribute like so:
[ServiceKnownType(typeof(CarA))]
[ServiceKnownType(typeof(CarB))]
[ServiceContract]
public interface ICarManager
{
[OperationContract]
ICar GetMyCar(int userID);
}
You could look at customize reply message by implement custom extension using IDispatchMessageFormatter
try this link if help you
IDispatchMessageFormatter – How to customize reply Messages on the server side
From Your server side you can only expose unique endpoint so you will expose only one endpoint as ICar and then you will choose which implementation of ICar you want to host via ServiceHost ,it can be CarA or CarB.
Now on client side you will just have a only interface as ICar and you should not be confused with which type should be serialized using your interface Icar. You will be only calling server side to get the service not the implementation.
More on ServiceHost
Use the ServiceHost class to configure and expose a service for use by
client applications when you are not using Internet Information
Services (IIS) or Windows Activation Services (WAS) to expose a
service. Both IIS and WAS interact with a ServiceHost object on your
behalf

RESTful framework alternatives to WCF

Looking for alternatives to the WCF REST start kit, ideally OSS frameworks.
Anyone got a list?
Cheers
Ollie
OpenRASTA is the most mature
ASP.NET MVC is a good alternative when it comes to generating REST XML and JSON feeds.
To build a rest architecture in .net you can use GenericHandlers. You can create a GenericHandler that will receive a HTTP message (POST, GET or..) and return a message of the content-type you specify.
For example I create a generic handler on the url:
http://site/getpeople.ashx?gender=female
And call it with the parmeter gender=female, as above the handler will return the following
<people>
<person>...</person>
...
<people>
And the content type would be text/xml.
This is the simplest way to implement REST web services in .NET
I also provide ServiceStack, a modern, code-first, DTO-driven, WCF replacement web services framework encouraging code and remote best-practices for creating DRY, high-perfomance, scalable REST web services.
There's no XML config, or code-gen and your one clean C# web service is enabled on all JSON, XML, SOAP, JSV, CSV, HTML endpoints out-of-the-box, automatically. It includes generic sync/async service clients providing a fast, typed, client/server communication gateway end-to-end.
It also includes generic sync/async service clients providing a fast, typed, client/server communication gateway end-to-end.
This is the complete example of all the code needed to create a simple web service, that is automatically without any config, registered and made available on all the web data formats on pre-defined and custom REST-ful routes:
public class Hello {
public string Name { get; set; }
}
public class HelloResponse {
public string Result { get; set; }
}
public class HelloService : IService<Hello> {
public object Execute(Hello request) {
return new HelloResponse { Result = "Hello, " + request.Name };
}
}
Above service can be called (without any build-steps/code-gen) in C# with the line below:
var response = client.Send<HelloResponse>(new Hello { Name = "World!" });
Console.WriteLine(response.Result); // => Hello, World
And in jQuery with:
$.getJSON('hello/World!', function(r){
alert(r.Result);
});