Ошибка HandleError ASP.NET MVC

Как мне использовать фильтр [HandleError] в asp.net MVC Preview 5?
Я установил customErrors в своем файле Web.config

<customErrors mode = "On" defaultRedirect = "Error.aspx">
  <error statusCode = "403" redirect = "NoAccess.htm"/>
  <error statusCode = "404" redirect = "FileNotFound.htm"/>
</customErrors>

и поместите [HandleError] над моим классом контроллера следующим образом:

[HandleError]
public class DSWebsiteController: Controller
{
    [snip]
    public ActionResult CrashTest()
    {
        throw new Exception("Oh Noes!");
    }
}

Затем я позволяю своим контроллерам наследовать от этого класса и вызываю для них CrashTest (). Visual Studio останавливается из-за ошибки, и после нажатия клавиши f5 для продолжения я перенаправляюсь на Error.aspx? Aspxerrorpath = / sxi.mvc / CrashTest (где sxi - это имя используемого контроллера. Конечно, путь не может быть найден, и я получаю сообщение «Ошибка сервера в приложении '/'». 404.

Этот сайт был перенесен с превью 3 на 5. Все работает (портировать было не так уж много), кроме обработки ошибок. Когда я создаю полностью новый проект, обработка ошибок, похоже, работает.

Идеи?

--Примечание--
Поскольку этот вопрос сейчас имеет более 3K просмотров, я подумал, что было бы полезно добавить то, что я использую сейчас (ASP.NET MVC 1.0). В проект mvc contrib есть замечательный атрибут под названием "RescueAttribute" Вам, наверное, тоже стоит это проверить;)

Ссылка на источник RescueAttribute: mvccontrib.codeplex.com/SourceControl/changeset/view/…

Peter 13.01.2012 16:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
110
1
99 928
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вам не хватает Error.aspx :) В предварительной версии 5 он находится в вашей папке Views / Shared. Просто скопируйте его из нового проекта Preview 5.

Спасибо за ответ, но я уже скопировал страницу Error.aspx. Я действительно мог бы забыть о чем-то, но не в этот раз. :П

Boris Callens 09.10.2008 10:41
Ответ принят как подходящий

[HandleError]

Когда вы предоставляете своему классу (или методу действия) только атрибут HandleError, тогда при возникновении необработанного исключения MVC сначала будет искать соответствующее представление с именем «Ошибка» в папке представления контроллера. Если он не может найти его там, он продолжит поиск в папке общего просмотра (в которой по умолчанию должен быть файл Error.aspx).

[HandleError(ExceptionType = typeof(SqlException), View = "DatabaseError")]
[HandleError(ExceptionType = typeof(NullReferenceException), View = "LameErrorHandling")]

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

Для получения дополнительной информации ознакомьтесь с Сообщение в блоге Скотта Гатри об этом.

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

Boris Callens 10.10.2008 23:27

Если требуется регистрация этих исключений, будет ли это приемлемым местом для добавления выделенного кода в представление?

Peter J 01.04.2009 19:09

Iconic, вот мой ответ «лучше поздно, чем никогда» на ваш комментарий: вместо этого вы можете создать подкласс HandleErrorAttribute и переопределить его метод «OnException»: затем вставьте любое желаемое ведение журнала или настраиваемые действия. Затем вы можете либо полностью обработать исключение (установив для context.ExceptionHandled значение true), либо вернуться для этого к собственному методу OnException базового класса. Вот отличная статья, которая может в этом помочь: blog.dantup.me.uk/2009/04/…

Funka 15.08.2009 00:59

У меня много контроллеров, могу ли я справиться с этим внутри global.asax, например это, чтобы показать сообщение пользователям?

Shaiju T 15.09.2016 15:29

@ Как насчет того, чтобы использовать ту же страницу ошибок, что и PartialView, и отображать ее в модальном диалоговом окне после возникновения исключения? Не могли бы вы привести пример в своем ответе? То, чего я хочу достичь, было объяснено на Глобальная обработка ошибок с использованием PartialView в MVC.

Jack 20.09.2016 16:23

Также следует отметить, что ошибки, которые не устанавливают код ошибки http на 500

(например, UnauthorizedAccessException)

не будет обрабатываться фильтром HandleError.

Верно, но проверьте RescueAttribute в MVC contrib (ссылка в OP)

Boris Callens 04.12.2009 11:14

Решение для кода ошибки http до 500 это атрибут под названием [ERROR] поместите его в действие

public class Error: System.Web.Mvc.HandleErrorAttribute
{
    public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
    {

            if (filterContext.HttpContext.IsCustomErrorEnabled)
            {
                filterContext.ExceptionHandled = true;

            }
            base.OnException(filterContext);
            //OVERRIDE THE 500 ERROR  
           filterContext.HttpContext.Response.StatusCode = 200;
    }

    private static void RaiseErrorSignal(Exception e)
    {
        var context = HttpContext.Current;
      // using.Elmah.ErrorSignal.FromContext(context).Raise(e, context);
    } 

}

//ПРИМЕР:

[Error]
[HandleError]
[PopulateSiteMap(SiteMapName = "Mifel1", ViewDataKey = "Mifel1")]
public class ApplicationController : Controller
{
}

    [HandleError]
    public class ErrorController : Controller
    {        
        [AcceptVerbs(HttpVerbs.Get)]
        public ViewResult NotAuthorized()
        {
            //401
            Response.StatusCode = (int)HttpStatusCode.Unauthorized;

        return View();
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult Forbidden()
    {
        //403
        Response.StatusCode = (int)HttpStatusCode.Forbidden;

        return View();
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult NotFound()
    {
        //404
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    public ViewResult ServerError()
    {
        //500
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

}

Атрибуты в MVC очень полезны при обработке ошибок в методе получить и опубликовать, он также отслеживает вызов ajax.

Создайте базовый контроллер в своем приложении и унаследуйте его в основном контроллере (EmployeeController).

открытый класс EmployeeController: BaseController

Добавьте ниже код в базовый контроллер.

/// <summary>
/// Base Controller
/// </summary>
public class BaseController : Controller
{       
    protected override void OnException(ExceptionContext filterContext)
    {
        Exception ex = filterContext.Exception;

        //Save error log in file
        if (ConfigurationManager.AppSettings["SaveErrorLog"].ToString().Trim().ToUpper() == "TRUE")
        {
            SaveErrorLog(ex, filterContext);
        }

        // if the request is AJAX return JSON else view.
        if (IsAjax(filterContext))
        {
            //Because its a exception raised after ajax invocation
            //Lets return Json
            filterContext.Result = new JsonResult()
            {
                Data = Convert.ToString(filterContext.Exception),
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();

            filterContext.Result = new ViewResult()
            {
                //Error page to load
                ViewName = "Error",
                ViewData = new ViewDataDictionary()
            };

            base.OnException(filterContext);
        }
    }

    /// <summary>
    /// Determines whether the specified filter context is ajax.
    /// </summary>
    /// <param name = "filterContext">The filter context.</param>
    private bool IsAjax(ExceptionContext filterContext)
    {
        return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
    }

    /// <summary>
    /// Saves the error log.
    /// </summary>
    /// <param name = "ex">The ex.</param>
    /// <param name = "filterContext">The filter context.</param>
    void SaveErrorLog(Exception ex, ExceptionContext filterContext)
    {
        string logMessage = ex.ToString();

        string logDirectory = Server.MapPath(Url.Content("~/ErrorLog/"));

        DateTime currentDateTime = DateTime.Now;
        string currentDateTimeString = currentDateTime.ToString();
        CheckCreateLogDirectory(logDirectory);
        string logLine = BuildLogLine(currentDateTime, logMessage, filterContext);
        logDirectory = (logDirectory + "\Log_" + LogFileName(DateTime.Now) + ".txt");

        StreamWriter streamWriter = null;
        try
        {
            streamWriter = new StreamWriter(logDirectory, true);
            streamWriter.WriteLine(logLine);
        }
        catch
        {
        }
        finally
        {
            if (streamWriter != null)
            {
                streamWriter.Close();
            }
        }
    }

    /// <summary>
    /// Checks the create log directory.
    /// </summary>
    /// <param name = "logPath">The log path.</param>
    bool CheckCreateLogDirectory(string logPath)
    {
        bool loggingDirectoryExists = false;
        DirectoryInfo directoryInfo = new DirectoryInfo(logPath);
        if (directoryInfo.Exists)
        {
            loggingDirectoryExists = true;
        }
        else
        {
            try
            {
                Directory.CreateDirectory(logPath);
                loggingDirectoryExists = true;
            }
            catch
            {
            }
        }

        return loggingDirectoryExists;
    }

    /// <summary>
    /// Builds the log line.
    /// </summary>
    /// <param name = "currentDateTime">The current date time.</param>
    /// <param name = "logMessage">The log message.</param>
    /// <param name = "filterContext">The filter context.</param>       
    string BuildLogLine(DateTime currentDateTime, string logMessage, ExceptionContext filterContext)
    {
        string controllerName = filterContext.RouteData.Values["Controller"].ToString();
        string actionName = filterContext.RouteData.Values["Action"].ToString();

        RouteValueDictionary paramList = ((System.Web.Routing.Route)(filterContext.RouteData.Route)).Defaults;
        if (paramList != null)
        {
            paramList.Remove("Controller");
            paramList.Remove("Action");
        }

        StringBuilder loglineStringBuilder = new StringBuilder();

        loglineStringBuilder.Append("Log Time : ");
        loglineStringBuilder.Append(LogFileEntryDateTime(currentDateTime));
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("Username : ");
        loglineStringBuilder.Append(Session["LogedInUserName"]);
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("ControllerName : ");
        loglineStringBuilder.Append(controllerName);
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("ActionName : ");
        loglineStringBuilder.Append(actionName);
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append("----------------------------------------------------------------------------------------------------------");
        loglineStringBuilder.Append(System.Environment.NewLine);

        loglineStringBuilder.Append(logMessage);
        loglineStringBuilder.Append(System.Environment.NewLine);
        loglineStringBuilder.Append("========================================================================================================= = ");

        return loglineStringBuilder.ToString();
    }

    /// <summary>
    /// Logs the file entry date time.
    /// </summary>
    /// <param name = "currentDateTime">The current date time.</param>
    string LogFileEntryDateTime(DateTime currentDateTime)
    {
        return currentDateTime.ToString("dd-MMM-yyyy HH:mm:ss");
    }

    /// <summary>
    /// Logs the name of the file.
    /// </summary>
    /// <param name = "currentDateTime">The current date time.</param>
    string LogFileName(DateTime currentDateTime)
    {
        return currentDateTime.ToString("dd_MMM_yyyy");
    }

}

================================================

Находит каталог: Root / App_Start / FilterConfig.cs

Добавьте ниже код:

/// <summary>
/// Filter Config
/// </summary>
public class FilterConfig
{
    /// <summary>
    /// Registers the global filters.
    /// </summary>
    /// <param name = "filters">The filters.</param>
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

Отследить ошибку AJAX:

Вызовите функцию CheckAJAXError при загрузке страницы макета.

function CheckAJAXError() {
    $(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {

        var ex;
        if (String(thrownError).toUpperCase() == "LOGIN") {
            var url = '@Url.Action("Login", "Login")';
            window.location = url;
        }
        else if (String(jqXHR.responseText).toUpperCase().indexOf("THE DELETE STATEMENT CONFLICTED WITH THE REFERENCE CONSTRAINT") >= 0) {

            toastr.error('ReferanceExistMessage');
        }
        else if (String(thrownError).toUpperCase() == "INTERNAL SERVER ERROR") {
            ex = ajaxSettings.url;
            //var url = '@Url.Action("ErrorLog", "Home")?exurl=' + ex;
            var url = '@Url.Action("ErrorLog", "Home")';
            window.location = url;
        }
    });
};

Вы теряете сведения об исключении в запросах AJAX, вы не всегда этого хотите. Ваш код ведения журнала не является потокобезопасным. Вы предполагаете, что есть представление Error, и возвращаете его, не изменяя код ответа. Затем вы проверяете определенные строки ошибок в JavaScript (как насчет локализации?). В основном вы повторяете то, что уже сказано в существующем ответе: «Переопределить OnException для обработки исключений», но демонстрируете довольно плохую его реализацию.

CodeCaster 20.09.2016 16:09

Что такое параметр @ School.Resource.Messages.ReferanceExist?

Jack 20.09.2016 16:10

@CodeCaster Знаете ли вы лучший способ использования такого метода обработки ошибок с помощью AJAX в ASP.NET MVC? Любая помощь, пожалуйста?

Jack 20.09.2016 16:11

Верните 400 или 500, как предполагается в HTTP. Не ищите конкретные строки в теле ответа.

CodeCaster 20.09.2016 16:14

@CodeCaster Не могли бы вы взглянуть на Глобальная обработка ошибок с использованием PartialView в MVC относительно этой проблемы?

Jack 20.09.2016 16:18

@SandipPatel Большое спасибо. Я пробовал этот метод, но когда в контроллере возникает исключение, я возвращаю JSON в связанный вызов AJAX, а затем вызываю ваш метод CheckAJAXError (). Но когда я отлаживаю с помощью Firebug, он возвращается после первой строки этого метода Javascript. Есть ли какая-либо реализация в моем методе контроллера (я уже унаследовал от BaseController). Любая идея?

Jack 20.09.2016 16:20

Другие вопросы по теме