gpt4 book ai didi

c# - 引用标准库后异常不会进入 ExceptionFilter

转载 作者:行者123 更新时间:2023-11-30 20:27:28 28 4
gpt4 key购买 nike

我在 .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);
}
}

MyController.cs

public class MyController : ApiController
{
public async Task<IHttpActionResult> Get()
{
await Task.Run(() => { throw new ArgumentNullException("Error"); });
return Ok();
}
}

按原样调用时,我将收到 400

但是,当添加对 .NETStandard 2.0 库的引用时,异常不会转到 ExceptionFilter 并且我收到以下错误:

{
"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()"
}

感谢任何帮助。

最佳答案

我在使用 .Net 4.6.2 Web 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);
...
}
}

在另一个 .NETStandart 2.0 dll 中定义了 MyLogger 类。在尝试调用它时,它向我显示了与上面相同的异常。

这里对我有用的解决方法是在 Web 项目引用的另一个库(非 .NETStandart 2.0)中定义一个 .Net 框架适配器 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());
}

因此从源 .NETStandart 库中看不到任何内容,然后将其注入(inject)处理程序(通过 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# - 引用标准库后异常不会进入 ExceptionFilter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48589767/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com