Webclient using download file to grab file from server - handling exceptions
I have a web service in which I am manipulating POST and GET methods to facilitate upload / download functionality for some files in a client/server style architecture. Basically the user is able to click a button to download a 开发者_开发知识库specific file, make some changes in the app, then click upload button to send it back.
Problem I am having is with the download. Say the user expects 3 files 1.txt, 2.txt and 3.txt. Except 2.txt does not exist on the server.
So I have code like (on server side):
public class HttpHandler : IHttpHandler
{
public void ProcessRequest
{
if (context.Request.HttpMethod == "GET")
{
GoGetIt(context)
}
}
private static void GoGetIt(HttpContext context)
{
var fileInfoOfWhereTheFileShouldBe = new FileInfo(......);
if (!fileInfoOfWhereTheFileShouldBe.RefreshExists())
{
//Remove this line below
//throw new Exception("Oh dear the file doesn't exist");
//Replace with a force return of whichever code I chose e.g. 200
??...
}
...
So the problem I have is that when I run the application, and I use a WebClient on client side to use DownloadFile method which then uses the code I have above, I get:
WebException was unhandled: The remote server returned an error: (500) Internal Server Error.
(While debugging) If I attach to the browser and use http://localhost:xxx/1.txt
I can step through server side code and throw the exception as intended. So I guess I'm wondering how I can handle the internal server error on the client side properly so I can return something meaningful like "File doesn't exist". One thought was to use a try catch around the WebClient.DownloadFile(address, filename)
method but i'm not sure thats the only error that will occur i.e. the file doesn't exist.
edit: following the solution using HttpResponse
So if I were to use HttpResponse, could I get some suggestions as how to start?
I remove the exception throw from the client side, and replace with custom HttpResponse? So basically I guess I would chose a code to use, say 200, and force return code 200 in that if statement above. See comment.
Then on client side just use If (Response.StatusCode == 200)
and do whatever I want to do (inform user file doesn't exist )
I'm along the right lines?
edit 2:
I've been trying using a try catch around my file copy methods, then in the catch, setting the status code or status description but this throws exceptions when setting the status description.. like this:
context.Response.StatusDescription = ex.ToString();
context.Response.Status = ex.ToString();
ArgumentOutOfRangeException - specified argument was out of the range of valid values.
If you're programming the IHttpHandler
interface you shouldn't throw exceptions on that code. Never!
Instead use the Response.StatusCode
and Response.StatusDescription
to return meaningful information to the client.
Let the throwing exception only to the system because then, it will REALLY be an exception to YOUR code.
Edited to add
Answering to your edit, the way I'd do it would be to in case of a file not found on the server side would return a 404
Status Code. And let the client handle this.
However, as you have put you're dealing with an web service, so, I'd simply add some additional response in the headers in order to better specify what really is going on the server side to your client application.
Edited to Add
Response.Status
is and integer. That's why you're getting the ArgumentOutOfRangeException
.
Make sure that Status is one of the valid HTTP return codes.
Instead of throwing the exception, Log the exception in a text file or event log so that you can see exactly what happened when the error occur.
Here is sample code for event logging http://support.microsoft.com/kb/307024. For saving in the text file
public void WriteExceptionToDisk(Exception exceptionLog)
{
string loggingname = @"c:\Exception-" + DateTime.Today.Month.ToString()
+ "-" + DateTime.Today.Day.ToString() + "-" +
DateTime.Today.Year.ToString() + ".txt";
// Put the exception some where in the server but
// make sure Read/Write permission is allowed.
StringBuilder message = new StringBuilder();
if (exceptionLog != null)
{
message.Append("Exception Date and Time ");
message.AppendLine();
message.Append(" ");
message.Append(DateTime.Today.ToLongDateString() + " at ");
message.Append(DateTime.Now.ToLongTimeString());
message.AppendLine();
message.Append("Exception Message ");
message.AppendLine(); message.Append(" ");
message.Append(exceptionLog.Message);
message.AppendLine();
message.AppendLine("Exception Detail ");
message.AppendLine();
message.Append(exceptionLog.StackTrace);
message.AppendLine();
}
else if (message == null || exceptionLog == null)
{
message.Append("Exception is not provided or is set as null.Please pass the exception.");
}
if (File.Exists(loggingname))// If logging name exists, then append the exception message
{
File.AppendAllText(loggingname, message.ToString());
}
else
{
// Then create the file name
using (StreamWriter streamwriter = File.CreateText(loggingname))
{
streamwriter.AutoFlush = true;
streamwriter.Write(message.ToString());
streamwriter.Close();
}
}
}
精彩评论