Get XML of Request and Response to a web service - c#

In c# using Asp.net, I am trying to get the XML format of the request and response I am making to a web service. I used one of the solution from this site but it is incomplete in my situation. I am able to serialize the response but I cannot do the same for the request since I am sending in multiple parameters as request and I cannot completely figure this out.
Example :
RefreshInfo info = refreshclient.getRefreshResponse(refreshcontext, itemID);
I added the below code for response and I could see the XML format of it.
XmlSerializer xmlSerializer = new XmlSerializer(info.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, info );
string repsonsexml = textWriter.ToString();
}
How can I do the same for the request from this?
Help is appreciated.. Thank you!!

I think the answer is right here. Posted too early, I suppose!
Generating XML from multiple classes?

Related

How to read Json data from Instagram RealTime API updates

I'm trying to use Instagram RealTime API to get updates whenever someone posts an image with an specific tag, I've followed all the steps, but I'm having problems to read the json data that is sent to my callback url. According to instagram's documentation :
When someone posts a new photo and it triggers an update of one of
your subscriptions, we make a POST request to the callback URL that
you defined in the subscription. The post body contains a raw text
JSON body with update objects.
I'm using C# and MVC 5, here's my code to read the "raw text JSON body", note that I'm saving the json string in a text file.
[HttpPost]
public HttpStatusCodeResult Receive()
{
string json;
using (var reader = new StreamReader(Request.InputStream))
{
json = reader.ReadToEnd();
}
File.WriteAllText(Path.Combine(Server.MapPath("~/"), "test.txt"), json);
return new HttpStatusCodeResult(200);
}
The problem is, when I receive the request, the file is create, but is always empty. There's something wrong with my code? Could it be some problem with Instagram's API? I'd appreciate some help with this.
Found it! Just set InputStream position to zero and it works!

Reading XML content from Body of WebAPI call is cut off at beginning

I'm creating a sort of proxy service that needs to process calls containing XML from the body of a POST to my WebAPI service and then POST it on to another service.
The odd thing is when I receive the XML message from the POST the 1st part of the XML from the body is cut off. Initially I thought maybe buffer size, or message was too big so I cut out a lot of the XML test message being sent reducing what was being sent. However the XML is still cut off in the same place.
I've tried the following (2) methods to read the XML BODY in the WebAPI service and the result is the same:
var reader = new StreamReader(Request.Content.ReadAsStreamAsync().Result);
string originalMessage = reader.ReadToEnd();
and:
var result = "";
Request.Content.ReadAsStreamAsync().ContinueWith(x =>
{
using (var sr = new StreamReader(x.Result))
{
result = sr.ReadToEnd();
}
});
Here is a snippet the original XML:
<Message version="123" release="001" xmlns="http://www.mysite.com/schema">
<Header>
<To Att1="A">001</To>
<From Att2="B">002</From>
<ID>9876</ID>
Here is the beginning of the content after reading it in the WebAPI controller POST:
</To>
<From Att2="B">002</From>
<ID>9876</ID>
See how it starts at the 'closing' tag of the <To> element? That's obviously not the beginning of the XML that it was sent.
The even more peculiar thing is the 'Content Size' when inspected before it is sent and after is 4188 on both sides. Something else interesting is that I have an old fashion .asmx tester (as opposed to a Web API service) that does the identical thing. When I read the incoming XML message in that app using the following:
// Get raw request body
Stream receiveStream = HttpContext.Current.Request.InputStream;
// Move to beginning of input stream and read
receiveStream.Position = 0;
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
// Load into XML document
xmlSoapRequest.Load(readStream);
}
...I see the full XML message. So not sure why the .asmx can read it but not the WebAPI service fully.
What am I doing wrong in my WebAPI POST call to where I can't see the full XML message that was sent in the body of the request?
Well I figured out the issue, but not 100% sure on the reason. The parameter I was using for the POST was the one right out of the box:
public HttpResponseMessage Post([FromBody]string value)
I changed it to take the request as a parameter on the POST instead:
public HttpResponseMessage Post(HttpRequestMessage request)
When I did the 2nd option above, I began to get the entire XML body from the request as expected.

.Net - Consuming webservice without WSDL

We have a new accounting system that provides webservice interface to external clients. I want to access one of the interfaces but there's no WSDL so i created the request through the use of HttpWebRequest and it works fine.
However to ease the creation of the requests and parsing of the response i would like to create some kind of automapping function. I have the request and response structure in an XSD file. Any ideas?
Request creation:
public void SendRequest()
{
HttpWebRequest request = CreateWebRequest();
XmlDocument soapEnvelopeXml = new XmlDocument();
soapEnvelopeXml.LoadXml(#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
++ structure type inserted here ++
</soap:Body>
</soap:Envelope>");
using (Stream stream = request.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
}
Well, if you really have no way of getting hold of a proper WSDL file but have XSD:s you could probably use the xsd.exe tool to create classes that map to your request and response types.
Something like this (run this in a Visual Studio Command Prompt)
xsd.exe TheRequest.xsd /c /n:Your.Namespace
xsd.exe TheResponse.xsd /c /n:Your.Namespace
But really, try your best to find that WSDL, it will make your life a lot easier..
I recommend that you Create a WSDL - reverse engineer it, and then produce your webservices client stubs from it.
The way to do it:
Get a wire trace of the exact request and response the webservice uses. Use Fiddler or something similar.
Build a WCF service, that approximates the request and response.
Get the trace of that
Compare (3) to (1). Remember you want XML infoset equivalence. Your namespace prefixes need not be the same, for example. Your namespaces need not be declared in the same location. But, the element names need to be exactly the same, and the xmlns strings need to be exactly the same. Modify the WCF service to more closely match the original. Restart it, go to step 3. Iterate as many times as it takes.
point your WCF client to the real web service
sit back and relax.
I've done this and it works. It can be tricky if you don't have insight into how DataContract attributes affect the XML on the wire. But as you play with it, you will gain the insight pretty quickly.
But how is it possible that it is a SOAP service and there is no WSDL on the service side? It might save you a ton of work to re-double your efforts to locate the real WSDL.

How to modify webservice proxy to get Raw XML

Here's the proxy method that was created for the web service I'm trying to access. How would I go about modifying it to get the raw XML from the web service call?
/// <remarks/>
[System.Web.Services.Protocols.SoapHeaderAttribute("CallOptionsValue")]
[System.Web.Services.Protocols.SoapHeaderAttribute("MruHeaderValue")]
[System.Web.Services.Protocols.SoapHeaderAttribute("SessionHeaderValue")]
[System.Web.Services.Protocols.SoapHeaderAttribute("QueryOptionsValue")]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace = "urn:partner.soap.sforce.com", ResponseNamespace = "urn:partner.soap.sforce.com", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("result")]
public QueryResult query(string queryString)
{
object[] results = this.Invoke("query", new object[] {
queryString});
return ((QueryResult)(results[0]));
}
Thanks for your help!
Fortunately there is a nice way to do it, just modify the generated proxy class so it inherits from different base. The alternative implementation comes from Web Services Enhancements 3.0 pack:
Microsoft.Web.Services3.WebServicesClientProtocol
in the class you'll have RequestSoapContext.Envelope.InnerXml and ResponseSoapContext.Envelope.InnerXml in the scope - that's exactly what you need.
If you want just make a dump using the Fiddler Web Debugging tools.
If you want to really retrive/process raw XML then proxy method will not help you. Create System.Net.HttpWebRequest for the web service, call it, and retrive pure XML response. Format/structure can be found at .ASPX page or web service documentation.
Well, as far as I remember, a buddy of mine that this once with regular ASMX webservices, and it was quite a hack....
How about just serializing the result you get back into XML? That might do the trick...
Something along the lines of (totally untested and from memory):
MemoryStream stm = new MemoryStream();
XmlSerializer xmlSer = new XmlSerializer(typeof(QueryResult));
xmlSer.Serialize(stm, queryResult);
Would that work?
Marc

Query Web Service for list of Messages?

Is there a straightforward way to query a web service to see which messages it supports? The C# .NET application I'm working on needs to be able to handle an older version of the web service, which does not implement the message I'm trying to send. The web service does not expose a version number, so Plan B is to see if the message is defined.
I'm assuming I can just make an HTTP request for the WSDL and parse it, but before I go down that path, I want to make sure there's not a simpler approach.
Update:
I've decided to get the WSDL and get messages directly. Here's the rough draft for getting all the messages:
HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create( "http://your/web/service/here.asmx?WSDL" );
webRequest.PreAuthenticate = // details elided
webRequest.Credentials = // details elided
webRequest.Timeout = // details elided
HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse();
XPathDocument xpathDocument = new XPathDocument( webResponse.GetResponseStream() );
XPathNavigator xpathNavigator = xpathDocument.CreateNavigator();
XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager( new NameTable() );
xmlNamespaceManager.AddNamespace( "wsdl", "http://schemas.xmlsoap.org/wsdl/" );
foreach( XPathNavigator node in xpathNavigator.Select( "//wsdl:message/#name", xmlNamespaceManager ) )
{
string messageName = node.Value;
}
Parsing the WSDL is probably the simplest way to do this. Using WCF, it's also possible to download the WSDL at runtime, essentially run svcutil on it through code, and end up with a dynamically generated proxy that you can check the structure of. See https://learn.microsoft.com/en-us/archive/blogs/vipulmodi/dynamic-programming-with-wcf for an example of a runtime-generated proxy.
I'm pretty sure WSDL is the way to do this.

Categories

Resources