【问题标题】:Handling Ajax cal exceptions via Custom Action Filters通过自定义操作过滤器处理 Ajax cal 异常
【发布时间】:2015-01-08 08:40:09
【问题描述】:

我正在通过自定义操作过滤器为我的 MVC 应用程序实施授权机制。

我为授权提供了以下自定义操作过滤器:

[AttributeUsageAttribute(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class AuthorizationFilterAttribute : ActionFilterAttribute
{
    public AuthorizationEntity Entity { get; set; }
    public AuthorizationPermission Permission { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        AuthorizationResult result = null;
        // Base actions (Authentication first)
        base.OnActionExecuting(filterContext);
        BaseController controller = filterContext.Controller as BaseController;
        if (controller != null)
        {   // Base actions (Authorizatioın next)
            User usr = controller.currentUser;
            AuthorizationResult ar = AuthorizationManager.GetAuthorizationResult(this.Entity, this.Permission, usr.UserId, usr.RoleId);
            if (!ar.IsAuthorized)
            {
                throw new UnauthorizedAccessException(ar.Description);
            }
            // Authorized, continue
            return;
        }
    }
}

在我的基本控制器类中,我正在处理 UnauthorizedAccessException 类型异常并通过以下代码将它们重定向到警告页面

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.Exception is UnauthorizedAccessException)
    {
        if (!filterContext.HttpContext.Request.IsAjaxRequest())
        {
            Exception ex = filterContext.Exception;

            filterContext.ExceptionHandled = true;
            filterContext.Result = new ViewResult()
            {
                ViewName = "UnauthorizedAccess"
            };
        }
        else
        {
            throw filterContext.Exception;
        }
    }
}

此机制适用于返回 ActionResult 的操作。但我也有一些 AJAX 调用,我不想重定向到警告页面,但会显示警告弹出窗口。这就是为什么我检查了请求是否是 Ajax 调用。

我正在使用以下代码进行 Ajax 调用:

$.ajax({
    type: "POST",
    url: "AjaxPostMethodName",
    dataType: "json",
    data:
        {
            postval: [some value here]
        },
    success: function (msg) {
        // Do some good actions here
    },
    error: function (x, t, m, b) {
        // Display error
        alert(m);
    }
})

控制器上的以下方法

public JsonResult AjaxPostMethodName(string postval)
{
    try
    {
       // Some cool stuff here
        return Json(null);
    }
    catch (Exception ex)
    {
        Response.StatusCode = UNAUTHORIZED_ACCESS_HTTP_STATUS_CODE;
        return Json(ex.Message);
    }
}

但是当我授权检查失败时,它直接显示“内部服务器错误”消息,而不是落入 AjaxPostMethodName 方法的 catch 块并显示正确的消息。

如何让这样的代码显示 filterContext.Exception 而不是静态的“Internal Server Error”消息?

问候。

【问题讨论】:

    标签: asp.net-mvc json exception-handling custom-action-filter


    【解决方案1】:

    我终于在另一个 Stack Overflow 帖子 (Can I return custom error from JsonResult to jQuery ajax error method?) 中找到了我的解决方案的答案。我应该使用 JsonExceptionFilterAttribute 如下:

    public class JsonExceptionFilterAttribute : FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.HttpContext.Response.StatusCode = 500;
                filterContext.ExceptionHandled = true;
    
                string msg = filterContext.Exception.Message;
                if (filterContext.Exception.GetType() == Type.GetType("System.UnauthorizedAccessException"))
                {
                    msg = "Unauthorized access";
                }
    
                filterContext.Result = new JsonResult
                {
                    Data = new
                    {
                        errorMessage = msg
                    },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
        }
    }
    

    【讨论】:

    • 我正在使用 return new HttpStatusCodeResult,它没有返回错误并显示 504 接收失败。现在我使用了return new JsonResult,问题就解决了。 :)
    【解决方案2】:

    当您的代码中存在未处理的异常时,您的 OnException 方法将被调用。在您的 ajax 方法AjaxPostMethodName 中,您已将代码放入try catch blcok。因此,此方法中的任何异常都不会转到您的 OnException 方法。

    【讨论】:

    • 不幸的是,这不起作用。 OnException 在 AjaxPostMethodName 名称之前运行并且在抛出异常之后实际方法不会运行。
    【解决方案3】:

    我刚刚检查了 Response.StatusCode 行为,对我来说它有效。

    Index.cshtml
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    
    <script type="text/javascript">
        $(document).ready(function () {
            alert('doc ready');
            $.ajax({
                type: "POST",
                url: '@Url.Action("AjaxPostMethodName")',                
                dataType: "json",
                data:
                    {
                        test: '10'
                    },
                success: function (msg) {
                    // Do some good actions here
                    alert('success');
                    alert(msg);
                },
                error: function (x, t, m, b) {
                    // Display error
                    alert('error');
                }
            });
        });
    </script>
    

    HomeController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MvcApplication1.Controllers
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            [HttpPost]
            public JsonResult AjaxPostMethodName(string postval)
            {
                Response.StatusCode = 401;
                return Json("test");
            }
    
        }
    }
    

    当我将 Response.StatusCode 设置为 200 时调用成功,当设置 401 时调用错误。

    请验证您的代码的其他部分是否不会以某种方式干扰它。

    您也可以尝试以下解决方法 - 如果 AjaxPostMethodName 抛出异常返回 JSON 具有标志 isValid 和消息 errorMessage,因此在您的 ajax 成功方法中您可以检查 isValid 是否正常并处理错误。

    【讨论】:

    • 这有效,但仅在页面上显示“错误”。我想要的是显示异常消息。
    猜你喜欢
    • 2023-04-01
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 2021-08-09
    相关资源
    最近更新 更多