Веб-клиент использует загружаемый файл для захвата файла с сервера — обработка исключений

У меня есть веб-служба, в которой я манипулирую методами POST и GET, чтобы облегчить загрузку/выгрузку некоторых файлов в архитектуре клиент/сервер. По сути, пользователь может нажать кнопку, чтобы загрузить определенный файл, внести некоторые изменения в приложение, а затем нажать кнопку загрузки, чтобы отправить его обратно.

У меня проблема с загрузкой. Скажем, пользователь ожидает 3 файла 1.txt, 2.txt и 3.txt. За исключением того, что 2.txt не существует на сервере.

Итак, у меня есть такой код (на стороне сервера):

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
          ??...
     }

    ...

Итак, моя проблема заключается в том, что когда я запускаю приложение и использую WebClient на стороне клиента, чтобы использовать метод DownloadFile, который затем использует код, который у меня есть выше, я получаю:

WebException не было обработано: удаленный сервер вернул ошибку: (500) Внутренняя ошибка сервера.

(Во время отладки) Если я подключаюсь к браузеру и использую http://localhost:xxx/1.txt, я могу выполнить код на стороне сервера и выдать исключение, как и предполагалось. Поэтому я думаю, мне интересно, как я могу правильно обработать внутреннюю ошибку сервера на стороне клиента, чтобы я мог вернуть что-то значимое, например «Файл не существует». Одна мысль заключалась в том, чтобы использовать try catch вокруг метода WebClient.DownloadFile(address, filename), но я не уверен, что это единственная ошибка, которая произойдет, т.е. файл не существует.

изменить: следуя решению с помощью HttpResponse

Итак, если бы я использовал HttpResponse, мог бы я получить несколько предложений о том, как начать?

Я удаляю генерацию исключения со стороны клиента и заменяю его пользовательским HttpResponse? Так что в основном я думаю, что я бы выбрал код для использования, скажем, 200, и принудительно вернул код 200 в этом операторе if выше. Смотрите комментарий.

Затем на стороне клиента просто используйте If (Response.StatusCode == 200) и делайте все, что я хочу (сообщите, что файл пользователя не существует)

Я на верном пути?

изменить 2:

Я пытался использовать try catch вокруг моих методов копирования файлов, а затем в catch, устанавливая код состояния или описание состояния, но это вызывает исключения при установке описания состояния .. вот так:

context.Response.StatusDescription = ex.ToString();
context.Response.Status = ex.ToString();

ArgumentOutOfRangeException — указанный аргумент находится вне диапазона допустимых значений.


person baron    schedule 15.03.2010    source источник


Ответы (2)


Если вы программируете интерфейс IHttpHandler, вы не должны создавать исключения для этого кода. Никогда!

Вместо этого используйте Response.StatusCode и Response.StatusDescription для возврата важную информацию для клиента.

Пусть выбрасывается исключение только для системы, потому что тогда оно ДЕЙСТВИТЕЛЬНО будет исключением для ВАШЕГО кода.

Отредактировано для добавления

Отвечая на ваше редактирование, я бы сделал так, чтобы в случае, если файл не найден на стороне сервера, возвращался бы код состояния 404. И пусть этим занимается клиент.

Однако, как вы сказали, вы имеете дело с веб-службой, поэтому я бы просто добавил дополнительный ответ в заголовки, чтобы лучше указать, что на самом деле происходит на стороне сервера для вашего клиентского приложения.

Отредактировано для добавления

Response.Status - это целое число. Вот почему вы получаете ArgumentOutOfRangeException.

Убедитесь, что статус является одним из допустимых кодов возврата HTTP.

person Paulo Santos    schedule 15.03.2010
comment
это из соображений безопасности? что не так с исключениями в IHttpHandler? - person baron; 15.03.2010
comment
@baron: они не будут переданы клиенту каким-либо значимым образом. - person John Saunders; 15.03.2010
comment
Я не понимаю, как заголовки помогут, когда он сломается (необработанное WebException) на (клиентской стороне) WebClient.DownloadFile(URLofTxt); также можете ли вы показать какой-нибудь код, как установить ответ, я не мог это решить или найти хорошие примеры в вашем ссылки. - person baron; 17.03.2010
comment
При просмотре вашего ответа мне удалось случайно проголосовать против вашего ответа (после того, как я уже проголосовал за него). Теперь stackoverflow с задержкой не позволит мне исправить это, потому что голосование слишком старо, чтобы его можно было изменить, если только этот ответ не будет отредактирован, несмотря на то, что я пытался вернуть его обратно сразу после того, как случайно изменился, чтобы проголосовать против в первую очередь. И что, я опоздал на полсекунды? Как-то мне трудно в это поверить. Гррр. Извини. - person baron; 23.03.2010

Вместо создания исключения запишите его в текстовый файл или журнал событий, чтобы точно видеть, что произошло при возникновении ошибки.

Вот пример кода для регистрации событий http://support.microsoft.com/kb/307024. . Для сохранения в текстовый файл

    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();
            }                 
        }
    }
person wonde    schedule 15.03.2010
comment
-1: 1) StreamWriter должен находиться в блоке using, иначе при возникновении исключения произойдет утечка ресурсов. 2) Построение сообщения путем конкатенации строк. - person John Saunders; 15.03.2010
comment
@ Джон Сондерс. Почему StreamWriter должен быть вставлен с помощью block.I только что явно закрыт? - person wonde; 15.03.2010
comment
потому что, если исключение выдается ВО ВРЕМЯ, когда используется StreamWriter, тогда произойдет утечка ресурса. Обернув его предложением using, вы гарантируете, что даже в случае возникновения исключения ресурс будет правильно очищен. - person Paulo Santos; 15.03.2010
comment
@Paulo Santos - Спасибо за подробное объяснение. - person wonde; 15.03.2010