There are many posts on WebResponse 403 error but my situation is a little different. I have created a console application that will run as a task on my server. The console application passes user emails in WebRequest and waits for WebResponse to receive the uri with the returning parameters. The code below worked perfectly a few days ago but one of the other programmers added a new parameter for a return web address. I know for a fact that this is causing the 403 error because if I paste the uri in IE with new parameter it works. But since I have a console application a return web address is something I cannot do, at least I don't think so.
Unfortunately the programmer said that he cannot change it back and said that there is a way to receive the uri or the entire page content and I can process it that way. I still have no clue what he was talking about because StreamReader requires a WebResponse and pretty much all other solutions I could think of.
Even though I get a 403 error the response still has the uri with the parameters I need because I can see it in IE in the web address. So all I need is the response uri. I would appreciate any help you have to offer. Below is the method giving me problems.
String employeeInfo = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest
.Create("http://example.com/subsub.aspx?instprod=xxx&vabid=emailaddress");
using (HttpWebResponse webResponse =
(HttpWebResponse)request.GetResponse()) //Error occurs here. 403 Forbidden
{
Uri myUri = new Uri(webResponse.ResponseUri.ToString());
String queryParamerter = myUri.Query;
employeeInfo = HttpUtility.ParseQueryString(queryParamerter).Get("vres");
if (employeeInfo != "N/A")
{
return employeeInfo;
}
else
{
employeeInfo = "0";
return employeeInfo;
}
}
}
catch (WebException)
{
employeeInfo = "0";
return employeeInfo;
}
Let's follow Jim Mischel's idea. We'll handle the WebException and use the Response property of the exception.
String employeeInfo = "";
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://example.com/subsub.aspx?instprod=xxx&vabid=emailaddress");
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse()) //Error occurs here. 403 Forbidden
{
Uri myUri = new Uri(webResponse.ResponseUri.ToString());
String queryParamerter = myUri.Query;
employeeInfo = HttpUtility.ParseQueryString(queryParamerter).Get("vres");
if (employeeInfo != "N/A")
{
return employeeInfo;
}
else
{
employeeInfo = "0";
return employeeInfo;
}
}
}
catch (WebException ex)
{
HttpWebResponse response = ex.Response as HttpWebResponse;
if(response.StatusCode != HttpStatusCode.Forbidden)
{
throw;
}
Uri myUri = new Uri(response.ResponseUri.ToString());
String queryParamerter = myUri.Query;
employeeInfo = HttpUtility.ParseQueryString(queryParamerter).Get("vres");
if (employeeInfo != "N/A")
{
return employeeInfo;
}
else
{
employeeInfo = "0";
return employeeInfo;
}
}
Related
I am using the WebClient class to post some data to a web form. I would like to get the response status code of the form submission. So far I've found out how to get the status code if there is a exception
Catch wex As WebException
If TypeOf wex.Response Is HttpWebResponse Then
msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode)
End If
However if the form is submitted successfully and no exception is thrown then I won't know the status code(200,301,302,...)
Is there some way to get the status code when there is no exceptions thrown?
PS: I prefer not to use httpwebrequest/httpwebresponse
You can check if the error is of type WebException and then inspect the response code;
if (e.Error.GetType().Name == "WebException")
{
WebException we = (WebException)e.Error;
HttpWebResponse response = (System.Net.HttpWebResponse)we.Response;
if (response.StatusCode==HttpStatusCode.NotFound)
System.Diagnostics.Debug.WriteLine("Not found!");
}
or
try
{
// send request
}
catch (WebException e)
{
// check e.Status as above etc..
}
There is a way to do it using reflection. It works with .NET 4.0. It accesses a private field and may not work in other versions of .NET without modifications.
I have no idea why Microsoft did not expose this field with a property.
private static int GetStatusCode(WebClient client, out string statusDescription)
{
FieldInfo responseField = client.GetType().GetField("m_WebResponse", BindingFlags.Instance | BindingFlags.NonPublic);
if (responseField != null)
{
HttpWebResponse response = responseField.GetValue(client) as HttpWebResponse;
if (response != null)
{
statusDescription = response.StatusDescription;
return (int)response.StatusCode;
}
}
statusDescription = null;
return 0;
}
If you are using .Net 4.0 (or less):
class BetterWebClient : WebClient
{
private WebRequest _Request = null;
protected override WebRequest GetWebRequest(Uri address)
{
this._Request = base.GetWebRequest(address);
if (this._Request is HttpWebRequest)
{
((HttpWebRequest)this._Request).AllowAutoRedirect = false;
}
return this._Request;
}
public HttpStatusCode StatusCode()
{
HttpStatusCode result;
if (this._Request == null)
{
throw (new InvalidOperationException("Unable to retrieve the status
code, maybe you haven't made a request yet."));
}
HttpWebResponse response = base.GetWebResponse(this._Request)
as HttpWebResponse;
if (response != null)
{
result = response.StatusCode;
}
else
{
throw (new InvalidOperationException("Unable to retrieve the status
code, maybe you haven't made a request yet."));
}
return result;
}
}
If you are using .Net 4.5.X or newer, switch to HttpClient:
var response = await client.GetAsync("http://www.contoso.com/");
var statusCode = response.StatusCode;
Tried it out. ResponseHeaders do not include status code.
If I'm not mistaken, WebClient is capable of abstracting away multiple distinct requests in a single method call (e.g. correctly handling 100 Continue responses, redirects, and the like). I suspect that without using HttpWebRequest and HttpWebResponse, a distinct status code may not be available.
It occurs to me that, if you are not interested in intermediate status codes, you can safely assume the final status code is in the 2xx (successful) range, otherwise, the call would not be successful.
The status code unfortunately isn't present in the ResponseHeaders dictionary.
Erik's answer doesn't work on Windows Phone as is. The following does:
class WebClientEx : WebClient
{
private WebResponse m_Resp = null;
protected override WebResponse GetWebResponse(WebRequest Req, IAsyncResult ar)
{
try
{
this.m_Resp = base.GetWebResponse(request);
}
catch (WebException ex)
{
if (this.m_Resp == null)
this.m_Resp = ex.Response;
}
return this.m_Resp;
}
public HttpStatusCode StatusCode
{
get
{
if (m_Resp != null && m_Resp is HttpWebResponse)
return (m_Resp as HttpWebResponse).StatusCode;
else
return HttpStatusCode.OK;
}
}
}
At least it does when using OpenReadAsync; for other xxxAsync methods, careful testing would be highly recommended. The framework calls GetWebResponse somewhere along the code path; all one needs to do is capture and cache the response object.
The fallback code is 200 in this snippet because genuine HTTP errors - 500, 404, etc - are reported as exceptions anyway. The purpose of this trick is to capture non-error codes, in my specific case 304 (Not modified). So the fallback assumes that if the status code is somehow unavailable, at least it's a non-erroneous one.
You should use
if (e.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
if (response.StatusCode == HttpStatusCode.NotFound)
System.Diagnostics.Debug.WriteLine("Not found!");
}
This is what I use for expanding WebClient functionality. StatusCode and StatusDescription will always contain the most recent response code/description.
/// <summary>
/// An expanded web client that allows certificate auth and
/// the retrieval of status' for successful requests
/// </summary>
public class WebClientCert : WebClient
{
private X509Certificate2 _cert;
public WebClientCert(X509Certificate2 cert) : base() { _cert = cert; }
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
if (_cert != null) { request.ClientCertificates.Add(_cert); }
return request;
}
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = null;
response = base.GetWebResponse(request);
HttpWebResponse baseResponse = response as HttpWebResponse;
StatusCode = baseResponse.StatusCode;
StatusDescription = baseResponse.StatusDescription;
return response;
}
/// <summary>
/// The most recent response statusCode
/// </summary>
public HttpStatusCode StatusCode { get; set; }
/// <summary>
/// The most recent response statusDescription
/// </summary>
public string StatusDescription { get; set; }
}
Thus you can do a post and get result via:
byte[] response = null;
using (WebClientCert client = new WebClientCert())
{
response = client.UploadValues(postUri, PostFields);
HttpStatusCode code = client.StatusCode;
string description = client.StatusDescription;
//Use this information
}
Just in case someone else needs an F# version of the above described hack.
open System
open System.IO
open System.Net
type WebClientEx() =
inherit WebClient ()
[<DefaultValue>] val mutable m_Resp : WebResponse
override x.GetWebResponse (req: WebRequest ) =
x.m_Resp <- base.GetWebResponse(req)
(req :?> HttpWebRequest).AllowAutoRedirect <- false;
x.m_Resp
override x.GetWebResponse (req: WebRequest , ar: IAsyncResult ) =
x.m_Resp <- base.GetWebResponse(req, ar)
(req :?> HttpWebRequest).AllowAutoRedirect <- false;
x.m_Resp
member x.StatusCode with get() : HttpStatusCode =
if not (obj.ReferenceEquals (x.m_Resp, null)) && x.m_Resp.GetType() = typeof<HttpWebResponse> then
(x.m_Resp :?> HttpWebResponse).StatusCode
else
HttpStatusCode.OK
let wc = new WebClientEx()
let st = wc.OpenRead("http://www.stackoverflow.com")
let sr = new StreamReader(st)
let res = sr.ReadToEnd()
wc.StatusCode
sr.Close()
st.Close()
You should be able to use the "client.ResponseHeaders[..]" call, see this link for examples of getting stuff back from the response
You can try this code to get HTTP status code from WebException or from OpenReadCompletedEventArgs.Error. It works in Silverlight too because SL does not have WebExceptionStatus.ProtocolError defined.
HttpStatusCode GetHttpStatusCode(System.Exception err)
{
if (err is WebException)
{
WebException we = (WebException)err;
if (we.Response is HttpWebResponse)
{
HttpWebResponse response = (HttpWebResponse)we.Response;
return response.StatusCode;
}
}
return 0;
}
I have a console application for the 2.0 framework in C#, using vs
2005. This is weird, the exact same code I have worked on both my pc and the server(using webservice).
When I execute HttpWebRequest.GetResponse on URL, First one(pc)
works well but last one(webservice) returns an error :
(404) Not Found. The URL is a trusted site.
Internet sites and local intranet sites are detected successfully.
But trusted sites only could not be detected.
I don't know why?
This is the code:
private bool getSiteConnStatus(string url)
{
bool result = true;
Uri uri = new Uri(url);
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
WebProxy SCProxy = new WebProxy("123.123.123.123");
SCProxy.Credentials = new NetworkCredential();
request.Proxy = SCProxy;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response == null || response.StatusCode != HttpStatusCode.OK)
{
result = false;
}
response.Close();
}
catch (Exception ex)
{
result = false;
}
return result;
}
~~~~~~~~~~
I've solved.
The Proxy information was changed whenever each site called. So I added some lines below.
Reference site
private bool getSiteConnStatus(string url)
{
bool result = true;
Uri uri = new Uri(url);
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
***WebProxy SCProxy;
if (request.Address.Host == "test.net")
{
SCProxy = new WebProxy("111.111.111.111", 8080);
}
else
{
SCProxy = new WebProxy("123.123.123.123", true);
}
request.Proxy = SCProxy;***
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response == null || response.StatusCode != HttpStatusCode.OK)
{
result = false;
}
response.Close();
}
catch (Exception ex)
{
result = false;
}
return result;
}
Try Accessing your url from Browser (on-server) - If it works your browser agent is configured to make communication to/from given ports to the outside world.
Check your firewall policies and any specific user-agent strings they are preventing to make connections to the out-side world ?
Also verify your Proxy Authentication , if you try it from the browser (i presume here its IE ) . browser might supply it automatically / NTLM Authentication strings. where your program might not be able to ?
In a web application I have to first check if an image exists and then display this image or a dummy image.
I use the following code and it works for URLS like:
"http://www.somedomain.com/niceimage.png"
"https://www.somedomain.com/niceimage.png".
public virtual bool WebResourceExists(string url)
{
WebHeaderCollection headers = null;
WebResponse response = null;
try
{
WebRequest request = WebRequest.Create(url);
request.Method = "HEAD";
response = request.GetResponse();
headers = response.Headers;
bool result = int.Parse(headers["Content-Length"]) > 0;
return result;
}
catch (System.Net.WebException)
{
return false;
}
catch (Exception e)
{
_log.Error(e);
return false;
}
finally
{
if (response != null)
{
response.Close();
}
}
}
In some places the the method is called with protocol agnostic urls like "//www.somedomain.com/niceimage.png".
There is an exception thrown for such urls:
System.InvalidCastException: Unable to cast object of type
'System.Net.FileWebRequest' to type 'System.Net.HttpWebRequest'
Is there a way to use protocol agnostic urls other then just prepending "http:" to the url?
Protocol-agnostic URLs are resolved by the browser using the current protocol, and are used to avoid making HTTP requests from an HTTPS page.
Code executing on the server doesn't really have a concept of a "current protocol". Whilst ASP.NET can determine whether the current request was issued over HTTP or HTTPS, the WebRequest classes are not restricted to ASP.NET applications, so they cannot rely on this.
You will need to specify the protocol. Whether you use HTTP or HTTPS will depend on whether you're concerned about third-parties eavesdropping on the connection between your server and "www.somedomain.com".
What about a two step process, check for the http version, if it doesn't exist check for https. I've quickly hacked together a basic example of how this could work but am not able to properly test and check it so it might need some tidying up/refactoring!
public virtual bool WebResourceExists(string url)
{
WebHeaderCollection headers = null;
WebResponse response = null;
try
{
if (url.StartsWith(#"//") {
url = "http:";
}
WebRequest request = WebRequest.Create(url);
request.Method = "HEAD";
response = request.GetResponse();
headers = response.Headers;
bool result = int.Parse(headers["Content-Length"]) > 0;
return result;
}
catch (System.Net.WebException)
{
if (url.StartsWith(#"http://") {
url = url.Replace("http://","https://");
} else {
return false;
}
try {
WebRequest request = WebRequest.Create(url);
request.Method = "HEAD";
response = request.GetResponse();
headers = response.Headers;
bool result = int.Parse(headers["Content-Length"]) > 0;
return result;
}
catch (System.Net.WebException)
{
return false;
}
}
catch (Exception e)
{
_log.Error(e);
return false;
}
finally
{
if (response != null)
{
response.Close();
}
}
}
I am attempting to make a simple function that verifies that a specific file exists on a website.
The web request is set to head so I can get the file length instead of downloading the entire file, but I get "Unable to connect to the remote server" exception.
How can I verify a file exists on a website?
WebRequest w;
WebResponse r;
w = WebRequest.Create("http://website.com/stuff/images/9-18-2011-3-42-16-PM.gif");
w.Method = "HEAD";
r = w.GetResponse();
edit: My bad, turns out my firewall was blocking http requests after I checked the log.
It didnt prompt me for an exception rule so I assumed it was a bug.
I've tested this and it works fine:
private bool testRequest(string urlToCheck)
{
var wreq = (HttpWebRequest)WebRequest.Create(urlToCheck);
//wreq.KeepAlive = true;
wreq.Method = "HEAD";
HttpWebResponse wresp = null;
try
{
wresp = (HttpWebResponse)wreq.GetResponse();
return (wresp.StatusCode == HttpStatusCode.OK);
}
catch (Exception exc)
{
System.Diagnostics.Debug.WriteLine(String.Format("url: {0} not found", urlToCheck));
return false;
}
finally
{
if (wresp != null)
{
wresp.Close();
}
}
}
try it with this url: http://www.centrosardegna.com/images/losa/losaabbasanta.png then modify the image name and it will return false. ;-)
try
{
WebRequest request = HttpWebRequest.Create("http://www.microsoft.com/NonExistantFile.aspx");
request.Method = "HEAD"; // Just get the document headers, not the data.
request.Credentials = System.Net.CredentialCache.DefaultCredentials;
// This may throw a WebException:
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode == HttpStatusCode.OK)
{
// If no exception was thrown until now, the file exists and we
// are allowed to read it.
MessageBox.Show("The file exists!");
}
else
{
// Some other HTTP response - probably not good.
// Check its StatusCode and handle it.
}
}
}
catch (WebException ex)
{
// Cast the WebResponse so we can check the StatusCode property
HttpWebResponse webResponse = (HttpWebResponse)ex.Response;
// Determine the cause of the exception, was it 404?
if (webResponse.StatusCode == HttpStatusCode.NotFound)
{
MessageBox.Show("The file does not exist!");
}
else
{
// Handle differently...
MessageBox.Show(ex.Message);
}
}
I am using the WebClient class to post some data to a web form. I would like to get the response status code of the form submission. So far I've found out how to get the status code if there is a exception
Catch wex As WebException
If TypeOf wex.Response Is HttpWebResponse Then
msgbox(DirectCast(wex.Response, HttpWebResponse).StatusCode)
End If
However if the form is submitted successfully and no exception is thrown then I won't know the status code(200,301,302,...)
Is there some way to get the status code when there is no exceptions thrown?
PS: I prefer not to use httpwebrequest/httpwebresponse
You can check if the error is of type WebException and then inspect the response code;
if (e.Error.GetType().Name == "WebException")
{
WebException we = (WebException)e.Error;
HttpWebResponse response = (System.Net.HttpWebResponse)we.Response;
if (response.StatusCode==HttpStatusCode.NotFound)
System.Diagnostics.Debug.WriteLine("Not found!");
}
or
try
{
// send request
}
catch (WebException e)
{
// check e.Status as above etc..
}
There is a way to do it using reflection. It works with .NET 4.0. It accesses a private field and may not work in other versions of .NET without modifications.
I have no idea why Microsoft did not expose this field with a property.
private static int GetStatusCode(WebClient client, out string statusDescription)
{
FieldInfo responseField = client.GetType().GetField("m_WebResponse", BindingFlags.Instance | BindingFlags.NonPublic);
if (responseField != null)
{
HttpWebResponse response = responseField.GetValue(client) as HttpWebResponse;
if (response != null)
{
statusDescription = response.StatusDescription;
return (int)response.StatusCode;
}
}
statusDescription = null;
return 0;
}
If you are using .Net 4.0 (or less):
class BetterWebClient : WebClient
{
private WebRequest _Request = null;
protected override WebRequest GetWebRequest(Uri address)
{
this._Request = base.GetWebRequest(address);
if (this._Request is HttpWebRequest)
{
((HttpWebRequest)this._Request).AllowAutoRedirect = false;
}
return this._Request;
}
public HttpStatusCode StatusCode()
{
HttpStatusCode result;
if (this._Request == null)
{
throw (new InvalidOperationException("Unable to retrieve the status
code, maybe you haven't made a request yet."));
}
HttpWebResponse response = base.GetWebResponse(this._Request)
as HttpWebResponse;
if (response != null)
{
result = response.StatusCode;
}
else
{
throw (new InvalidOperationException("Unable to retrieve the status
code, maybe you haven't made a request yet."));
}
return result;
}
}
If you are using .Net 4.5.X or newer, switch to HttpClient:
var response = await client.GetAsync("http://www.contoso.com/");
var statusCode = response.StatusCode;
Tried it out. ResponseHeaders do not include status code.
If I'm not mistaken, WebClient is capable of abstracting away multiple distinct requests in a single method call (e.g. correctly handling 100 Continue responses, redirects, and the like). I suspect that without using HttpWebRequest and HttpWebResponse, a distinct status code may not be available.
It occurs to me that, if you are not interested in intermediate status codes, you can safely assume the final status code is in the 2xx (successful) range, otherwise, the call would not be successful.
The status code unfortunately isn't present in the ResponseHeaders dictionary.
Erik's answer doesn't work on Windows Phone as is. The following does:
class WebClientEx : WebClient
{
private WebResponse m_Resp = null;
protected override WebResponse GetWebResponse(WebRequest Req, IAsyncResult ar)
{
try
{
this.m_Resp = base.GetWebResponse(request);
}
catch (WebException ex)
{
if (this.m_Resp == null)
this.m_Resp = ex.Response;
}
return this.m_Resp;
}
public HttpStatusCode StatusCode
{
get
{
if (m_Resp != null && m_Resp is HttpWebResponse)
return (m_Resp as HttpWebResponse).StatusCode;
else
return HttpStatusCode.OK;
}
}
}
At least it does when using OpenReadAsync; for other xxxAsync methods, careful testing would be highly recommended. The framework calls GetWebResponse somewhere along the code path; all one needs to do is capture and cache the response object.
The fallback code is 200 in this snippet because genuine HTTP errors - 500, 404, etc - are reported as exceptions anyway. The purpose of this trick is to capture non-error codes, in my specific case 304 (Not modified). So the fallback assumes that if the status code is somehow unavailable, at least it's a non-erroneous one.
You should use
if (e.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse response = (HttpWebResponse)ex.Response;
if (response.StatusCode == HttpStatusCode.NotFound)
System.Diagnostics.Debug.WriteLine("Not found!");
}
This is what I use for expanding WebClient functionality. StatusCode and StatusDescription will always contain the most recent response code/description.
/// <summary>
/// An expanded web client that allows certificate auth and
/// the retrieval of status' for successful requests
/// </summary>
public class WebClientCert : WebClient
{
private X509Certificate2 _cert;
public WebClientCert(X509Certificate2 cert) : base() { _cert = cert; }
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
if (_cert != null) { request.ClientCertificates.Add(_cert); }
return request;
}
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = null;
response = base.GetWebResponse(request);
HttpWebResponse baseResponse = response as HttpWebResponse;
StatusCode = baseResponse.StatusCode;
StatusDescription = baseResponse.StatusDescription;
return response;
}
/// <summary>
/// The most recent response statusCode
/// </summary>
public HttpStatusCode StatusCode { get; set; }
/// <summary>
/// The most recent response statusDescription
/// </summary>
public string StatusDescription { get; set; }
}
Thus you can do a post and get result via:
byte[] response = null;
using (WebClientCert client = new WebClientCert())
{
response = client.UploadValues(postUri, PostFields);
HttpStatusCode code = client.StatusCode;
string description = client.StatusDescription;
//Use this information
}
Just in case someone else needs an F# version of the above described hack.
open System
open System.IO
open System.Net
type WebClientEx() =
inherit WebClient ()
[<DefaultValue>] val mutable m_Resp : WebResponse
override x.GetWebResponse (req: WebRequest ) =
x.m_Resp <- base.GetWebResponse(req)
(req :?> HttpWebRequest).AllowAutoRedirect <- false;
x.m_Resp
override x.GetWebResponse (req: WebRequest , ar: IAsyncResult ) =
x.m_Resp <- base.GetWebResponse(req, ar)
(req :?> HttpWebRequest).AllowAutoRedirect <- false;
x.m_Resp
member x.StatusCode with get() : HttpStatusCode =
if not (obj.ReferenceEquals (x.m_Resp, null)) && x.m_Resp.GetType() = typeof<HttpWebResponse> then
(x.m_Resp :?> HttpWebResponse).StatusCode
else
HttpStatusCode.OK
let wc = new WebClientEx()
let st = wc.OpenRead("http://www.stackoverflow.com")
let sr = new StreamReader(st)
let res = sr.ReadToEnd()
wc.StatusCode
sr.Close()
st.Close()
You should be able to use the "client.ResponseHeaders[..]" call, see this link for examples of getting stuff back from the response
You can try this code to get HTTP status code from WebException or from OpenReadCompletedEventArgs.Error. It works in Silverlight too because SL does not have WebExceptionStatus.ProtocolError defined.
HttpStatusCode GetHttpStatusCode(System.Exception err)
{
if (err is WebException)
{
WebException we = (WebException)err;
if (we.Response is HttpWebResponse)
{
HttpWebResponse response = (HttpWebResponse)we.Response;
return response.StatusCode;
}
}
return 0;
}