Asp.Net WebApi 捕获控制器构造函数中生成的异常
Asp.Net WebApi catch exceptions generated in controller constructor
在我的基础 API 控制器 class 构造函数中,我根据 windows 身份验证填充用户权限。我正在使用类似
的东西
var ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName.ToUpper());
var userInfo = UserPrincipal.FindByIdentity(ctx, System.Environment.UserName.ToUpper());
从AD中获取用户信息。问题是,当用户被锁定时,应用程序失败并返回 500,因为构造函数中发生了异常。有没有办法处理这些调用的异常并将其作为未经授权的异常或其他异常冒泡?我试图用 try catch 包围它并抛出未经授权的 httpresponse 异常,但它仍然冒出 500。
编辑#1
构造函数中发生的事情很少,当它失败时,我不想以 500 失败。我需要捕获异常并抛出其他东西。授权只是其中的一小部分。
编辑 #2
对于所有写我不应该在构造函数中有任何逻辑的人:
构造函数用于将对象初始化为有效状态。这部分应用程序的控制器必须具有数据库连接、用户信息和一些其他填充的属性,因为所有请求都使用所有这些信息。如果其中任何一个失败,我想 return 向用户提供不同类型的错误。在标准 class 的情况下,它将是不同类型的异常(SqlException、DbConnectionException、某种 AD 异常)。对于 WebApi,我希望它是不同类型的响应代码(未授权、未实现 (501) 等)。将相同的代码复制粘贴到应用程序该部分中的每个请求代表维护问题。
最简单的方法是在控制器构造函数中不使用与用户/会话相关的逻辑。
对于身份验证,您可以使用属性过滤器,获取用户信息只需创建助手 class 并在需要时使用它。
编辑
最后一件事:尝试使用依赖注入(如结构图),它会迫使您在构造函数中进行适当的更改,并且会使初始化更容易。 https://www.exceptionnotfound.net/setting-up-dependency-injection-in-web-api-with-structuremap/
由于原始异常几次被包装到其他异常中,到目前为止我发现的唯一方法是拥有一个全局异常过滤器,然后浏览上下文的内部异常。异常直到它为空或者我没有达到我正在寻找的类型的异常。
namespace SomeWebApi
{
public class GlobalExceptionHandler : ExceptionHandler
{
public override async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
if (context.Exception != null)
{
Exception filteredException = context.Exception;
while (
(filteredException != null)
&&
(filteredException.GetType() != typeof(HttpResponseException)
)
{
filteredException = filteredException.InnerException ;
}
if (
(filteredException != null)
&&
(filteredException != context.Exception)
)
{
var httpResponseException = (HttpResponseException) filteredException;
var response = context.Request.CreateErrorResponse(
httpResponseException.Response.StatusCode,
httpResponseException
);
context.Result = new ResponseMessageResult(response);
}
}
}
}
}
接下来我需要在WebApiConfig.Register中注册它:
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
在我的基础 API 控制器 class 构造函数中,我根据 windows 身份验证填充用户权限。我正在使用类似
的东西 var ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName.ToUpper());
var userInfo = UserPrincipal.FindByIdentity(ctx, System.Environment.UserName.ToUpper());
从AD中获取用户信息。问题是,当用户被锁定时,应用程序失败并返回 500,因为构造函数中发生了异常。有没有办法处理这些调用的异常并将其作为未经授权的异常或其他异常冒泡?我试图用 try catch 包围它并抛出未经授权的 httpresponse 异常,但它仍然冒出 500。
编辑#1
构造函数中发生的事情很少,当它失败时,我不想以 500 失败。我需要捕获异常并抛出其他东西。授权只是其中的一小部分。
编辑 #2
对于所有写我不应该在构造函数中有任何逻辑的人:
构造函数用于将对象初始化为有效状态。这部分应用程序的控制器必须具有数据库连接、用户信息和一些其他填充的属性,因为所有请求都使用所有这些信息。如果其中任何一个失败,我想 return 向用户提供不同类型的错误。在标准 class 的情况下,它将是不同类型的异常(SqlException、DbConnectionException、某种 AD 异常)。对于 WebApi,我希望它是不同类型的响应代码(未授权、未实现 (501) 等)。将相同的代码复制粘贴到应用程序该部分中的每个请求代表维护问题。
最简单的方法是在控制器构造函数中不使用与用户/会话相关的逻辑。 对于身份验证,您可以使用属性过滤器,获取用户信息只需创建助手 class 并在需要时使用它。
编辑
最后一件事:尝试使用依赖注入(如结构图),它会迫使您在构造函数中进行适当的更改,并且会使初始化更容易。 https://www.exceptionnotfound.net/setting-up-dependency-injection-in-web-api-with-structuremap/
由于原始异常几次被包装到其他异常中,到目前为止我发现的唯一方法是拥有一个全局异常过滤器,然后浏览上下文的内部异常。异常直到它为空或者我没有达到我正在寻找的类型的异常。
namespace SomeWebApi
{
public class GlobalExceptionHandler : ExceptionHandler
{
public override async Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
if (context.Exception != null)
{
Exception filteredException = context.Exception;
while (
(filteredException != null)
&&
(filteredException.GetType() != typeof(HttpResponseException)
)
{
filteredException = filteredException.InnerException ;
}
if (
(filteredException != null)
&&
(filteredException != context.Exception)
)
{
var httpResponseException = (HttpResponseException) filteredException;
var response = context.Request.CreateErrorResponse(
httpResponseException.Response.StatusCode,
httpResponseException
);
context.Result = new ResponseMessageResult(response);
}
}
}
}
}
接下来我需要在WebApiConfig.Register中注册它:
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());