C # Обрабатывать исключения WebS в DAL - PullRequest
0 голосов
/ 17 мая 2019

Есть ли способ правильно обрабатывать исключения WebException на уровне доступа к данным?

Ниже приведен метод SendReceive в нашем DAL, используемый для связи с нашим удаленным сервером, если существует проблема со связью, например, недоступность конечной точки и, следовательно, данные не могут быть получены, я бы хотел, чтобы пользователь был перенаправлен на a Просмотр, информируя пользователя, пожалуйста, попробуйте позже.

private static TResult SendReceive<TResult, TPayLoad>(string method, string route, TPayLoad payload, bool post, bool authentication, string hashedPassword)
{
    var subject = "WebApplication1 - " + method + " Error";

    using (var webClient = new WebClient())
    {
        try
        {
            var uri = new Uri("http://ourdomain/ourwebapicontroller/" + route);

            webClient.Headers[HttpRequestHeader.ContentType] = "application/json";

            if (authentication)
            {
                var hashedPasswordAsBytes = Encoding.UTF8.GetBytes(hashedPassword);

                webClient.Headers.Add(HttpRequestHeader.Authorization, "Basic " + Convert.ToBase64String(hashedPasswordAsBytes));
            }

            var response = post ? webClient.UploadString(uri, JsonConvert.SerializeObject(payload)) : webClient.DownloadString(uri);

            var parsedResponse = JsonConvert.DeserializeObject<TResult>(response);

            return parsedResponse;
        }
        catch (WebException webException)
        {
            SendEmail(subject, MvcApplication.To, MvcApplication.From, "<p>WebException [" + webException.Message + "]</p>");

            // Issue with endpoint 
        }
        catch (Exception exception)
        {
            SendEmail(subject, MvcApplication.To, MvcApplication.From, "<p>Exception [" + exception.Message + "]</p>");
        }
    }

    return default(TResult);
}

public Models.WebApplication1.Test GetTest(int id)
{
    return SendReceive<Models.WebApplication1.Test, int?>("GetTest", "get-test/" + id, null, false, false, null);
}

public int SetTest(Models.WebApplication1.Test test)
{
    return SendReceive<int, Models.WebApplication1.Test>("SetTest", "set-test", test, true, false, null);
}    

Поскольку на DAL ссылается контроллер, я не верю, что возможно использовать throw new HttpException(), однако это может быть обработано так:

public ViewResult Test(int id)
{
    var test = Dal.GetTest(id);

    if (test == null)
    {
        throw new HttpException(404, "Please try again later.");
    }

    return View(test);
}

Предпочитает обрабатывать проблему связи в SendReceive, а не обрабатывать на уровне контроллера для каждого метода, ссылающегося на SendReceive.

1 Ответ

0 голосов
/ 17 мая 2019

Все зависит от того, что вы подразумеваете под «дескриптором» и даже «исключением».

Контроллер
Что вы хотите делать в контроллере, если клиент запрашивает то, чего не существует? А 404 это хороший ответ. Но что, если DAL выдает исключение? Имеет ли смысл возвращать клиенту точно такой же результат? Ошибка 500, которая говорит клиенту, что что-то пошло не так, может иметь больше смысла.

Это несоответствие указано здесь:

throw new HttpException(404, "Please try again later.");

Если запрос вызвал исключение (по любой причине, включая DAL), то имеет смысл возвращать ошибку 500 с «повторить попытку позже». Вы четко сообщаете, что проблема на вашем конце. Извините, надеюсь, это больше не повторится, и если мы над этим работаем.

Если клиент запросил что-то, чего не существует, то это может измениться, а может и не измениться. Должны ли они попробовать позже? Зачем? Возможно, то, что они просили, никогда не будет найдено. Это тоже не исключение. Тот, кто просит что-то, чего не существует, и ничего не получает, означает, что ваше приложение работает правильно. 404 сообщает им, что наше приложение работает - у нас просто нет того, что они хотят.

Исходя из этого, всплытие фактического исключения для контроллера, вероятно, имеет смысл. DAL не знает о контроллере или даже веб-сайте. Не очень хорошо знать, должен ли звонящий знать, что произошло исключение.

DAL «Обработка» исключения может означать разные вещи. (Я оставлю свое мнение о том, что правильно, потому что оно не имеет отношения к делу.)

Если ваш DAL выдает исключение, вы можете сделать несколько вещей. Некоторые, возможно, лучше, чем другие, но опять же, это зависит от мнения и потребностей. - Ничего не делать. Пусть возникнет исключение. - Записывай и перебрасывай. - Зарегистрируйте его, затем оберните в другое исключение, которое обеспечивает некоторый контекст, и сгенерируйте новое исключение. (Обернуть ли исключение или нет - это целое обсуждение.)

Кто-то скажет, что «обработка» исключения - это нечто иное, включающее в себя реакцию на исключение таким образом, чтобы решить проблему, что мы с меньшей вероятностью сделаем. Например, если наше приложение извлекает ежедневную шутку Чака Норриса из API, но оно выдает исключение, мы можем зарегистрировать это, чтобы узнать, что что-то пошло не так, но затем заменить его резервной шуткой Чака Норриса.

Самая важная вещь, которую я не сделал бы , это "скрыть" исключение, чтобы для вызывающего абонента исключение и "ничего не найдено" выглядели одинаково. Если что-то пошло не так, контроллер должен знать, что - даже если он не понимает специфику - поэтому он (не DAL) - может определить, что следует сообщить вызывающей стороне.

Отношения между контроллером и DAL аналогичны отношениям между клиентом браузера и контроллером. Если это не просто работает, мы сообщаем об этом. Если нет данных, мы сообщаем об этом.


Я не рекомендую писать код в DAL, который отправляет электронное письмо. Это очень специфично и связывает весь ваш код с этим решением и, возможно, с реализацией отправки почты.

Альтернативой является определение интерфейса, подобного этому:

public interface ILog
{
    void LogException(Exception ex);
    void LogMessage(string message);
}

... и вводить в класс DAL. Когда возникает исключение, звоните _log.LogException(ex);. Ваш DAL не знает, что такое реализация. Вы можете войти или даже отправить электронное письмо, если хотите.

...