Post JSON over HTTPS - c#

In the past I have successfully called a JSON webservice over HTTP
But, now I have to make a JSON POST over HTTPS.
I have tried using the code that works for HTTP and simply changed the url that is being called to https but it won't work.
This is the code i am using...
WebRequest wrGETURL;
wrGETURL = WebRequest.Create("https://apitest.example.com/geo/coverage/v1/?appId=2644571&appKey=836621d715b6ce4db5f007d8fa2214f");
wrGETURL.Method = "POST";
Stream objStream;
objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string responseFromServer = objReader.ReadToEnd();
and the error message i am seeing in fiddler is:
fiddler.network.https> Failed to secure existing connection for apitest.example.com. A call to SSPI failed, see inner exception. InnerException: System.ComponentModel.Win32Exception (0x80004005): The client and server cannot communicate, because they do not possess a common algorithm
Can anyone help me with that I need to do to make a call over HTTPS please?

Do you need to authenticate or maybe a callback for the server certificate?
This works for me in most cases:
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://someurl/");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
// Create NetworkCredential Object
NetworkCredential admin_auth = new NetworkCredential("username", "password");
// Set your HTTP credentials in your request header
httpWebRequest.Credentials = admin_auth;
// callback for handling server certificates
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"name\":\"TEST_123\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
}

I am using React and Expressjs and ran into this issue. Send your ie: https://www.google.com with out the https:
part of my router.js
router('/vod')
.rout.get('/vod', (req,res)=>{
res.send({message: "//www.google.com"});
App.js
function App() {
const [vod, setVod] = React.useState(null);
React.useEffect(() => {
fetch("/vod")
.then((res) => res.json())
.then((vod) => setVod(vod.message));
},
[]);
return (
<div className="App">
<header className="App-header">
<iframe src={"https:"+vod}
id="myIframe" autoPlay width={1000} height=
{500} frame></iframe>
</header>
</div>
);
in the iframe to change the source I used {"https:"+vod} to simulate the full url.
in your case try to combine your "result" like ("https:"+result)
I noticed that json grabs the : and messes the string up.

Related

Why python request working but C# request not working?

First, i try to post the script in PostMan tool.
{"AO":"ECHO"}
It working fine. Then i'm writing this request in C# but it not working.
And more i wrote the request again in Python, and it working well.
But my project is in Microsoft C#. I dont want to run script Python in C# at all.
==== Python =========
import httplib
import json
import sys
data = '{"AO":"ECHO"}'
headers = {"Content-Type": "application/json", "Connection": "Keep-Alive" }
conn = httplib.HTTPConnection("http://10.10.10.1",1040)
conn.request("POST", "/guardian", data, headers)
response = conn.getresponse()
print response.status, response.reason
print response.msg
==== C# ============
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://10.10.10.1:1040/guardian");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"AO\":\"ECHO\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
}
}
I try to put "ContentLength" but it still timeout exception.
And i try to using RestSharp, it's not timeout but return null.
Any one please help...
var client = new RestClient("http://10.10.10.1:1040/guardian");
var request = new RestRequest();
request.Method = Method.POST;
request.AddHeader("Content-Type", "application/json");
request.Parameters.Clear();
request.RequestFormat = DataFormat.Json;
request.AddBody(new { AO = "ECHO" });
var response = client.Execute(request);
var content = response.Content;
Please help me,
I dont understand why it working fine in python.
But why it not working in C#.
I try to find many request in C# but it got error exception with timeout.
Python will automatically add Content-Length http header.
https://docs.python.org/2/library/httplib.html#httpconnection-objects
I think you might have to set this header manually in C#.
httpWebRequest.ContentLength = json.length;
Depending on the server, you may have to set UserAgent as well.
httpWebRequest.UserAgent=".NET Framework Test Client";

How to: C# WebClient to hit service endpoint (Oauth 2.0 like protocol) with Mutual TLS

I need to hit a service to obtain the app ticket to authenticate against another service. The solution is hosted on a endpoint.
I tried using the POSTMAN app in google chrome and it succeeds and returns me the AppID. When I submit the (POST)request in POSTMAN app, it prompts for a certificate. When I select the correct certificate the call succeeds.
I need to implement the same in C# (in a web application)
I tried using the RestSharp.RestClient library and am constantly getting the following error:
"Client certificate not found in site certificates".
Attaching the code for reference.
var client = new RestSharp.RestClient("MyUrl");
var request = new RestSharp.RestRequest("pksecure/oauth20_clientcredentials.srf", RestSharp.Method.POST);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("param2", "value2");
request.AddParameter("scope", "machinename");
client.ClientCertificates = new System.Security.Cryptography.X509Certificates.X509CertificateCollection();
client.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(
#"E:\MyCertificate.pfx"
, "MyPassword"
));
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslError)
{
bool validationResult = true;
return validationResult;
};
var response = client.Execute(request);
var content = response.Content; // raw content as string
Pls. help to make this call using the mutual TLS.
TIA,
Sam.
I am not sure why I was not able to get it done using RestSharp.
But I could get it working by using HttpWebRequest Instead.
Also, earlier I was using the Certficate.Pfx file which caused the error. Using the Certificate.Cer file solved the issue.
Posting the code for reference:
var request = (HttpWebRequest)WebRequest.Create("MyURL/oauth20_clientcredentials.srf");
var postData = "grant_type=client_credentials";
postData += "&param2=value2";
postData += "&scope=" + HttpUtility.UrlEncode("machinename");
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
request.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(#"E:\MyCertificate.cer"));
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return appToken;
Thanks,
Sam Jayander Thiagarajan.

HttpWebRequest.GetResponse() keeps getting timed out

i wrote a simple C# function to retrieve trade history from MtGox with following API call:
https://data.mtgox.com/api/1/BTCUSD/trades?since=<trade_id>
documented here: https://en.bitcoin.it/wiki/MtGox/API/HTTP/v1#Multi_currency_trades
here's the function:
string GetTradesOnline(Int64 tid)
{
Thread.Sleep(30000);
// communicate
string url = "https://data.mtgox.com/api/1/BTCUSD/trades?since=" + tid.ToString();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string json = reader.ReadToEnd();
reader.Close();
reader.Dispose();
response.Close();
return json;
}
i'm starting at tid=0 (trade id) to get the data (from the very beginning). for each request, i receive a response containing 1000 trade details. i always send the trade id from the previous response for the next request. it works fine for exactly 4 requests & responses. but after that, the following line throws a "System.Net.WebException", saying that "The operation has timed out":
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
here are the facts:
catching the exception and retying keeps causing the same exception
the default HttpWebRequest .Timeout and .ReadWriteTimeout are already high enough (over a minute)
changing HttpWebRequest.KeepAlive to false didn't solve anything either
it seems to always work in the browser even while the function is failing
it has no problems retrieveing the response from https://www.google.com
the amount of successful responses before the exceptions varies from day to day (but browser always works)
starting at the trade id that failed last time causes the exception immediately
calling this function from the main thread instead still caused the exception
running it on a different machine didn't work
running it from a different IP didn't work
increasing Thread.Sleep inbetween requests does not help
any ideas of what could be wrong?
I had the very same issue.
For me the fix was as simple as wrapping the HttpWebResponse code in using block.
using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
{
// Do your processings here....
}
Details: This issue usually happens when several requests are made to the same host, and WebResponse is not disposed properly. That is where using block will properly dispose the WebResponse object properly and thus solving the issue.
There are two kind of timeouts. Client timeout and server timeout. Have you tried doing something like this:
request.Timeout = Timeout.Infinite;
request.KeepAlive = true;
Try something like this...
I just had similar troubles calling a REST Service on a LINUX Server thru ssl. After trying many different configuration scenarios I found out that I had to send a UserAgent in the http head.
Here is my final method for calling the REST API.
private static string RunWebRequest(string url, string json)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
// Header
request.ContentType = "application/json";
request.Method = "POST";
request.AllowAutoRedirect = false;
request.KeepAlive = false;
request.Timeout = 30000;
request.ReadWriteTimeout = 30000;
request.UserAgent = "test.net";
request.Accept = "application/json";
request.ProtocolVersion = HttpVersion.Version11;
request.Headers.Add("Accept-Language","de_DE");
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
byte[] bytes = Encoding.UTF8.GetBytes(json);
request.ContentLength = bytes.Length;
using (var writer = request.GetRequestStream())
{
writer.Write(bytes, 0, bytes.Length);
writer.Flush();
writer.Close();
}
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var jsonReturn = streamReader.ReadToEnd();
return jsonReturn;
}
}
This is not a solution, but just an alternative:
These days i almost only use WebClient instead of HttpWebRequest. Especially WebClient.UploadString for POST and PUT and WebClient.DownloadString. These simply take and return strings. This way i don't have to deal with streams objects, except when i get a WebException. i can also set the content type with WebClient.Headers["Content-type"] if necessary. The using statement also makes life easier by calling Dispose for me.
Rarely for performance, i set System.Net.ServicePointManager.DefaultConnectionLimit high and instead use HttpClient with it's Async methods for simultaneous calls.
This is how i would do it now
string GetTradesOnline(Int64 tid)
{
using (var wc = new WebClient())
{
return wc.DownloadString("https://data.mtgox.com/api/1/BTCUSD/trades?since=" + tid.ToString());
}
}
2 more POST examples
// POST
string SubmitData(string data)
{
string response;
using (var wc = new WebClient())
{
wc.Headers["Content-type"] = "text/plain";
response = wc.UploadString("https://data.mtgox.com/api/1/BTCUSD/trades", "POST", data);
}
return response;
}
// POST: easily url encode multiple parameters
string SubmitForm(string project, string subject, string sender, string message)
{
// url encoded query
NameValueCollection query = HttpUtility.ParseQueryString(string.Empty);
query.Add("project", project);
query.Add("subject", subject);
// url encoded data
NameValueCollection data = HttpUtility.ParseQueryString(string.Empty);
data.Add("sender", sender);
data.Add("message", message);
string response;
using (var wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
response = wc.UploadString( "https://data.mtgox.com/api/1/BTCUSD/trades?"+query.ToString()
, WebRequestMethods.Http.Post
, data.ToString()
);
}
return response;
}
Error handling
try
{
Console.WriteLine(GetTradesOnline(0));
string data = File.ReadAllText(#"C:\mydata.txt");
Console.WriteLine(SubmitData(data));
Console.WriteLine(SubmitForm("The Big Project", "Progress", "John Smith", "almost done"));
}
catch (WebException ex)
{
string msg;
if (ex.Response != null)
{
// read response HTTP body
using (var sr = new StreamReader(ex.Response.GetResponseStream())) msg = sr.ReadToEnd();
}
else
{
msg = ex.Message;
}
Log(msg);
}
For what it's worth, I was experiencing the same issues with timeouts every time I used it, even though calls went through to the server I was calling. The problem in my case was that I had Expect set to application/json, when that wasn't what the server was returning.

ASP.NET HTTP Authorization Header

I would like to know why my asp.net application will not add the header to my post when it is named 'Authorization' but will work fine when I change one character, say "Authorizations". In documentation for other sites they always use the name "Authorization" so I would like to as well and at this point I just want to under stand why.
I have read a few topics about this but have not found any logical reason why.
Here is my code below:
string fileName = "c:\\xyz.xml";
string uri = "http://myserver/Default.aspx";
req = WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "text/xml";
byte[] authBytes = Encoding.UTF8.GetBytes("DDSServices:jCole2011".ToCharArray());
req.Headers.Add("Authorization", "BASIC " + Convert.ToBase64String(authBytes) );
req.Headers.Add("test", "test");
UTF8Encoding encoder = new UTF8Encoding();
byte[] data = encoder.GetBytes(this.GetTextFromXMLFile(fileName));
req.ContentLength = data.Length;
Stream reqStream = req.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
req.Headers.Add("Authorization", "BASIC" + Convert.ToBase64String(authBytes));
System.Net.WebResponse response = req.GetResponse();
System.IO.StreamReader reader = new StreamReader(response.GetResponseStream());
string str = reader.ReadToEnd();
The other annoying this is when i add the watched variable through fiddler it works fine.
I was ran into a question how to add Authentication/Credentials to the headers. I found the solution in the following way.
string _auth = string.Format("{0}:{1}", "myUser","myPwd");
string _enc = Convert.ToBase64String(Encoding.ASCII.GetBytes(_auth));
string _cred = string.Format("{0} {1}", "Basic", _enc);
req.Headers[HttpRequestHeader.Authorization] = _cred;
Which gave me those headers I want (pasted Wireshark descriptions),
Authorization: Basic bXlVc2VyOm15UHdk\r\n
Credentials: myUser:myPwd
For HTTP Basic Authorization, you should be using the Credentials property.
req.Credentials = new NetworkCredential("DDSServices", "jCole2011");
This should do what you want. Rather than setting the Authorization header.
NetworkCredential is a good solution but the site you are calling has to handle an unauthorized with a 401 AND a WWW-Authenticate header in the response.
Client:
request.Credentials = new CredentialCache {{aUri, "Basic", new NetworkCredential(aUserName, aPassword)}};
Server:
Response.ClearContent();
Response.StatusCode = 401;
Response.AddHeader("WWW-Authenticate", "Basic");
Response.End();
This will result in 2 hits to the server. The initial call will go to the server without credentials. When the server responds with a 401 AND the WWW-Authenticate header (with the type of authentication required), the request will be resent with the credentials in the request.

WebRequest to connect to the Wikipedia API

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

Categories