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
Related
I'm quite stuck trying to perform a POST request using a P12 certificate that was provided by the server. I've never dealt with HTTPS before, and I'm going in circles (I'm not sure I'm even using the right terminology). I know this must be quite basic, but this is the first time I need to code something like this.
I've even tried to replicate what others have done for exactly the same purpose, but for some reason it does not work (perhaps it has to do with how it works in Android, I'm not sure).
This is what I have right now:
// P12 certificate is placed in "assets" folder
AssetManager assets = Application.Context.Assets;
byte[] bytes;
using (StreamReader sr2 = new StreamReader(assets.Open("myCertificate.p12")))
{
using (var memstream = new MemoryStream())
{
sr2.BaseStream.CopyTo(memstream);
bytes = memstream.ToArray();
}
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://www.aidap.naimes.faa.gov/aidap/XmlNotamServlet");
X509Certificate2 clientCertificate = new X509Certificate2(bytes, "myPassword");
req.ClientCertificates.Add(clientCertificate);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
string postData = "uid=myUsername&password=myPassword&active=Y";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
req.ContentLength = byteArray.Length;
// **Next line triggers the Exception**
using (Stream dataStream = req.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
}
// Show the first 10 lines
using (StreamReader sr = new StreamReader(req.GetResponse().GetResponseStream()))
{
for (int i = 0; i < 10; i++)
Console.WriteLine(sr.ReadLine());
}
When calling GetRequestStream() I get the following (I copy the first bit, as it's quite long):
{System.Net.WebException: Error: SecureChannelFailure (One or more errors occurred.) ---> System.AggregateException: One or more errors occurred. ---> System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> Mono.Btls.MonoBtlsException: Syscall
at Mono.Btls.MonoBtlsContext.ProcessHandshake () [0x00038] in <9624f2cab6ac4ffc9c31e9469d40591a>:0
at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake
The certificate and password seems to work correctly, as I can inspect in debug mode and verify that all details are loaded in "clientCertificate".
EDIT
So I tried following Ketan's suggestion but I'm not quite sure how to add a trace to an Android project. What I did, is to create a small console application but I didn't have to add a trace because it worked perfectly right away.
I also tried a different approach with RestSharp and it worked once again perfectly in the console application but not in Xamarin:
var client = new RestClient("https://www.aidap.naimes.faa.gov/aidap/XmlNotamServlet");
client.ClientCertificates = new X509CertificateCollection() { clientCertificate };
string postData = "uid=myUsername&password=myPassword&active=Y";
var request = new RestRequest(Method.POST);
request.AddParameter("application/x-www-form-urlencoded", postData, ParameterType.RequestBody);
var response = client.Execute(request);
So there must be something preventing the SSL from working in Android.
I can't insert permission to a file with this code:
string URI = String.Format("https://www.googleapis.com/drive/v2/files/{0}/permissions&access_token={1}", fileId, "token");
var request = (HttpWebRequest)HttpWebRequest.Create(URI);
request.Method = "POST";
request.ContentType = "application/json";
string json = "{\"role\": \"reader\",\"type\": \"anyone\"}";
byte[] byteData = new System.Text.ASCIIEncoding().GetBytes(json);
request.ContentLength = byteData.Length;
using (var dataStream = request.GetRequestStream())
{
dataStream.Write(byteData, 0, byteData.Length);
}
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream()))
{
json = reader.ReadToEnd();
}
I al getting a 404 error. What's the problem?
string URI = String.Format("https://www.googleapis.com/drive/v2/files/{0}/permissions&access_token={1}", fileId, "token");
Access token is not a string "token" it must be a valid access token for the user who owns the file.
Update:
permissions?access_token={1}",
You should be using ? and not & to add a parameter to the url. Not even sure you can do it like that with a HTTP Post.
Added info:
If this is not simply a typo on your part you may want to read up on Authorization a little
I also recommend checking out the Google client library instead of writing this yourself. Google.Apis.Drive.v2 Client Library.
There is a newer version of the Google Drive API you might also be interested in looking at rather then writing new code for an older version of the API. Google Drive API v3.
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")
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());
}
}
}
This may be a pathetically simple problem, but I cannot seem to format the post webrequest/response to get data from the Wikipedia API. I have posted my code below if anyone can help me see my problem.
string pgTitle = txtPageTitle.Text;
Uri address = new Uri("http://en.wikipedia.org/w/api.php");
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
string action = "query";
string query = pgTitle;
StringBuilder data = new StringBuilder();
data.Append("action=" + HttpUtility.UrlEncode(action));
data.Append("&query=" + HttpUtility.UrlEncode(query));
byte[] byteData = UTF8Encoding.UTF8.GetBytes(data.ToString());
request.ContentLength = byteData.Length;
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(byteData, 0, byteData.Length);
}
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
// Get the response stream.
StreamReader reader = new StreamReader(response.GetResponseStream());
divWikiData.InnerText = reader.ReadToEnd();
}
You might want to try a GET request first because it's a little simpler (you will only need to POST for wikipedia login). For example, try to simulate this request:
http://en.wikipedia.org/w/api.php?action=query&prop=images&titles=Main%20Page
Here's the code:
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create("http://en.wikipedia.org/w/api.php?action=query&prop=images&titles=Main%20Page");
using (HttpWebResponse response = (HttpWebResponse)myRequest.GetResponse())
{
string ResponseText;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
ResponseText = reader.ReadToEnd();
}
}
Edit: The other problem he was experiencing on the POST request was, The exception is : The remote server returned an error: (417) Expectation failed. It can be solved by setting:
System.Net.ServicePointManager.Expect100Continue = false;
(This is from: HTTP POST Returns Error: 417 "Expectation Failed.")
I'm currently in the final stages of implementing an C# MediaWiki API which allows the easy scripting of most MediaWiki viewing and editing actions.
The main API is here: http://o2platform.googlecode.com/svn/trunk/O2%20-%20All%20Active%20Projects/O2_XRules_Database/_Rules/APIs/OwaspAPI.cs and here is an example of the API in use:
var wiki = new O2MediaWikiAPI("http://www.o2platform.com/api.php");
wiki.login(userName, password);
var page = "Test"; // "Main_Page";
wiki.editPage(page,"Test content2");
var rawWikiText = wiki.raw(page);
var htmlText = wiki.html(page);
return rawWikiText.line().line() + htmlText;
You seem to be pushing the input data on HTTP POST, but it seems you should use HTTP GET.
From the MediaWiki API docs:
The API takes its input through
parameters in the query string. Every
module (and every action=query
submodule) has its own set of
parameters, which is listed in the
documentation and in action=help, and
can be retrieved through
action=paraminfo.
http://www.mediawiki.org/wiki/API:Data_formats