Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# MVC4异常处理程序属性调用顺序_C#_Asp.net Mvc 4_Exception Handling - Fatal编程技术网

C# MVC4异常处理程序属性调用顺序

C# MVC4异常处理程序属性调用顺序,c#,asp.net-mvc-4,exception-handling,C#,Asp.net Mvc 4,Exception Handling,问题描述: 我正在尝试创建属性,这些属性定义如何处理ASP.NETMVC4控制器中的异常,以及操作。具体来说,他们将设置返回服务器的结果。 我几乎达到了预期的效果,但呼叫命令存在问题。 下面是我目前正在做的一个例子: [DefaultExceptionHandler] public abstract class BaseController { } public abstract class AuthorizeController : BaseController [VeryGoodExc

问题描述:

我正在尝试创建属性,这些属性定义如何处理ASP.NETMVC4控制器中的异常,以及操作。具体来说,他们将设置返回服务器的结果。 我几乎达到了预期的效果,但呼叫命令存在问题。 下面是我目前正在做的一个例子:

[DefaultExceptionHandler]
public abstract class BaseController
{

}

public abstract class AuthorizeController : BaseController

[VeryGoodExceptionHandler]
public class VeryGoodController : AuthorizeController
{

[ViewPageExceptionHandler]
public ActionResult ViewPage()
{
throw new Exception(); //Just for demonstration
return View();
}

public ActionResult ActionWithoutAttribute()
{
return View();
}
}
这是我的控制器的基本结构。这些属性都是以下类的后代:

public abstract class ExceptionHandlerAttributeBase : FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {            
            filterContext.Result = CreateExceptionResult(filterContext.Exception);
        }

        protected abstract ActionResult CreateExceptionResult(Exception e);
    }
CreateExceptionResult可以返回JsonResult、视图、StatusCodeResult,无论您希望返回什么。在我的例子中,它总是接收一个特殊的异常类型(一些企业库魔术),但这不是必需的

该属性工作得非常好,我将其置于某个对象之上,然后像应该的那样调用OneException方法,将适当的ActionResult放入filterContext中,并将其发送回客户端。 当我想要覆盖该属性时,问题就开始了。每个OneException方法都会在相同的上下文中被调用。当只装饰控制器时,一切(几乎)都很好,首先调用放在BaseController上的控制器,然后调用放在“VeryGoodController”上的控制器,覆盖结果。摆脱基本呼叫会很好,但不管怎样。在操作和控制器装饰的情况下,调用顺序恰好是:操作属性的OnException(设置所需结果)、基本控制器的OnException和子控制器的OnException(覆盖所需结果)。ExceptionContext没有任何属性可用作进一步处理的标志(可能Exception属性可以设置为null,但我不会这样做)

问题: 所以问题是我如何才能得到a)最后调用操作的OneException方法,和/或如果可能b)拒绝调用不太具体的方法(以更有效的方式,然后覆盖它们的结果)

一些额外信息: 我用这个答案作为参考。 同样,如果我按照本文中描述的方式注册过滤器,并且不添加属性,也会发生同样的情况

提前感谢,,
罗伯特

所以,我原来指望这样的事情会发生是完全错误的

根据博客文章(据我自己的代码测试所证实的),整个异常过滤器(即使我只是简单地覆盖Controller.OnException方法)是非常有限的,并且只在某些情况下有效。我能找到的唯一(不是很吸引人的)替代方法是在每个控制器方法中处理某个助手类中的异常,该类是从通用异常助手调用的。另一种选择是在Application_错误块中编写一些额外的讨厌的代码,并在那里处理这些东西

这篇博文提到了一个图书馆,这(理论上)非常好,但描述中的“抓住了大多数例外”并不是很吸引人

我最终得到的结果是,将所有“预期”异常包装在某个自定义异常中(这可能会带来很大的影响,我有一些基本异常类,在我的异常上有一些类别,如
BusinessRuleViolationException
,或
DbException
等,而确切的异常就是从这些中派生出来的)。在我的控制器中,所有动作代码都由一个
try
块包围,并有一个
catch(异常e)
块。此块调用我的exceptionhandler实用程序类的handleexception函数,并返回结果

异常处理程序函数:

public static ActionResult HandleException(Exception e)
        {
            try
            {
                //Calling the EL exception handler block. Configured to rethrow a HandledException.
                ExceptionPolicy.HandleException(e, ExceptionPolicyName.StatusCodePolicy.GetCode());
                //If no exception happened, that is a problem. Internal Server Error, also logging should be done.
                return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
            }
            //Catch the HandledException. It contains only controlled info on the error, which can be sent to the client. Also, the original exception is already logged by this time.
            catch (HandledException ex)
            {              
                return new HttpStatusCodeResult(ex.StatusCode, ex.Message);
            }
            catch (Exception ex)
            {
                //If the exception was not a HandledException (very unlikely), that is a problem, it should be logged. Also, Internal Server Error.
                return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
            }
        }
就目前而言,作为最后一道防线,一些代码应该放在Application_Error函数中,严格地消除任何信息泄漏的机会,如果有任何信息泄漏,则记录(可能是严重错误)。
异常处理函数可以参数化,以便能够提供不同的结果(如ajax场景中的StatusCode,但标准场景中的error View),因此我认为该解决方案非常灵活,基本上是最简单的解决方案。我有点担心抛出异常的数量,但这是一个MVC4 webapp,具有广泛的数据库通信,这是我目前最不关心的性能问题。

请向我们展示连接
OneException
方法调用的代码。我想你可以在那里解决它。FilterAttribute(我很确定)可以做到这一点。另一方面,现在整个事件被一个内部服务器错误覆盖,包含原始异常,这几乎是我不想看到的,所以这个问题可能很快会得到一些扩展…关于原始异常覆盖问题:如果我在控制器中抛出原始异常,没有问题,它起作用了。如果它是来自内层的异常,则会被覆盖。奇怪的是,当我捕获异常并抛出另一个异常时,它仍然会将原始异常放在结果上。因此,经过一些研究,我发现mvc的另一部分做得不太好(imho)。如果我在几天内没有得到答案(与我的结论不同),我会回答我自己的问题。看看这一页,更具体地说是“过滤顺序”章节。不确定这是否对您有帮助,但它确实帮助我了解了如何调用过滤器属性。;-)