Windows 7 SP1.
Domain network.
.NET Framework 4.6.1.
All my Internet browsers have configured proxy settings for Internet connections (it works fine).
I need to download file from Internet. I configure WebClient for it will read proxy settings from default Internet browser and use credential of current process and I expected these conditions are enough for successfull downloading. But I get the exception (look the comment in my code):
static void Main(string[] args) {
String file_name = Path.GetRandomFileName();
String full_path = Environment.ExpandEnvironmentVariables(
Path.Combine(#"%LocalAppData%\Temp", file_name));
using (WebClient client = new WebClient()) {
client.Credentials = CredentialCache.DefaultCredentials;
//client.Proxy = WebRequest.GetSystemWebProxy();
var proxyUri = WebRequest.GetSystemWebProxy()
.GetProxy(new Uri("https://yadi.sk/i/jPScGsw9qiSXU"));
try {
client.DownloadFile(proxyUri, full_path);
}
catch (Exception ex) {
// The remote server returned an error: (502) Bad Gateway.
Console.WriteLine(ex.Message);
}
}
Console.WriteLine("Press any key for exit.");
Console.ReadKey();
}
What I did wrong?
You need to retrieve the proxy for the specific URL then set it as the proxy URL of the web request.
static void Main(string[] args) {
String file_name = Path.GetRandomFileName();
String full_path = Environment.ExpandEnvironmentVariables(
Path.Combine(#"%LocalAppData%\Temp", file_name));
using (WebClient client = new WebClient()) {
client.Credentials = CredentialCache.DefaultCredentials;
var proxyUri = WebRequest.GetSystemWebProxy()
.GetProxy(new Uri("https://yadi.sk/i/jPScGsw9qiSXU"));
client.Proxy = new WebProxy(proxyUri);
client.Proxy.Credentials = CredentialCache.DefaultCredentials;
try {
client.DownloadFile("https://yadi.sk/i/jPScGsw9qiSXU", full_path);
}
catch (Exception ex) {
// The remote server returned an error: (502) Bad Gateway.
Console.WriteLine(ex.Message);
}
}
Console.WriteLine("Press any key for exit.");
Console.ReadKey();
}
This is implemented just in case the proxy uri is different depending on the url you are trying to access.
Related
I have a Xamarin Android app that has a feature for taking snapshots of external cameras. Until now we were using some models that provided us access from HTTP with CGI for this.
However, these models were discontinuated and we are forced to change for models that provide ONVIF protocol.
I created an additional ClassLibrary project in my solution (once it is not possible to add Services References directly in Xamarin Android projects) to handle this function. And in this project I added a Service Reference to ONVIF wsdl (http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl).
So, I created the following function:
public string GetSnapshotUri(string cameraIPAddress, string username, string password)
{
try
{
var messageElement = new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
};
HttpTransportBindingElement httpBinding = new HttpTransportBindingElement()
{
AuthenticationScheme = AuthenticationSchemes.Basic
};
CustomBinding bind = new CustomBinding(messageElement, httpBinding);
var mediaClient = new MediaClient(bind, new EndpointAddress($"http://{ cameraIPAddress }/onvif/Media"));
mediaClient.ClientCredentials.UserName.UserName = username;
mediaClient.ClientCredentials.UserName.Password = password;
Profile[] profiles = mediaClient.GetProfiles();
string profileToken = profiles[0].token;
MediaUri mediaUri = mediaClient.GetSnapshotUri(profileToken);
return mediaUri.Uri;
}
catch (WebException ex)
{
return ex.Message;
}
catch (Exception ex)
{
return ex.Message;
}
}
But when the function is called and the mediaClient.GetProfiles() method is reached, an error is thrown:
**
System.Net.WebException: 'There was an error on processing web
request: Status code 400(BadRequest): Bad Request'
**
see error message
I've tried to search for any related problem, but everything I've tried didn't work.
Any suggestions?
Link related: ONVIF api capture image in C#
Thanks!
After a long time, I finally had success.
Here is the final solution:
public Byte[] GetSnapshotBytes(string ip, string user, string password)
{
try
{
if (string.IsNullOrEmpty(ip)) return null;
var snapshotUri = string.Format("http://{0}:80/onvifsnapshot/media_service/snapshot?channel=1&subtype=0", ip);
NetworkCredential myCredentials = new NetworkCredential(user, password);
WebRequest myWebRequest = WebRequest.Create(snapshotUri);
myWebRequest.Credentials = myCredentials.GetCredential(new Uri(snapshotUri), "");
using (HttpWebResponse lxResponse = (HttpWebResponse)myWebRequest.GetResponse())
{
using (BinaryReader reader = new BinaryReader(lxResponse.GetResponseStream()))
{
Byte[] lnByte = reader.ReadBytes(1 * 1024 * 1024 * 10);
return lnByte;
}
}
}
catch (Exception)
{
throw;
}
}
I am sending a request to third party website by PostAsJsonAsync as below:
var nbParamsJson = Newtonsoft.Json.JsonConvert.SerializeObject(nbParams);
var httpContent = new StringContent(nbParamsJson);
try
{
var response = await client.PostAsJsonAsync(siteUrl, httpContent);
}
catch (Exception exp)
{
}
which throws an exception: [The request was aborted: Could not create SSL/TLS secure channel.]
I know my website in test environment does not have a SSL certificate and probably is happening because the third-party website has SSL certificate.
I want to know is there any way to create SSL channel without moving to SSL.
I just added
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
before PostAsJsonAsync and it solved my issue.
I'm not sure of your async, but here is an adaptation from working code to send JSON data to an SSL website that you should be able to adapt to your specific case:
var baseurl = "https://example.com/api/upload/123";
var rqst = (HttpWebRequest)WebRequest.Create(baseurl);
rqst.Method = "PUT";
rqst.Accept = "application/json";
var authInfo = "authtoken";
rqst.Headers["Authorization"] = "Token " + authInfo;
rqst.UserAgent = "curl/7.37.0";
rqst.ContentType = "application/json; charset=utf-8";
using (var streamWriter = new StreamWriter(rqst.GetRequestStream()))
{
streamWriter.Write(GetJsonData());
}
try
{
var resp = rqst.GetResponse();
using (var sr = new StreamReader(resp.GetResponseStream() ?? throw new InvalidOperationException()))
{
var txt = sr.ReadToEnd();
textBox1.Text = txt;
}
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
I am trying to download a xml file from an url but I get this error:
"The remote server returned an error (401) unauthorized". Also, this webpage needs some credentials.
I searched on different topics before coming to ask you, but I didn't find a solution to this...
Here are two versions of codes I tried but didn't work:
try
{
WebClient wClient = new WebClient();
wClient.Credentials = new NetworkCredential(nni, pwd);
var dlString = wClient.DownloadString(url);
//Stream data = wClient.OpenRead(url);
//var reader = new XmlTextReader(wClient.OpenRead(url));
//doc.LoadXml();
doc.Load(wClient.OpenRead(url));
Console.WriteLine(doc.InnerText);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(xmlUrl);
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(nni, pwd);
string htmlCode = client.DownloadString(xmlUrl);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Can you guys please help me on this?
I am using the below code to send push notifications from my WCF web service
using (var wc = new WebClient())
{
wc.Headers.Add("Authorization", "Key=" + ConfigurationSettings.AppSettings["apiKey"]);
var nameValues = new NameValueCollection
{
{"registration_id", objSendNotificationBE.RegistrationID},
{"collapse_key", Guid.NewGuid().ToString()},
{"data.payload", objSendNotificationBE.Message}
};
var resp = wc.UploadValues("https://android.googleapis.com/gcm/send", nameValues);
respMessage = Encoding.Default.GetString(resp);
if (respMessage == "Error=InvalidRegistration")
{
string respMessage = "";
}
}
It's working fine but sometimes I am getting the exception
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.WebClient.UploadValues(Uri address, String method, NameValueCollection data)
at System.Net.WebClient.UploadValues(String address, NameValueCollection data)
I have deployed my web service on azure server.
You are sending a request to a site that uses SSL/TLS i.e. starts with https. Like you alluded to in your comment, you need to configure your web client to use SSL/TLS. You need to figure out whether the remote server you are trying to reach uses SSL or TLS then use the correct security mode.
You can see this answered in this question.
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
class Program
{
static void Main(string[] args)
{
Uri address = new Uri("https://archive.org/details/OTRR_In_The_Name_Of_The_Law_Singles");
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 ;
using (WebClient webClient = new WebClient())
{
var stream = webClient.OpenRead(address);
using (StreamReader sr =new StreamReader(stream))
{
var page = sr.ReadToEnd();
}
}
}
/// <summary>
/// Certificate validation callback.
/// </summary>
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
// If the certificate is a valid, signed certificate, return true.
if (error == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
Console.WriteLine("X509Certificate [{0}] Policy Error: '{1}'",
cert.Subject,
error.ToString());
return false;
}
}
Hi guys need help i am trying to make a console application which checks whether a website is available or not. Also i am trying to get the title of the page.
For doing this i am using HttpWebRequest Class (for getting status) and WebClient class (for getting title).
Note: The page i am trying to get is on a private server.
URl format is (applicationname-environment.corporation.companyname.com)
example: FIFO-dev.corp.tryit.com
When i try to get the status it is always giving me 401 as its status even though the page is up and running
List<int> Web_Status = new List<int>();
foreach (var URL in WEB_URL)
{
try
{
HttpWebRequest Web_Test = (HttpWebRequest)WebRequest.Create("http://" + URL);
Web_Test.AllowAutoRedirect = true;
HttpWebResponse Web_response = (HttpWebResponse)Web_Test.GetResponse();
Web_Status.Add((int)Web_response.StatusCode);
Web_response.Close();
}
catch (System.Net.WebException ex)
{
HttpWebResponse Web_response = (HttpWebResponse)ex.Response;
Web_Status.Add((int)Web_response.StatusCode);
}
}
Also note while giving url's i am making sure that i am not reentering http://.
The below code is giving this error
"System.Net.WebException: The remote server returned an error: (401)
Unauthorized.
at System.Net.WebClient.DownloadDataInternal(Uri address,
WebRequest& request)
at System.Net.WebClient.DownloadString(Uri address)
at website_monitoring.Get_Title.Title(List`1 WEB_URL) in "
string source = "";
List<string> status = new List<string>();
WebClient x = new WebClient();
foreach (var item in WEB_URL)
{
try
{
source = x.DownloadString("http://" + item);
status.Add(Regex.Match(source, #"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value);
}
catch (System.Net.WebException ex)
{
status.Add(ex.ToString());
}
}
Sorry guys i cant give the exact url i am trying on.
This code is working with all the common websites and blogs like
"stackoverflow.com","http://understandingarduino.blogspot.in/" and so
on.
Update 1: following mammago suggestion i was able to handle 4xx issue but now it is giving too many redirects issues while getting title.
i was able to handle 302 status issue by autoredirect property to 1000;
List<int> Web_Status = new List<int>();
foreach (var URL in WEB_URL)
{
try
{
HttpWebRequest Web_Test = (HttpWebRequest)WebRequest.Create("http://" + URL);
// Set credentials to use for this request.
Web_Test.Credentials = CredentialCache.DefaultCredentials;
Web_Test.CookieContainer = new CookieContainer();
Web_Test.AllowAutoRedirect = true;
Web_Test.MaximumAutomaticRedirections = 1000;
//Web_Test.UserAgent =
HttpWebResponse Web_response = (HttpWebResponse)Web_Test.GetResponse();
Web_Status.Add((int)Web_response.StatusCode);
Web_response.Close();
}
catch (System.Net.WebException ex)
{
HttpWebResponse Web_response = (HttpWebResponse)ex.Response;
Web_Status.Add((int)Web_response.StatusCode);
}
}
Now all i need help is how to handle auto- redirect issue in this segment
string source = "";
List<string> status = new List<string>();
WebClient x = new WebClient();
//letting the website know its a known user who is accessing it (as if website have auto authentication)
x.Credentials = CredentialCache.DefaultCredentials;
foreach (var item in WEB_URL)
{
try
{
source = x.DownloadString("http://" + item);
status.Add(Regex.Match(source, #"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value);
}
catch (System.Net.WebException ex)
{
status.Add(ex.ToString());
//source = x.DownloadString("http://" + ex);
//status.Add(Regex.Match(source, #"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value);
}
}
"System.Net.WebException: Too many automatic redirections were
attempted. at System.Net.WebClient.DownloadDataInternal(Uri
address, WebRequest& request) at
System.Net.WebClient.DownloadString(Uri address)