MVC3 Какой уровень я должен ловить ошибки - PullRequest
1 голос
/ 06 февраля 2012

У меня есть сайт, использующий MVC3. У меня n-уровневая архитектура, и мне интересно, на каком уровне лучше ловить ошибки.

Для примера, скажем, у меня есть таблица учеников. У меня есть StudentRepository с функцией, такой как: StudentRepository.GetHightestGrade (studentId)

Так что, если у моей функции Repositry есть блок try / catch, или я должен поместить try / catch непосредственно в функцию ActionResult. ИЛИ мне бы лучше добавить добавление в бизнес-класс, и тогда моя функция ActionResult сделала бы что-то вроде

Business.GetHighestGrade (studentId), и эта функция просто выполняет попытку / отлов и вызывает функцию репозитория?

Ответы [ 4 ]

1 голос
/ 06 февраля 2012

Вы должны действительно обернуть методы в try / catch, если вы пытаетесь предотвратить переполнение стека ошибками. Как правило, лучше размещать try / catch на верхних слоях, чтобы защитить пользователей от ошибок. Нижние уровни обычно генерируют исключения при исключительных обстоятельствах, вы должны пытаться перехватывать их только на более высоких уровнях.

Вы найдете, что ваш код гораздо более читабелен без множества блоков try / catch, я лично стараюсь избегать их, когда могу, и позволяю атрибуту фильтра MVC3 HandleError позаботиться об отображении сообщений об ошибках. Однако иногда вам может потребоваться повторить операцию, если она выдает исключение, что является хорошим кандидатом на попытку / отлов.

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

1 голос
/ 06 февраля 2012

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

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

0 голосов
/ 06 февраля 2012

Уровень репозитория должен иметь конструкцию try-catch, которая обрабатывает исключения sql и записывает ошибки в журнал.Если ваша бизнес-логика сложна и может привести к ошибкам или несовместимым состояниям - вы должны проверить ее и записать ошибки в журнал.Если вы хотите уведомить пользователя о том, что что-то пошло не так (если бизнес-логика предоставляет исключения) - вы должны использовать конструкции try-catch в действиях вашего контроллера и использовать ModelState.AddModelError(), как один из способов уведомления пользователя, или использовать другой способ передачи информацииоб ошибке в поле зрения.И, наконец, вы должны зарегистрировать class CustomErrorFilter : IExceptionFilter в global.asax в Application_Start:

GlobalFilters.Filters.Add(new LoggingFilter());

Этот фильтр должен записывать в журнал все необработанные ошибки, возникающие на уровне контроллера.

Помните, что ваш код обеспечивает нормальный рабочий процесс и может обеспечить рабочий процесс с ошибками (генерировать исключения как один из способов организации рабочего процесса с ошибками или возвращать некоторые коды ошибок).Вы должны рассчитывать на это и обрабатывать оба рабочих процесса.

0 голосов
/ 06 февраля 2012

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

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Text;

    namespace Filters
    {
        public sealed class HandleException : FilterAttribute, IExceptionFilter
        {
            public void OnException(ExceptionContext filterContext)
            {
                if (filterContext == null)
                    throw new ArgumentException("filterContext");
                else if (typeof(AjaxException).IsInstanceOfType(filterContext.Exception) && !filterContext.ExceptionHandled)
            {
                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.ContentEncoding = Encoding.UTF8;
                filterContext.HttpContext.Response.HeaderEncoding = Encoding.UTF8;
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
                filterContext.HttpContext.Response.StatusCode = 400;
                filterContext.Result = new ContentResult
                {
                    Content = "Unexpected error",
                    ContentEncoding = Encoding.UTF8,
                };
            }
        }
    }
}

и добавьте этот фильтр в глобальные атрибуты фильтра в global.asax

...