Обработка ошибок в ASP.NET MVC

Вот пример установки GtkFileFilter с шаблоном *.cpp для отображения только файлов C ++. Также устанавливается имя документа по умолчанию test.cpp.

компиляция с помощью: g ++ filechooser.cpp `pkg-config --cflags gtk + -3.0`` pkg-config --libs gtk + -3.0`

#include <gtk/gtk.h>

static void dialog_result(GtkWidget *dialog, gint resp, gpointer data)
{
    if (resp == GTK_RESPONSE_OK) {
        // do nothing
    } else {
        gtk_widget_destroy(dialog);
    }
}

static void open_dialog(GtkWidget *button, gpointer window)
{
    GtkWidget *dialog;
    GtkFileFilter *filter;

    dialog = gtk_file_chooser_dialog_new("Choose a file:", GTK_WINDOW(window), 
                        GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_SAVE,
                         GTK_RESPONSE_OK, GTK_STOCK_CANCEL,
                         GTK_RESPONSE_CANCEL, NULL);

    filter = gtk_file_filter_new();
    gtk_file_filter_add_pattern(filter, "*.cpp");
    gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "test.cpp");
    gtk_widget_show_all(dialog);
    gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
    if (resp == GTK_RESPONSE_OK)
        g_print("%s\n", gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
    else
        g_print("You pressed the cancel\n");
    gtk_widget_destroy(dialog);
}

int main()
{
    gtk_init(NULL, NULL);
    GtkWidget *window, *button;
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
    button = gtk_button_new_with_label("Save");
    g_signal_connect(button, "clicked", G_CALLBACK(open_dialog), window);
    gtk_container_set_border_width(GTK_CONTAINER(window), 100);
    gtk_container_add(GTK_CONTAINER(window), button);
    gtk_widget_show_all(window);
    gtk_main();
}
64
задан Matthew Manela 2 December 2010 в 16:37
поделиться

6 ответов

Благодаря kazimanzurrashaid вот что я в итоге и сделал в Global.asax.cs:

protected void Application_Error()
{
    Exception unhandledException = Server.GetLastError();
    HttpException httpException = unhandledException as HttpException;
    if (httpException == null)
    {
        Exception innerException = unhandledException.InnerException;
        httpException = innerException as HttpException;
    }

    if (httpException != null)
    {
        int httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int) HttpStatusCode.Unauthorized:
                Response.Redirect("/Http/Error401");
                break;
        }
    }
}

Я смогу добавить больше страниц в HttpContoller на основе любых дополнительных кодов ошибок HTTP Мне нужно поддержать.

21
ответ дан 24 November 2019 в 15:54
поделиться

Controller.OnException (контекст ExceptionContext) . Переопределите его.

protected override void OnException(ExceptionContext filterContext)
{
    // Bail if we can't do anything; app will crash.
    if (filterContext == null)
        return;
        // since we're handling this, log to elmah

    var ex = filterContext.Exception ?? new Exception("No further information exists.");
    LogException(ex);

    filterContext.ExceptionHandled = true;
    var data = new ErrorPresentation
        {
            ErrorMessage = HttpUtility.HtmlEncode(ex.Message),
            TheException = ex,
            ShowMessage = !(filterContext.Exception == null),
            ShowLink = false
        };
    filterContext.Result = View("ErrorPage", data);
}
63
ответ дан 24 November 2019 в 15:54
поделиться

Я не думаю, что вы сможете показать конкретную ErrorPage, основанную на HttpCode с атрибутом HandleError, и я бы предпочел использовать для этой цели HttpModule. Предполагая, что у меня есть папка «ErrorPages», где существует отдельная страница для каждой конкретной ошибки, и сопоставление указывается в файле web.config так же, как и в обычном приложении веб-формы. Ниже приведен код, который используется для отображения страницы с ошибкой:

public class ErrorHandler : BaseHttpModule{

public override void OnError(HttpContextBase context)
{
    Exception e = context.Server.GetLastError().GetBaseException();
    HttpException httpException = e as HttpException;
    int statusCode = (int) HttpStatusCode.InternalServerError;

    // Skip Page Not Found and Service not unavailable from logging
    if (httpException != null)
    {
        statusCode = httpException.GetHttpCode();

        if ((statusCode != (int) HttpStatusCode.NotFound) && (statusCode != (int) HttpStatusCode.ServiceUnavailable))
        {
            Log.Exception(e);
        }
    }

    string redirectUrl = null;

    if (context.IsCustomErrorEnabled)
    {
        CustomErrorsSection section = IoC.Resolve<IConfigurationManager>().GetSection<CustomErrorsSection>("system.web/customErrors");

        if (section != null)
        {
            redirectUrl = section.DefaultRedirect;

            if (httpException != null)
            {
                if (section.Errors.Count > 0)
                {
                    CustomError item = section.Errors[statusCode.ToString(Constants.CurrentCulture)];

                    if (item != null)
                    {
                        redirectUrl = item.Redirect;
                    }
                }
            }
        }
    }

    context.Response.Clear();
    context.Response.StatusCode = statusCode;
    context.Response.TrySkipIisCustomErrors = true;

    context.ClearError();

    if (!string.IsNullOrEmpty(redirectUrl))
    {
        context.Server.Transfer(redirectUrl);
    }
}

}

6
ответ дан 24 November 2019 в 15:54
поделиться

Атрибут HandleError, похоже, обрабатывает только исключения, сгенерированные инфраструктурой MVC, а не исключения, сгенерированные моим собственным кодом.

Это просто неправильно. Действительно, HandleError будет «обрабатывать» только исключения, добавленные в ваш собственный код или в код, вызываемый вашим собственным кодом. Другими словами, только исключения, когда ваше действие находится в стеке вызовов.

Реальное объяснение поведения, которое вы видите, - это конкретное исключение, которое вы выбрасываете. HandleError ведет себя по-разному с HttpException. Из исходного кода:

        // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method),
        // ignore it.
        if (new HttpException(null, exception).GetHttpCode() != 500) {
            return;
        }
13
ответ дан 24 November 2019 в 15:54
поделиться

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

 System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>

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

Эта модель отправлена ​​на страницу с ошибкой. Если ваша страница с ошибкой использует ту же главную страницу, что и остальная часть вашего сайта, и требует любой другой информации о модели, вам нужно будет либо создать свой собственный тип атрибута [HandleError] , либо переопределить OnException ] или что-то в этом роде.

3
ответ дан 24 November 2019 в 15:54
поделиться

Я выбрал подход Controller.OnException (), который для меня является логическим выбором - поскольку я выбрал ASP.NET MVC, я предпочитаю оставаться на уровне фреймворка и не вмешиваться в основную механику, если возможный.

Я столкнулся со следующей проблемой:

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

Я исправил это, очистив ответ перед установкой filterContext.Result - вот так:

        filterContext.HttpContext.Response.Clear(); // gets rid of any garbage
        filterContext.Result = View("ErrorPage", data);

Надеюсь, это еще кому-то сэкономит: -)

2
ответ дан 24 November 2019 в 15:54
поделиться