We have SOAP implementations of our services and up till now we had some legacy code that was wrapping our args and returns in another object to get around some serialization / generics on RPC methods.
After optimization, we had implemented this class so that it Json serialized (DataContractJsonSerializer) and GZipped our complex request params and response objects.
I now want to push this stuff down into the WCF stack. What I really want is the ability to encode the message body as GZipped Json on a standard SOAP service. We need transactional support and security etc so we need to be able to support the standard bindings.
I have managed to implement an Operation Behavior to Json serialize so that the message infoset will contain json compatible XML. I then wanted to add a MessageEncoder to turn the xml into json in the message body. This is where I have issues. I can't serialize the whole message as we still have standard soap headers etc and the s:body still contains a root Request or Response object before the json compatible xml. I figure I can use the JsonReaderWriterFactory just not sure how to apply to the correc portion of the message.
I know I can do the GZIP later if I can just figure out reading and writing this Json section.
Any ideas?
Pete
OK. So some clarification.
My service looks like this
[ServiceContract]
public interface IMyService {
[OperationContract]
Person SavePerson(Person personToSave);
[OperationContract]
Person GetPersons();
}
and the output from the GetPersons() method would look something like this:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.petegoo.com/wcf/MyService/IMyService/GetPersonsResponse</a:Action>
<a:RelatesTo>urn:uuid:a18ccf1c-0793-4240-ba6f-9e86b6f2fdf6</a:RelatesTo>
</s:Header>
<s:Body>[{"DateOfBirth":"\/Date(286801200000+1300)\/","FirstName":"Foo","Id":1,"LastName":"Bar"},{"DateOfBirth":"\/Date(333720000000+1200)\/","FirstName":"Foo","Id":1,"LastName":"Bar"}]</s:Body>
</s:Envelope>
Note: The above was ad hoc so may not be syntactically or semantically correct.
My understanding is you like embed JSON into XML infoset in the SOAP?
It'd be easier to write some sample request and response that you want to achieve.
I don't see a good reason to coexist JSON infoset with XML infoset. However you can return JSON data as a string value of a XML element/attribute in the SOAP.
Ahh!! Just realise how old this is. Will leave here in-case it works for anyone else.
I'm fairly new to all this myself but, as a suggestion, have you tried looking into MessageInspectors? You can add these to the clientRuntime and dispatchRuntime to "play" with SOAP messages before and after they are sent by WCF.
By implementing IDispatchMessageInspector and / or IClientMessageInspector you could receive a call before the message is sent, read the current soap message xml, alter the content of the body element to contain your zipped content (perhaps adding it as a new child node) and then re-build the message and pass it back to WCF to send out. At the receiving end you grab the message again in AfterReceiveRequest and reverse the process.
Don't know if this will work for you but hope it helps. W
Related
My parent company has a WSDL, and I can create a ServiceModel, and use it to invoke web methods, and that's fine. However, what I need is to generate the SOAP XML without sending it. So, if I do this:
var mySvc = new MyWsdl.MyWebService();
var response = mySvc.DoTheThing(myUser, myData, myOtherData);
I know that under the covers, .NET is creating XML and sending it across the wire. But I need that XML without sending it, so, ideally, some code like:
var mySvc = new MyWsdl.MyWebService();
var xml = mySvc.GetSOAP("DoTheThing", myUser, myData, myOtherData);
Is there a way to do this? I am trying to get out of manually generating the XML.
The reason I'm doing this is because I need to actually send the SOAP to a different, normal non-SOAP web service. I suspect that that service is just going to turn around and call the SOAP service anyway, possibly massage the results, and return something to me, but that's out of my hands. Very soon I will not be able to use the ServiceClient directly.
Thanks!
EDIT: I would like to do this programatically. Otherwise, yes, I can get the XML by capturing a sent request, or using an app like SoapUI, but then I'm still manually creating the XML. The idea is, that if the WSDL changes, I don't want to have to change the XML I generate, so if the service client can do it for me, that would be ideal.
I have a WCF service that is being used to generate an XML file based on multiple different queries. In the end I am left with a complete XML file and I need a way of passing this back to the application that calls the method in my service. How can this be achieved using WCF?
I have tried a multitude of things such as sending back an XmlElement instead and populating that but when I do that the best I can do is pass back the root element and the contents inside that which isnt ideal as I lose the header which I need.
I tried this:
[OperationContract]
XmlElement Foo(MyType myType, string user);
string responseXMLString = getPointsResponse.ResponseHeader;
responseXMLString += getPointsResponse.ResponseRecords;
responseXMLString += getPointsResponse.ResponseFooter;
XmlDocument myDocument = new XmlDocument();
myDocument.LoadXml(responseXMLString);
return myDocument.DocumentElement;
This got me the whole document minus the header but I need the header. I want to send it all back as one object in XML format.
When I tried to send back an XML document I got a multitude of errors. When I also try to send it back as a string I get errors due to it having special chars and interfering with the SOAP response.
Any ideas?
Out of the box WCF's http-based bindings all use soap to wrap the message payload except webHttpBinding, which enables support for RESTful-style interfaces.
Alternatively you could be looking at is how to achieve POX messaging with WCF, which can be found here: http://msdn.microsoft.com/en-us/library/aa395208(v=vs.90).aspx
UPDATE
REST support in WCF has well established procedures for security. For example, http://www.codeproject.com/Articles/149738/Basic-Authentication-on-a-WCF-REST-Service
Additionally I would say that you should look at your service contract composition, ie the number and types of operations exposed on your endpoint. It may be that this problem you face is a good enough reason to decouple the POX operations from the SOAP operations into their own service endpoint.
You can get it in string format using the following.
return myDocument.DocumentType.ToString() + myDocument.DocumentElement;
I've built a simple C# app (.Net 4.0 + WPF) which can send and receive JSON messages via TCP sockets.
As a next step, it should be possible that JavaScript apps on websites and PHP scripts can send and receive JSON messages to/from my app. Is that possible?
Since JS/PHP will use stateless HTTP connections, how should a request to my app work, for example, should the JS/PHP apps send a JSON message to my app and my app response (HTTP response) with a JSON message? Is that even possible? And should I use GET or POST method to send the JSON messages to/from my app?
Hope my questions do not cause too much confusion ;-) I but I appreciate every tip, clarification or feedback you can give me.
Mike
You can accomplish this via a .NET web service using special JSON directives on the web method, e.g.
[ScriptMethod(UseHttpGet = true, ResponseFormat=ResponseFormat.Json)]
public string DoSomething(string param1, int param2)
{
// Do Something
}
When the ResponseFormat.Json property is specified, the data returned will be serialized into the appropriate JSON format. Also note, in order to recieve a true JSON response, you'll need to set your content-type to "application/json" from the requesting application. Otherwise, the method will attempt to wrap the response in XML.
Also, I am enabling a HttpGet on this method so that you can post via a query string to the method, e.g.
http://www.example.com/service.asmx?param1='Hello'¶m2=1;
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.
I'm using a webservice which spits out very large amounts of data in one piece. The response string can be something like 8MB. While not an issue on a desktop PC, an embedded device goes nuts dealing with an 8MB string object.
I wonder if there is a way to get the response as a stream? Currently I'm using the method like below. I tried using a POST request instead, but SOAP is just more convenient (the response is XML and with the POST I have to convert the plain text reply back to valid XML) and I'd like to stick with it. Is it possible to use a different kind of "Invoke" which won't return strings but streams? Any ideas?
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("MyAPI/MyMethod", RequestNamespace="MyAPI", ResponseNamespace="MyAPI", ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped, Use=System.Web.Services.Description.SoapBindingUse.Literal)]
public string MyMethod(string sID)
{
object[] results = this.Invoke("MyMethod", new object[] { sID });
return ((string)(results[0]));
}
If you use the old ASMX web service client infrastructure, then you're stuck with its limitations. One limitation is that there's no simple way to get the response except as deserialized data.
If it were necessary, then you could use a partial class to override the GetWebResponse method to return your own custom WebResponse. This latter would in turn override the GetResponseStream method to call the base version, consume the stream, then to return a stream containing an "empty" web request (otherwise .NET will choke on a stream with no contents).
You might also try something similar by overriding the GetReaderForMessage method. This is passed a SoapClientMessage instance which has a Stream property that you might be able to use. Again, you'll have to set the stream to something that the web service infrastructure can consume.
The better way to do this is with a WCF client. WCF has much more powerful and easy to use extensibility mechanisms.
In fact, you might not even need to extend a WCF client. You might simply be able to configure it to not have this buffering problem at all.
Any web service call is going to return SOAP, isn't it? I don't think a stream could be serialized into a soap packet to be returned from your service. And even if it could, wouldn't the serialized stream be at least as big as the string itself?
I believe the answer is no, there is no concept of a stream for SOAP.
Probably the simplest answer is to have your method:
Parse your response into segments your mobile device can handle
Cache your response in a application variable as a dictionary of these segments
return an arraylist of GUIDs.
You can then have your client request each of these segments separately via their GUIDs, then reassemble the original response when and handle it all the web services return.
ASMX can't do much about this. WCF's BasicHttpBinding can return a Stream to the caller.
http://msdn.microsoft.com/en-us/library/ms733742.aspx