当前位置: 首页 > 知识库问答 >
问题:

引用标准库后不转到ExceptionFilter的异常

裴凯定
2023-03-14

我在.NET 4.6.1上有一个传统的WebApi项目,该项目具有全局exceptionfilter,它处理已知的异常,以返回带有相应状态代码的友好消息。

webapiconfig.cs

public static void Register(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    config.Filters.Add(new MyExceptionFilterAttribute());
}

MyExceptionFilterAttribute.cs

internal sealed class GatewayExceptionFilterAttribute : ExceptionFilterAttribute
{
    private static readonly Dictionary<Type, HttpStatusCode> Exceptions = new Dictionary<Type, HttpStatusCode>
    {
        // HTTP 400
        [typeof(ArgumentException)] = HttpStatusCode.BadRequest,
        [typeof(ArgumentNullException)] = HttpStatusCode.BadRequest,
    };

    public override void OnException(HttpActionExecutedContext context)
    {
        var type = context.Exception.GetType();

        if (context.Exception is HttpResponseException)
            return;

        // Return 500 for unspecified errors
        var status = HttpStatusCode.InternalServerError;
        var message = Strings.ERROR_INTERNAL_ERROR;

        if (Exceptions.ContainsKey(type))
        {
            status = Exceptions[type];
            message = context.Exception.Message;
        }

        context.Response = context.Request.CreateErrorResponse(status, message);
    }
}
public class MyController : ApiController
{
    public async Task<IHttpActionResult> Get()
    {
        await Task.Run(() => { throw new ArgumentNullException("Error"); });
        return Ok();
    }
}
{
    "message": "An error has occurred.",
    "exceptionMessage": "Method not found: 'System.Net.Http.HttpRequestMessage System.Web.Http.Filters.HttpActionExecutedContext.get_Request()'.",
    "exceptionType": "System.MissingMethodException",
    "stackTrace": "   at MyApi.Filters.MyExceptionFilterAttribute.OnException(HttpActionExecutedContext context)\r\n   at System.Web.Http.Filters.ExceptionFilterAttribute.OnExceptionAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ExceptionFilterAttribute.<ExecuteExceptionFilterAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}

感谢任何帮助。

共有1个答案

井旺
2023-03-14

我在使用.NET4.6.2Web API时遇到了同样问题。我已经在Web项目中定义了以下异常处理程序:

public class ExceptionHandlerAttribute : ExceptionFilterAttribute
{
    private readonly MyLogger _logger;

    private const string ExceptionOccuredLoggingTag = "ExceptionOccured";

    public ExceptionHandlerAttribute(MyLogger logger)
    {
        _logger = logger;
    }


    public override void OnException(HttpActionExecutedContext context)
    {
        ...
        _logger.Error(errorMessage,
            context.Exception,
            mostRecentFrame.Class.Name,
            mostRecentFrame.Method.Name,
            ExceptionOccuredLoggingTag);
        ...
    }
}

其中定义myLogger类的位置位于另一个.netstandart 2.0 DLL中。当我试图调用它时,它显示了与上面相同的异常。

这里对我有用的一个解决办法是在web项目引用的另一个库(非.NetStandart 2.0)中定义一个.NET framework适配器myLoggerAdapter:

public interface ILoggerCompatable
{
    void Error(string message, object data, params string[] tags);
}

public class MyLoggerAdapter : ILoggerCompatable
{
    private readonly MyLogger _logger;

    public MyLoggerAdapter(MyLogger logger)
    {
        _logger = logger;
    }

    public void Error(string message, object data, params string[] tags) => _logger.Error(message, data, tags.Select(tag => (Tag)tag).ToArray());
}

以便从source.netstandart库中看不到任何东西,然后将其注入处理程序(通过Autofac):

public class ExceptionHandlerAttribute : ExceptionFilterAttribute
{
    private readonly ILoggerCompatable _logger;

    private const string ExceptionOccuredLoggingTag = "ExceptionOccured";

    public ExceptionHandlerAttribute(ILoggerCompatable logger)
    {
        _logger = logger;
    }


    public override void OnException(HttpActionExecutedContext context)
    {
        ...
        _logger.Error(errorMessage,
            context.Exception,
            mostRecentFrame.Class.Name,
            mostRecentFrame.Method.Name,
            ExceptionOccuredLoggingTag);
        ...);
    }
}

过滤器注册如下所示:

var loggerCompatable = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(ILoggerCompatable)) as ILoggerCompatable;
GlobalConfiguration.Configuration.Filters.Add(new ExceptionHandlerAttribute(loggerCompatable));
 类似资料:
  • 经验表明,异常是可以分类的。C++ 草案标准提供了标准库异常层次。这个层次以基类 excephon 开始(在头文件 <exception> 中定义),该基类提供服务 what(),在每个派生类中重定义,发出相应的错误消息。 从基类 exception 可以派生直接派生类runtime_error和Iogic_error(都在头文件 <stdexcept> 中定义),每个派生类又可以派生其他类。 从

  • Rust 的标准库提供了很多有用的功能,不过它假设它的 host 系统的多种功能的支持:线程,网络,堆分配和其他功能。有些系统并没有这些功能,不过,Rust也能在这些系统上工作。为此,我们可以通过一个属性来告诉 Rust 我们不想使用标准库:#![no_std]。 注意:这个功能技术上是稳定的,不过有些附加条件。其一,你可以构建一个稳定的#![no_std]库,但二进制文件不行。关于没有标准库的库

  • Python 标准库(Python Standrad Library)中包含了大量有用的模块,同时也是每个标准的 Python 安装包中的一部分。熟悉 Python 标准库十分重要,因为只要你熟知这些库可以做到什么事,许多问题都能够轻易解决。 我们将探索这个库中的一些常用模块。你能在你的 Python 安装包中附带的文档中的“库概览(Library Reference)” 部分中查找到所有模块的全

  • String string.byte string.char string.dump string.find string.format string.gmatch string.gsub string.len string.lower string.match string.rep string.reverse string.sub string.upper 在st

  • Object 对象 属性描述对象 Array 对象 包装对象 Boolean 对象 Number 对象 String 对象 Math 对象 Date 对象 RegExp 对象 JSON 对象

  • 我是谷歌应用引擎服务的新手。我有一个JavaMaven项目,其中一个模块运行在应用引擎flex上,另一个模块运行在应用引擎标准上。我正在为应用引擎Flex API使用JWT身份验证。我想从应用引擎标准向应用引擎Flex发出发布请求。验证服务的最佳方式应该是什么? 此外,我还有一个cron服务,它可以访问我用于某些后端内容的特定URL。如何验证请求是否仅来自Cron服务?