【问题标题】:How to return JSON from a HandleError filter?如何从 HandleError 过滤器返回 JSON?
【发布时间】:2012-08-15 19:23:01
【问题描述】:

aspnet mvc 有 HandleError 过滤器,如果发生错误,它将返回一个视图,但如果在调用 JsonResult Action 时发生错误,我如何返回表示错误的 JSON 对象?

我不想将代码包装在每个在 try/catch 中返回 JsonResult 的操作方法中来完成它,我宁愿通过添加“HandleJsonError”属性或使用现有的 HandleError 属性来完成它所需的操作方法。

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    看看HandleErrorAttribute的MVC实现。它返回一个 ViewResult。您可以编写自己的版本 (HandleJsonErrorAttribute),返回 JsonResult。

    【讨论】:

    • 我已经尝试过了,但是当调用 HandleJsonErrorAttribute OnException 方法时,当动作所属的 Controller 类上有 HandleErrorAttribute 时,filterContext.ExceptionHandled 属性始终为真。动作方法handleerror不应该优先被调用吗?
    【解决方案2】:

    简而言之,可以去扩展HandleErrorAttribute,像这样:

    public class OncHandleErrorAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            // Elmah-Log only handled exceptions
            if (context.ExceptionHandled)
                ErrorSignal.FromCurrentContext().Raise(context.Exception);
    
            if (context.HttpContext.Request.IsAjaxRequest())
            {
                // if request was an Ajax request, respond with json with Error field
                var jsonResult = new ErrorController { ControllerContext = context }.GetJsonError(context.Exception);
                jsonResult.ExecuteResult(context);
                context.ExceptionHandled = true;
            }
            else
            {
                // if not an ajax request, continue with logic implemented by MVC -> html error page
                base.OnException(context);
            }
        }
    }
    

    如果您不需要 Elmah 日志记录代码行,请删除它。我使用我的一个控制器根据错误和上下文返回一个 json。这是示例:

        public class ErrorController : Controller
    {
        public ActionResult GetJsonError(Exception ex)
        {
            var ticketId = Guid.NewGuid(); // Lets issue a ticket to show the user and have in the log
    
            Request.ServerVariables["TTicketID"] = ticketId.ToString(); // Elmah will show this in a nice table
    
            ErrorSignal.FromCurrentContext().Raise(ex); //ELMAH Signaling
    
            ex.Data.Add("TTicketID", ticketId.ToString()); // Trying to see where this one gets in Elmah
    
            return Json(new { Error = String.Format("Support ticket: {0}\r\n Error: {1}", ticketId, ex.ToString()) }, JsonRequestBehavior.AllowGet);
        }
    

    我在上面添加了一些票务信息,你可以忽略这个。由于过滤器的实现方式(扩展了默认的 HandleErrorAttributes),我们可以从全局过滤器中删除 HandleErrorAttribute:

        public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new GlobalAuthorise());
            filters.Add(new OncHandleErrorAttribute());
            //filters.Add(new HandleErrorAttribute());
        }
    

    基本上就是这样。您可以阅读my blog entry 了解更多详细信息,但对于这个想法,以上就足够了。

    【讨论】:

    • 以上在 IISExpress 中开发时有效。为了在部署到真正的 IIS 网络服务器时能够正常工作,我们需要在创建 jsonmessage 时添加 context.HttpContext.Response.TrySkipIisCustomErrors = true;,因为 IIS 会覆盖错误消息并显示其默认状态代码 500 页面
    【解决方案3】:

    也许您可以创建自己的属性并拥有一个构造函数值,该值采用 View 或 Json 的枚举值。下面是我使用自定义授权属性来演示我的意思。这样,当 json 请求的身份验证失败时,它会以 json 错误响应,如果它返回 View,则同样如此。

       public enum ActionResultTypes
       {
           View,
           Json
       }
    
        public sealed class AuthorizationRequiredAttribute : ActionFilterAttribute, IAuthorizationFilter
        {
            public ActionResultTypes ActionResultType { get; set; }
    
            public AuthorizationRequiredAttribute(ActionResultTypes actionResultType)
            {
                this.ActionResultType = ActionResultType;
            }
        }
    
        //And used like
        [AuthorizationRequired(ActionResultTypes.View)]
        public ActionResult About()
        {
        }
    

    【讨论】:

    • 我将尝试实现一个工作示例。如果您发现它不起作用或找到其他解决方案,请告诉我!
    猜你喜欢
    • 2019-12-03
    • 2020-03-14
    • 1970-01-01
    • 2015-02-23
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多