Exception using WebClient calling HTTPS URLs - c#

For about 3 months I have a public app which is using the WebClient to call some HTTPS API.
Until about 3 weeks ago everything worked fine, but suddenly the app stopped working and all the WebClient calls throw "The remote server returned an error: NotFound." exception.
I didn't update my app in any way, the API didn't change, I didn't notice any update for the Windows Phone.
I mention that my app is targeting the Windows Phone OS 7.1 and I also tried to use the HttpWebRequest class - the result is the same.
My code looks something like this:
private void tile_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri("https://www.google.com"));
}
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
try {
StreamReader s = new StreamReader(e.Result);
string r = s.ReadToEnd();
MessageBox.Show(r);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This code will fail every time it's called with the above mentioned exception. If I would try to get the "http://www.google.com" or any other HTTP URL the code will work fine.
However, I need to use HTTPS as I need to send also credentials with the WebClient calls.
I found on the Internet that other people ran into such issues last year, but this problem was supposed to be fixed with Mango update.
Does anybody know how can I fix this issue or any workaround as I ran out of ideas.
Thank you in advance!
Regards,
Andrei

First the NotFound error is a generic one, to get the specifics of the problem you need to use a tool like Fiddler (with the emulator: http://blogs.msdn.com/b/fiddler/archive/2010/10/15/fiddler-and-the-windows-phone-emulator.aspx / with a device : http://blogs.msdn.com/b/fiddler/archive/2011/01/09/debugging-windows-phone-7-device-traffic-with-fiddler.aspx)
Now maybe it's a problem with the SSL certificate? I you visit the same URL with a desktop browser do you get a warning/error about its validity? If so you are out of luck, because I don't think you can override the validation of the certificate on Windows Phone like it's possible with the fwk on desktop.
But first try to debug with Fiddler to get some details.

Related

400 bad request invalid hostname only in android application

I have a asp.net mvc website deployed on a server, providing a few web interfaces to others. For example, getting the current user's information, my test C# console application looks like this:
using (var client = new WebClient())
{
try
{
var url = "http://api.fake.mysite.com/v1.0/user/current";
var token = "e0034e1c082de62b74e361b15f9c6471";
var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(token));
client.Headers["Authorization"] = encoded;
client.Headers["Content-Type"] = "application/json";
Console.WriteLine(client.DownloadString(url));
}
catch (WebException e)
{
//log the exception
}
}
You can see the usage is pretty simple, just request the url via HTTP_GET, set the Authorization header to the encoded token. Actually it works fine in my machine. But some one else meets a strange issue when visiting this url in an android application, here is the java code:
HttpClient httpClient = new DefaultHttpClient();
String token = "e0034e1c082de62b74e361b15f9c6471";
String url = "http://api.fake.mysite.com/v1.0/user/current";
HttpGet httpGet = new HttpGet(url);
String encoded = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
httpGet.addHeader("Authorization", encoded);
httpGet.addHeader("Content-Type", "application/json");
try {
HttpResponse httpResponse = httpClient.execute(httpGet);
int responseCode = httpResponse.getStatusLine().getStatusCode();
String response = EntityUtils.toString(httpResponse.getEntity());
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
then he got "400 bad request invalid host name" error. I've tried:
(1) make sure the variable "encoded" has the same value in C# and Java code.
(2) make sure the website's domain name is correctly set in server IIS
(3) all PCs/mobile phones can visit the test index page(http://api.fake.mysite.com)
(4) ping api.fake.mysite.com works fine
(5) if removing httpGet.addHeader("Authorization", encoded);, the Java program got a 401 Unauthorized result as expected(the server code under my control returns the result)
(6) some other applications using C# and PHP can use the web methods well, only android application can't(tested in two totally different android mobile phones, the android emulator got 400 invalid host name either)
(7) use IP instead of domain name http://xx.xx.xx.xx/v1.0/user/current, everything is the same. (xx.xx.xx.xx stands for the ip address)
(8) checked the IIS log, all requests to /v1.0/user/current returns 200/401/500, no 400 results.
(9) make sure the android application has internet permissions(actually we've added all permissions)
Does anyone know the reason or help to find the reason? Thank you very much, this issue is driving me crazy.
Should be httpGet.addHeader("Authorization", "basic " + encoded); and String encoded = Base64.encodeToString(token.getBytes(), Base64.NO_WRAP);
I struggled the very same problem. I can send HTTP POST from Fiddler or any other tool to my asp.net web API in debug mode but I can not access from my android application.
I tried to be sure to connect from my computer browser to
web API interface.
I tried to be sure to connect from android emulator web
browser(AEWB). And then I deployed my web api to IIS so I can get certain address to access from AEWB.
I can accessed to this adres from my AEWB
http://10.0.0.2:8088/api/tran
http://10.0.0.2 -> this is your local host address seen from Android
8088 -> this is your port of web api hosted on IIS
/api -> this is web api
/tran -> this is your controller

WebClient failing on physical device and emulator

UPDATE:
Maybe it's just me not understanding how oAuth works? I tried running
the query manually on http://www.apikitchen.com and I get a 400 error
there too! Just to be sure, am I constructing the URL correctly here?
POST URL:
https://api.bufferapp.com/1/oauth2/token.json?client_id=[hidden]&client_secret=[hidden]&redirect_uri=http://apps.joel-murphy.com/buffer/code/success.php&code=[the
access code I get from buffer starting with
1/]&grant_type=authorization_code
Original post:
I'm building a Windows Phone application which requires the use of data from a website. The website uses oAuth to authenticate users.
I used the built in web browser control to make a GET request to authenticate users. The official documentation requires the URL structure to be like this:
GET https://bufferapp.com/oauth2/authorize?
client_id=...&
redirect_uri=...&
response_type=code
This part of my app works. Although when it comes to exchanging the Authorization token for an access token from the server, I am facing problems. The official documentation requires the URL structure to be like this:
POST https://api.bufferapp.com/1/oauth2/token.json?
client_id=...&
client_secret=...&
redirect_uri=...&
code=...&
grant_type=authorization_code
Correct me if I'm wrong, but from what I know there is no way to make a POST request from a browser, unless submitting a form. For this reason, I have decided to use the WebClient class to submit data to the server. However, no matter if I run my code on an actual device or on the Visual studio emulator I always receive the following error:
The remote server returned an error: NotFound
Does anyone have any idea what's wrong with the following code? I've spent over 5 hours across 2 days trying to solve this error, but nothing seems to be working.
The code I'm using:
WebClient wc = new WebClient();
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(wc_UploadStringCompleted);
wc.UploadStringAsync(new Uri(access_token_url), "POST", GetPostParameters());
void wc_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
try
{
MessageBox.Show(e.Result);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
string GetPostParameters()
{
string data = "";
data += "client_id="+client_id + "&";
data += "client_secret=" +client_secret + "&";
data += "redirect_uri=" + redirect_uri+ "&";
data += "code=" + App.AccessToken + "&";
data += "grant_type=authorization_code";
return data;
}
Does anyone have any idea what's wrong? this is driving me crazy and it's a real shame that oauth has to be so complicated when it's such a used technology nowadays.
Thanks in advance.
Can you try URL-encoding the redirect_uri variable?

StreamReader, Bad Request (400)

We have a website that allow firmware downloads.
Somwhere along the way it uses a StreamReader. For some unknown reason, some customer (In Israel) get a 400 Bad Request error. Everyone else do not get this error.
Any1 out there experienced the same thing ? Anyone got a clue ?
protected void Page_Load(object sender, EventArgs e)
{
string strURL = Request.Url.Host;
System.Net.WebRequest reqPT = System.Net.WebRequest.Create("http://" + strURL + "/Products/ProductTree.asp");
System.IO.StreamReader srPT = new System.IO.StreamReader(reqPT.GetResponse().GetResponseStream());
dvPT.Controls.Add(new LiteralControl(srPT.ReadToEnd()));
}
It crashes, for them only, at the new StreamReader.
Thank you !
UPDATE : We noticed that the customer is actually loosing the "www" in the address (strURL), wich cause the error. Why would someone, (clicking on the same link as the rest of the planet is) would loose the www ?? I'm seeing 2 differents behavior for the exact same code :S
Well with the HTTP 400 error the requested URL is probably invalid, and since the literals in your System.Net.WebRequest look OK, my guess is your Israeli user is requesting the page using a different Request.Url.Host than everyone else. Can you debug and verify the value of strUrl?

How do i catch page cannot load message?

Hi i hope someone can help,
In basic terms i am trying to stop the embedded browser, in my Windows Forms app, from navigating to the 'This program cannot display the webpage' page and instead display my own error page.
The C# application is a Web Browser embedded in my Windows Forms, its purpose is allowing the user to click on the provided buttons that navigate the browser to predefined WebService URL's. If the Service is not running on the Machine then instead of the browser saying that it was unable to load i need to to navigate to my custom page instead.
I have looked around and as yet had no luck in finding a solution apparently HttpStatusCodes are a way to go but i have no idea how to use them.
Code Snippet:
private void currentMachineToolStripMenuItem_Click(object sender, EventArgs e)
{
webBrowser1.Navigate("http://localhost:2021/wsservice/status");
}
As you can see, currently very simple program.
You can try this:
Private void WebBrowser1_NavigateError(Object sender, EventArgs e)
{
WebBrowser1.Navigate( App.Path + "\retry.htm");
}
Taken from this link -
You would need to use an HttpWebRequest and an HttpWebResponse object to do
this. Create the HttpWebRequest with the desired URL, using the
WebRequest.Create(url) method. Then use the GetResponse() method to get the
HttpWebResponse. The HttpWebResponse will have the status code returned from
the server. This will tell you if the URL exists or not. 404 indicates "Page
not Found." 200 indicates "Success." Etc.
http://msdn.microsoft.com/en-us/library/8y7x3zz2(vs.71).aspx
Also another link which might help you - http://www.vcskicks.com/check-website.php
You can check the page content for a word that indicates that the page did not load correctly
if(webBrowser1.Document.InnerHtml.Contains("error"))
You can check too the returned document url, find the resource address that webBrowser use to show error page:
if (webBrowser1.Document.Url.ToString().Contains("res://ieframe.dll/dnserrordiagoff.htm") )
...

.NET HttpWebRequest HTTPS Error

Hello I'm trying to fetch data from a https web (i'm not behind firewall or proxy) however even accepting all certificates it keeps throwing System.Net.WebExceptionStatus.SecureChannelFailure with the message shown: Cancelled the request: Unable to create a secure SSL/TLS channel
... i've looked everywhere so you guys are my last chance.
static void Main(string[] args)
{
RemoteCertificateValidationCallback ServerCertificateValidationCallback = delegate { return true; };
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://miyoigo.yoigo.com");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
Console.Write(reader.ReadToEnd());
}
}
Thanks in advance ;)
try printing the InnerException property of the WebException, should provide a particular reason the negot failed
Console.WriteLine("Inner Exception");
Console.WriteLine(String.Concat(e.InnerException.StackTrace, e.InnerException.Message));
That code works fine for me exactly as you have it. My guess is that you've got something network related going on. Are you behind a proxy or firewall? Like Ray said in his comment, try hitting that URL from a browser.
I have resolved my problem looking at:
How do you get a System.Web.HttpWebRequest object to use SSL 2.0?

Categories