Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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();
            }                 
        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top