Это обходное решение, с которым я столкнулся, столкнувшись с той же проблемой. Решение больше связано с ASP.NET, чем с ABP.
Во-первых, я в своем базовом исключении создал поле для кода ошибки.
Что-то вроде этого:
public class BaseException : Exception
{
public int ErrorCode { get; private set; }
public BaseException() : this(500)
{
}
public BaseException(int errorCode)
{
ErrorCode = errorCode;
}
public BaseException(int errorCode, string message) : base(message)
{
ErrorCode = errorCode;
}
}
Затем я представил следующий модифицированный фильтр исключений, который будет распознавать мои BaseException
исключения и прочитать код ошибки:
namespace Abp.WebApi.ExceptionHandling
{
/// <summary>
/// Used to handle exceptions on web api controllers.
/// </summary>
public class CustomApiExceptionFilter : ExceptionFilterAttribute, ITransientDependency
{
/// <summary>
/// Reference to the <see cref="ILogger"/>.
/// </summary>
public ILogger Logger { get; set; }
/// <summary>
/// Reference to the <see cref="IEventBus"/>.
/// </summary>
public IEventBus EventBus { get; set; }
public IAbpSession AbpSession { get; set; }
private readonly IAbpWebApiModuleConfiguration _configuration;
/// <summary>
/// Initializes a new instance of the <see cref="AbpApiExceptionFilterAttribute"/> class.
/// </summary>
public CustomApiExceptionFilter(IAbpWebApiModuleConfiguration configuration)
{
_configuration = configuration;
Logger = NullLogger.Instance;
EventBus = NullEventBus.Instance;
AbpSession = NullAbpSession.Instance;
}
/// <summary>
/// Raises the exception event.
/// </summary>
/// <param name="context">The context for the action.</param>
public override void OnException(HttpActionExecutedContext context)
{
var wrapResultAttribute = (context.ActionContext.ActionDescriptor)
.GetWrapResultAttributeOrNull();
// ?? _configuration.DefaultWrapResultAttribute;
if (wrapResultAttribute == null || wrapResultAttribute.LogError)
{
LogHelper.LogException(Logger, context.Exception);
}
if (wrapResultAttribute == null || wrapResultAttribute.WrapOnError)
{
context.Response = context.Request.CreateResponse(
GetStatusCode(context),
new AjaxResponse(
SingletonDependency<ErrorInfoBuilder>.Instance.BuildForException(context.Exception),
context.Exception is Abp.Authorization.AbpAuthorizationException)
);
EventBus.Trigger(this, new AbpHandledExceptionData(context.Exception));
}
}
private HttpStatusCode GetStatusCode(HttpActionExecutedContext context)
{
if (context.Exception is Abp.Authorization.AbpAuthorizationException)
{
return AbpSession.UserId.HasValue
? HttpStatusCode.Forbidden
: HttpStatusCode.Unauthorized;
}
var customException = (context.Exception as BaseException);
if (customException != null)
return
(HttpStatusCode)customException.ErrorCode;
return
HttpStatusCode.InternalServerError;
}
}
}
Наконец, заменил АВР автоматически зарегистрирован фильтр с моей реализацией в инициализации WebApiModule.
public MyWebApiModule : AbpModule
{
public override void Initialize()
{
// ...
var filters = Configuration.Modules.AbpWebApi().HttpConfiguration.Filters;
var exceptionFilter = filters.First(h => h.Instance is AbpExceptionFilterAttribute).Instance;
filters.Remove(exceptionFilter);
filters.Add(IocManager.Resolve<CustomApiExceptionFilter>());
}
}
Теперь, используя мои собственные исключения и фильтр, я смог контролировать коды статуса ответа.