#boilerplate #asp.net-boilerplate
#шаблон #asp.net-шаблон
Вопрос:
Я пытаюсь передать пользовательские коды состояния Http в заголовках ответов при использовании Asp.Net динамический API котельной плиты и веб-API написаны путем наследования AbpApiController.
Ниже приведены два способа, которые я пробовал, но потерпел неудачу: a) В AppService я использовал
public async Task<HttpResponseMessage> GetData()
{
HttpResponseMessage response=new HttpResponseMessage();
response.Headers.Add("Status", "201");
return response;
}
б) Мой другой подход заключался в написании ApiController, который унаследовал AbpApiController. И в этом я написал
public IHttpActionResult GetData()
{
var data=null;
return NotFoundResult(data);
}
Оба этих подхода завершились неудачей. Как мы это реализуем?
Заранее спасибо 🙂
=======
Кроме того, как можно реализовать HostAuthenticationFilter(«Bearer») для AbpApiController?
Ответ №1:
Это обходной путь, который я придумал, когда столкнулся с той же проблемой. Решение больше связано с ASP.NET чем АБП.
Во-первых, я в своем базовом исключении создал поле для кода ошибки.
Что-то вроде этого :
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;
}
}
}
Наконец, заменил автоматически зарегистрированный фильтр ABP моей реализацией в инициализации 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>());
}
}
Теперь с помощью моих пользовательских исключений и фильтра я смог управлять кодами состояния ответа.