C# FtpWebRequest Error 403 - c#

I have the following code to retrieve a file via FTP:
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath);
request.KeepAlive = true;
request.UsePassive = true;
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(username, password);
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
using (StreamWriter destination = new StreamWriter(destinationFile))
{
destination.Write(reader.ReadToEnd());
destination.Flush();
}
return 0;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
This works in most cases, but I have one client machine where I get an exception:
The remote server returned an error 403: Forbidden
Can anyone tell me why this could be the case? It’s exactly the same code running on all clients (including the same username and password)?

I've encountered the same problem.
I have already done some monitoring.
First I monitored communications for FTP connection via TotalCommander (It works, so it is a good reference). After that I also monitored my program. I was shocked by what was happening.
Somehow HTTP request was sent by an FTPRequest instance! I haven't solved the problem yet, but I am getting closer. I'll inform you if I find out anything new yet.
The solution was very simple for me. I just added the following line, after creating the request instance:
request.Proxy = null;

The only thing I can suggest is installing Wireshark and monitoring exactly what's being transmitted between the client and server, and comparing that between different machines. If necessary, to get the messages more similar between FTP and IE, change the request's user agent. Is there any funky networking going on, like IP-based permissions?

Related

Upload to FTP, not using anonymous C#

I used the following example code to upload to an FTP, it turns out that the server don't want to use anonymous connection, but I can't figure out how to change it to be able to upload with out breaking that rule.
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("username", "password");
// Copy the contents of the file to the request stream.
byte[] fileContents;
using (StreamReader sourceStream = new StreamReader(file))
{
fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
}
request.ContentLength = fileContents.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileContents, 0, fileContents.Length);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
}
Anonymous credentials are still credentials. You can get rid of them by removing the line
request.Credentials = new NetworkCredential("username", "password");
and you won't be sending any credentials to the server at all.
Nevertheless, as mentioned in "Remarks" section of the MSDN docs, FtpWebRequest class is not recommended to be used for new development. Microsoft recommends to use one of third-party libraries listed here.
I also recommend choosing one of those, as they provide more robust way to communicate with FTP servers. You can enable logging and it will be easier for you to see why exactly your communication with the server is failing. You will see all the commands your app is sending to the server and also all the responses from the server. These libraries also implement all the basic operations like listing, downloading, uploading, permission setting, sync/async etc, so you don't have to write them yourself.

Ftp requests in Windows Service Timing out

I have windows service that periodically upload file upload file on an FTP server. I have set,
ServicePointManager.DefaultConnectionLimit = 100;
and I have,
public void MyMethod(string url,
string userName,
string password)
{
try
{
var request = (FtpWebRequest) WebRequest.Create(url);
request.Timeout = GetFtpTimeoutInMinutes()*60*1000;
request.Credentials = new NetworkCredential(userName, password);
request.Method = method;
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = false;
request.GetResponse();
}
catch (Exception ex)
{
_logger.Log(ex);
}
Its work fine for 100 or more request but after 100 or more I am continuously getting,
System.Net.WebException: The operation has timed out.
at System.Net.FtpWebRequest.CheckError()
at System.Net.FtpWebRequest.GetResponse()
Why this is happening.
Update: I am thinking to move in http
request.GetResponse();
Your snippet is very incomplete, but surely the problem started here. GetResponse() returns an FtpWebResponse object, it is crucial that your code calls Close() or disposes it to ensure that the Ftp connection is closed.
If you forget then you will have 100 active connections after downloading 100 files and trip the ServicePointManager.DefaultConnectionLimit. The garbage collector doesn't run often enough to keep you out of trouble. After which any subsequent downloads will die with a timeout. Fix:
using (var response = request.GetResponse()) {
// Do stuff
//...
}
Which uses the reliable way to ensure that the connection will be closed, even if the code falls over with an exception. If you still have trouble then diagnose with, say, SysInternals' TcpView utility. It is a good way to see active connections.

"Hostname could not be parsed" From "ftp" URL

I just purchased some online storage from GoDaddy and I an trying to FTP into my storage account. The thing is, I can view and modify my account using FileZilla, but my C Sharp program will not even access it because of the "hostname could not be parsed" error.
I believe it is because the entire ftp address of my account has two "#" signs in the url, and it is the wreaking havoc in the URI creation process.
Is there anyway I can get around this, or am I screwed because of the naming convention of the GoDaddy storage?
The URL is: ftp:[slashslash]lastname.firstname#gmail.com#onlinefilefolder.com/Home/
Do you need to specify the username and password in the URI for some specific reason? You can simply connect to the host and then provide credentials.
// Create a request to the host
var request = (FtpWebRequest)WebRequest.Create("ftp://onlinefilefolder.com");
// Set the username and password to use
request.Credentials = new NetworkCredential ("lastname.firstname#gmail.com","password");
request.Method = WebRequestMethods.Ftp.UploadFile;
var sourceStream = new StreamReader("testfile.txt");
var fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
response.Close();
The exception is originating from System.Uri, which (despite it being acceptable by the standards definition) will not allow two # symbols.
// This will reproduce the reported exception, I assume it is what your code is
// doing either explicitly, or somewhere internally
new Uri(#"ftp://lastname.firstname#gmail.com#onlinefilefolder.com/Home/")
A potential workaround is to percent-encode the first # symbol, which will allow the Uri instance to be instantiated without exception--but may or may not work depending on the server's behavior (I have only used this approach a couple times, but it has worked for me):
new Uri(#"ftp://lastname.firstname%40gmail.com#onlinefilefolder.com/Home/")

The remote server returned an error: (407) Proxy Authentication Required

I referred several websites, which had answer for this question
"The remote server returned an error: (407) Proxy Authentication Required." ,but none were helpful.
I wrote a sample code to check the proxy authentication in office. The code throws exception.
My requirement:- Verify what the website returns. Outside office, the code works fine, but in office it throws an exception due to proxy.
When I hardcode the credentials using new NetworkCredential, it works fine.
int ResponseCode;
string url = "http://www.msftncsi.com/ncsi.txt";
WebRequest request = WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultCredentials;
using (WebResponse response = request.GetResponse())
{
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
ResponseCode = (int)((HttpWebResponse)response).StatusCode;
reader.Close();
}
I do not want to Hardcode. I referred the solution in http://social.msdn.microsoft.com/Forums/is/csharpgeneral/thread/c06d3032-dceb-4a1a-bb6a-778fd13a938a, but even that didnt help.
What am I missing?
I had the same issue, this did the trick for me
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
There are many things here. You can try setting Credentials explicitly
request.Credentials = new NetworkCredentials(username, password)
You might need to specify proxy. By default it uses your IE proxy. You might not want that
WebRequest webRequest = WebRequest.Create("http://stackoverflow.com/");
webRequest.Proxy = new WebProxy("http://proxyserver:80/",true);

Difficulty with BugzScout.net from behind a proxy

I'm attempting to use Fogbugz's BugzScout in order to automatically submit unhanded application exceptions to my Fogbugz on demand Account. I've written up a wrapper class for it and everything appears to be just groovy - on my box. Testing the same code in the production environment, behind a Proxy that requires authentication, I have had nothing but issues.
I went to work modifying the BugzScout code in order to get it to authenticate with the Proxy, and after trying many different methods suggested via a Google search, found one that works! But now I'm getting an "Connection actively refused" error from Fogbugz itself, and I don't know what to do.
Here is the code where the BugzScout connects via a .net WebClient to submit a new case, with my modifications to deal with our Proxy. What am I doing that would cause Fogbugz to refuse my request? I've removed all non web-client related code from the procedure for ease of reading.
public string Submit(){
WebClient client = new WebClient();
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Byte[] response = client.DownloadData(fogBugzUrl);
string responseText = System.Text.Encoding.UTF8.GetString(response);
return (responseText == "") ? this.defaultMsg : responseText;
}
The url is correct and the case is filled in properly- this has been verified.
EDIT: Additional info.
Using Fogbugz on Demand.
Using FogBugz.net code in it's entirety, with only these additions
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Error occurs when attempting to connect to both https://oursite.fogbugz.com/scoutsubmit.asp and http://oursite.fogbugz.com//scoutsubmit.asp (except one says port 443, and the other port 80, obviously)
I don't know anything about web authentication so I can't tell you what kind I'm using- if you tell me where to look I'd be happy to answer that for you.
Got the fix from Fogbugz- this is the appropriate network code to get though the proxy authentication and not mis-authenticate with Bugzscout.
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
WebRequest request = WebRequest.Create(fogBugzUrl);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
Is your fogbugzUrl using HTTP Basic Authentication? Is it SSL (hosted on On Demand?)
The connection actively refused message would be coming from the web server itself, not really FogBugz.
Can you post the HTTP Status Code?
One thing to note if you are using FogBugz On Demand is you HAVE to use the https:// url (not the http url).

Categories