1

I am trying to pass custom Http Status codes in the response headers, when using Asp.Net boiler plate Dynamic API and web api written by inheriting AbpApiController.

The following are the two ways I tried, but failed: a) In the AppService, I used

public async Task<HttpResponseMessage> GetData() 
{
    HttpResponseMessage response=new HttpResponseMessage();
    response.Headers.Add("Status", "201");
    return response;
}

b) My another approach was to write an ApiController which inherited AbpApiController. And in that, I wrote

public IHttpActionResult GetData()
{
     var data=null;
     return NotFoundResult(data);
 }

Both of these approaches failed. How do we implement this?

Thanks in advance :-)

=======

Also, how is it possible to implement HostAuthenticationFilter("Bearer") for AbpApiController?

1 Answers1

1

This is workaround I came up with when faced the same problem. Solution is more related to ASP.NET than ABP.

First, I in my base exception I created field for error code.

Something like this :

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;
    }
}

Then I introduced following modified exception filter that would recognize my BaseException exceptions and read the error code :

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;
        }
    }
}

Finally, replaced ABP auto-registered filter with my implementation in WebApiModule initialization.

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>());
    }
}

Now through my custom exceptions and filter I was able to control response status codes.

Edgars Pivovarenoks
  • 1,526
  • 1
  • 17
  • 31