Programmatically call webmethods in C# - c#

I'm trying to write a function that can call a webmethod from a webserive given the method's name and URL of the webservice. I've found some code on a blog that does this just fine except for one detail. It requires that the request XML be provided as well. The goal here is to get the request XML template from the webservice itself. I'm sure this is possible somehow because I can see both the request and response XML templates if I access a webservice's URL in my browser.
This is the code which calls the webmethod programmatically:
XmlDocument doc = new XmlDocument();
//this is the problem. I need to get this automatically
doc.Load("../../request.xml");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost/dummyws/dummyws.asmx?op=HelloWorld");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
Stream stm = req.GetRequestStream();
doc.Save(stm);
stm.Close();
WebResponse resp = req.GetResponse();
stm = resp.GetResponseStream();
StreamReader r = new StreamReader(stm);
Console.WriteLine(r.ReadToEnd());

Following on from the comments above. If you have a WSDL file that describes your service you use this as the information required to communicate with your web service.
Using a proxy class to communicate with your service proxy is an easy way to abstract yourself from the underlying plumbing of HTTP and XML.
There are ways of doing this at run-time - essentially generating the code that Visual Studio generates when you add a web service reference to your project.
I've used a solution that was based on: this newsgroup question, but there are also other examples out there.

FYI, your code is missing using blocks. It should be more like this:
XmlDocument doc = new XmlDocument();
//this is the problem. I need to get this automatically
doc.Load("../../request.xml");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost/dummyws/dummyws.asmx?op=HelloWorld");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
using (Stream reqstm = req.GetRequestStream())
{
doc.Save(reqstm);
}
using (WebResponse resp = req.GetResponse())
{
using (Stream respstm = resp.GetResponseStream())
{
using (StreamReader r = new StreamReader(respstm))
{
Console.WriteLine(r.ReadToEnd());
}
}
}

Related

c# Sign a SOAP envelope webrequest with a 509 cert

I'm working with a third party that refuses to fix their scheme for a published WSDL. The issue is the SOAP service is expecting different name spaces than the WSDL is providing. So in my C# app I'm having a lot of trouble using the Proxy by .Net. In an attempt to work around this I want to just send a web-request and package up my data
I just can't figure out how to add my signature to the header of my request.
Microsoft.Web.Services3.SoapEnvelope soapEnvelopeXml = new Microsoft.Web.Services3.SoapEnvelope();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"https://Illinois-stage.tylerhost.net/efm/FilingReviewMDEPort.svc");
request.Headers.Add("SOAPAction:\"urn:oasis:names:tc:legalxml-courtfiling:wsdl:WebServicesProfile-Definitions-4.0/FilingReviewMDEPort/ReviewFilingRequest\"");
request.Headers.Add("Accept-Encoding: gzip, deflate");
request.KeepAlive = true;
request.Headers.Add("MIME-Version: 1.0");
request.ContentType = "multipart/related; type=\"application/xop+xml\";start=\"<http://tempuri.org/0>\";boundary=\"uuid:936f2c7e-590a-4f19-b154-ce8285adf18a+id=2\";start-info=\"text/xml\"";
request.Method = "POST";
soapEnvelopeXml.Load(#"c:\temp\ReviewFilingRequest.xml");
System.IdentityModel.Tokens.X509SecurityToken securityToken = new System.IdentityModel.Tokens.X509SecurityToken(X509);
Microsoft.Web.Services3.Security.Tokens.X509SecurityToken signatureToken = new Microsoft.Web.Services3.Security.Tokens.X509SecurityToken(X509);
MessageSignature sig = new MessageSignature(signatureToken);
////////// XmlDocumentFragment xfrag = soapEnvelopeXml.CreateDocumentFragment();
//////////xfrag.InnerXml = messageHeader;
//////////soapEnvelopeXml.DocumentElement.FirstChild.AppendChild(xfrag);
XmlDocument xmlDoc = new XmlDocument();
MemoryStream xmlStream = new MemoryStream();
xmlDoc.Save(xmlStream);
using (var writer = XmlDictionaryWriter.CreateMtomWriter(xmlStream, Encoding.UTF8, int.MaxValue, "text/xml", "uuid:936f2c7e-590a-4f19-b154-ce8285adf18a+id=2", "http://tempuri.org/0",false,false))
{
soapEnvelopeXml.WriteTo(writer);
using (Stream stream = request.GetRequestStream())
{
stream.Write(xmlStream.ToArray(),0, xmlStream.ToArray().Length );
}
}
using (WebResponse response = request.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
string soapResult = rd.ReadToEnd();
Console.WriteLine(soapResult);
}
}
A couple things that might be able to help.
What error message are you getting back? Access Denied (or something along those lines)?
Have you tried looking at which headers you are missing? The best way to do this is to download WireShark or Telerik's Fiddler which allows HTTPS decryption. Using one of these, you can access the website in an internet browser and view the headers that are being sent through a normal browser.
I ended up signing it in Node.js Making the switch to node gave me a lot more control over the message. As an added bonus I didn't have to pay the Microsoft Tax.
https://www.npmjs.com/search?q=soap&page=1&ranking=optimal

cannot call web api successfully when sending xml data

I cannot successfully call an API using C# at the moment. I have attached a screen shot of the call being successfully made with Chrome PostMan although I'm not able to replicate it in C#. He is my attempt so far which fails. The response I get back from the server is included below. Can anyone see what I'm doing wrong?
Many thanks,
James
Code Snippet
const string xml = "<Envelope><Body> <AddRecipient>...";
var req = (HttpWebRequest)WebRequest.Create(ApiUrl);
var requestBytes = System.Text.Encoding.ASCII.GetBytes(xml);
req.Method = "POST";
req.Headers.Add("Authorization", "Bearer " + token);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = requestBytes.Length;
var requestStream = req.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
var res = (HttpWebResponse)req.GetResponse(); // Call API
var sr = new StreamReader(res.GetResponseStream(), System.Text.Encoding.Default);
var backstr = sr.ReadToEnd();
sr.Close();
res.Close();
Chrome PostMan
Response back from API
<Envelope><Body><RESULT><SUCCESS>false</SUCCESS></RESULT><Fault><Request/><FaultCode/><FaultString>Server Error</FaultString><detail><error><errorid>50</errorid><module/><class>SP.API</class><method/></error></detail></Fault></Body></Envelope>
Is there any documentation about what error 50 is? Could just be a bad pram? If not I recommend downloading fiddler. You can then properly compare the request from both PostMan and your application to see what the actual difference is.

How to register the device via SOAP?

I'm executing the following code in order to register a randomized user name and a password for login using live id.
String regUrl = "https://login.live.com/ppsecure/DeviceAddCredential.srf";
WebRequest request = WebRequest.Create(regUrl);
request.ContentType = "application/soap+xml; charset=UTF-8";
request.Method = "POST";
request.Timeout = 60000;
StreamReader reader = new StreamReader(request.GetRequestStream());
String contents = reader.ReadToEnd();
I'm following the code in this article and it's not going quick nor easy. I get the error telling me that stream was not readable.
What am I missing and what can be done about it?
You're trying to read from a request stream, when you should be writing to it. The response stream contains the server's reply.

C# HttpWebRequest with XML Structured Data

I'm developing the client-side of a third party webservice. The purpose is that I send xml-file to the server.
How should I attach the xml-file to the httpwebrequest? What contentType is needed? More suggestions?
I cannot use mtom or dime.ie because I am using httpwebrequest. I am unable to use WCF either.
Here is a very basic method of sending XML structured data using HttpWebRequest (by the way you need to use request.ContentType = "application/xml";) :
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(myUrl));
request.Method = "POST";
request.ContentType = "application/xml";
request.Accept = "application/xml";
XElement redmineRequestXML =
new XElement("issue",
new XElement("project_id", 17)
);
byte[] bytes = Encoding.UTF8.GetBytes(redmineRequestXML.ToString());
request.ContentLength = bytes.Length;
using (Stream putStream = request.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}
// Log the response from Redmine RESTful service
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
Logger.Info("Response from Redmine Issue Tracker: " + reader.ReadToEnd());
}
I use this at one of my projects (NBug) to submit an issue report to my Redmine issue tracker which accepts XML structured data over web requests (via POST). If you need further examples, you can get a couple of fully featured examples here: http://nbug.codeplex.com/SourceControl/list/changesets (click 'Browse' under 'Latest Verion' label on the right then navigate to "NBug\Submit\Tracker\Redmine.cs")

500 internal server error at GetResponse()

I have a heavy traffic aspx page calling a web service upon every user`s request as follows.
string uri = "Path.asmx";
string soap = "soap xml string";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers.Add("SOAPAction", "\"http://xxxxxx"");
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
using (Stream stm = request.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
WebResponse response = request.GetResponse();
response.close();
Everything is working fine but sometimes I am getting the following error.
The remote server returned an error: (500) Internal Server Error.
at System.Net.HttpWebRequest.GetResponse()
Does anybody have any idea about this error or can anybody tell me if I am doing wrong.
For me this error occurred because I had 2 web API actions that had the exact same signatures and both had the same verbs, HttpPost, what I did was change one of the verbs (the one used for updating) to PUT and the error was removed. The following in my catch statement helped in getting to the root of the problem:
catch (WebException webex)
{
WebResponse errResp = webex.Response;
using (Stream respStream = errResp.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
string text = reader.ReadToEnd();
}
}
From that error, I would say that your code is fine, at least the part that calls the webservice. The error seems to be in the actual web service.
To get the error from the web server, add a try catch and catch a WebException. A WebException has a property called Response which is a HttpResponse. you can then log anything that is returned, and upload you code. Check back later in the logs and see what is actually being returned.
Finally I get rid of internal server error message with the following code. Not sure if there is another way to achieve it.
string uri = "Path.asmx";
string soap = "soap xml string";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Headers.Add("SOAPAction", "\"http://xxxxxx"");
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
using (Stream stm = request.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
using (WebResponse webResponse = request.GetResponse())
{
}
Have you tried to specify UserAgent for your request? For example:
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
looking at your error message first of all I would suggest you to recompile your whole application, make sure all the required dlls are there in bin folder when you recompile it.
In my case my request object inherited from base object. Without knowingly I added a property with int? in my request object and my base object also has same property ( same name ) with int datatype. I noticed this and deleted the property which I added in request object and after that it worked fine.
For me the error was misleading. I discovered the true error by testing the errant web service with SoapUI.
In my case I just remove the SoapAction instruction from the HttpWebRequest object. So, I don't define .Headers.Add("SOAPAction","someurl") in HttpWebRequest definitions and my code works fine.
ResultXML is an XDocument.
ResultString is a string.
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
//req.Headers.Add("SOAPAction", "http://tempuri.org/IWebService/GetMessage");
req.ProtocolVersion = HttpVersion.Version11;
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.KeepAlive = true;
req.Method = "POST";
using (Stream stm = req.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
stmw.Write(soapStr);
}
using (StreamReader responseReader = new StreamReader(req.GetResponse().GetResponseStream()))
{
string result = responseReader.ReadToEnd();
ResultXML = XDocument.Parse(result);
ResultString = result;
}
}

Categories