ASP.NET MVC - декларативное перенаправление при ошибке - PullRequest
4 голосов
/ 11 января 2012

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

        try
        {
            return action(parameters);
        }
        catch (Exception exception)
        {
            ErrorViewModel errorModel = new ErrorViewModel();
            errorModel.ErrorMessage = "An error occured while doing something.";
            errorModel.ErrorDetails = exception.Message;
            errorModel.ReturnUrl = Url.Action("Controller", "Action");
            return RedirectToAction("Index", "Error", errorModel);
        }

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

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        HandleErrorAttribute attribute = new HandleErrorAttribute();
        filters.Add(attribute);
    }

, и у меня есть мои настройки web.config, подобные этим:

<customErrors mode="On" defaultRedirect="~/Error/Unknown">

Но это работает только для необработанных исключений.

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

Ответы [ 2 ]

4 голосов
/ 12 января 2012

Вот небольшой класс RedirectOnErrorAttribute, который я создал:

using System;
using System.Web.Mvc;
using MyApp.Web.Models;

namespace MyApp.Web.Utilities
{
    public class RedirectOnErrorAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// Initializes a new instance of a RedirectOnErrorAttribute.
        /// </summary>
        public RedirectOnErrorAttribute()
        {
            ErrorMessage = "An error occurred while processing your request.";
        }

        /// <summary>
        /// Gets or sets the controller to redirect to.
        /// </summary>
        public string ReturnController { get; set; }

        /// <summary>
        /// Gets or sets the action to redirect to.
        /// </summary>
        public string ReturnAction { get; set; }

        /// <summary>
        /// Gets or sets the error message.
        /// </summary>
        public string ErrorMessage { get; set; }

        /// <summary>
        /// Redirects the user to an error screen if an exception is thrown.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext.Exception != null && !filterContext.ExceptionHandled)
            {
                ErrorViewModel viewModel = new ErrorViewModel();
                viewModel.ErrorMessage = ErrorMessage;
                viewModel.ErrorDetails = filterContext.Exception.Message;
                string controller = ReturnController;
                string action = ReturnAction;
                if (String.IsNullOrWhiteSpace(controller))
                {
                    controller = (string)filterContext.RequestContext.RouteData.Values["controller"];
                }
                if (String.IsNullOrWhiteSpace(action))
                {
                    action = "Index";
                }
                UrlHelper helper = new UrlHelper(filterContext.RequestContext);
                viewModel.ReturnUrl = helper.Action(action, controller);
                string url = helper.Action("Index", "Error", viewModel);
                filterContext.Result = new RedirectResult(url);
                filterContext.ExceptionHandled = true;
            }
            base.OnActionExecuted(filterContext);
        }
    }
}

Теперь я могу украсить все свои действия так:

[RedirectOnError(ErrorMessage="An error occurred while doing something.", ReturnController="Controller", ReturnAction="Action")]
3 голосов
/ 11 января 2012

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

    [HandleError]
    public class AccountController : Controller
    {
       [HttpPost]
       public ActionResult YourAction(SomeModel model)
        {
            //do stuff but don't catch exception
            return View();
        }
        protected override void OnException(ExceptionContext filterContext)
        {
            EventLog.WriteEntry("YourProjectEventName", filterContext.Exception.ToString(), EventLogEntryType.Error);
            base.OnException(filterContext);
       }
}
...