Send full XML document back to calling application Via WCF with SOAP - c#

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;

Related

I have a WSDL, how do I create (BUT NOT SEND) the SOAP for a request?

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.

.net Client consuming Axis2 Web Service

I have an .net 2.0 C# client app that has a web service reference to an Axis2 Java Webservice.
The idea is to send some xml data to the webservice, so it can be parsed and inserted into database.
The WS method accepts a single parameter of type 'xsd:anytype'.
Java web service:
public class JWS{
public Response AddData(Object inputXML) {
return Response;
}
}
C# Client:
JWS client = new JWS();
object inputXML = "<xml>some xml data</xml>";
response = client.AddData(inputXML);
There are 2 issues i am seeing when monitored using fiddler.
1) The request has an additional element '<inputXML>' added before the actual xml data.
<inputXML><xml>some xml data</xml></inputXML>
2) The xml is encoded, so '<' is appearing as "<"
I am not sure if this is how SOAP request's are generated but i would like to remove the <inputXML> tag and also, have the xml appear as is without having to replace the special characters.
Is this possible? Is it got something to do with 'Wrapping'/'UnWrapping' Types?
Also, i have used SoapUI to test the java web service and it works well. However, in the request tab, i had to manually remove the <inputXML> tag and submit for it to work correctly. Please help.
TIA
This is expected behaviour under SOAP and the inputXml variable will be decoded back to the original string when passed to your web service method.
However this may indicate a problem with your design, have you considered constructing an object to send to your web service rather than xml data? (As this object will transparently be converted to xml for the web service call anyway).
I found out that the issue is not with encoding but it was interpreted incorrectly on java side when the message was viewed in axis2. So, it is getting decoded properly. Also, the inputxml is now being handled correctly.

SoapHttpClientProtocol: get response as a stream instead of a string?

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

Does WCF automatically URL encode/decode streams?

I'm programming a service for a program that uses HTTP post/get requests, so I handle all incoming requests with a hook method that takes a System.IO.Stream and returns a System.IO.Stream.
When I parse the incoming request (contained in an HTML form) by converting to a string and then using System.Web.HttpUtility.ParseQueryString(string), it seems to automatically URL-decode the data. When I return a file path (a Windows UNC, not going to explain why I do that), I initially URL-encoded the string before converting to a stream and returning it using a return-statement, the client seems to get a doubly-coded string.
So, just to be sure, does WCF automatically URL encode/decode streams for me as part of using System.ServiceModel.WebHttpBinding?
Apparently, it does:
"For RESTful services, WCF provides a binding named System.ServiceModel.WebHttpBinding.
This binding includes pieces that know how to read and write information using the HTTP and HTTPS transports, as well as encode messages suitable for use with HTTP."
from here.

WCF: Use JSON to encode a SOAP Message Body

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

Categories