I have a controller that looks like this:

[HttpPost]
public async Task<ActionResult> CreateAsync(TodoItems item)
    await item.AddNewItemAsync(item.Id, item.Name);
    return Ok(new ApiOkResponse(item, $"An item has been added."));
[HttpGet("get")]
public async Task<ActionResult> Get(int id)
    TodoItems items = new();
    if (!items.TryGetProduct(id, out var item))
            throw new NotFoundException($"The item with id {id} not found");
     return Ok(new ApiOkResponse(item));

Here in the controller, in the CreateAsync action, I have tried to return the object wrapped with messages and data.

And in the Get action, I have thrown a NotFoundException.

To wrap the return responses, along with exception handling I have tried two different ways:

One way is by inheriting the ObjectResultExecutor, which looks so simple and plain, which I have implemented from.

public class ResponseEnvelopeResultExecutor : ObjectResultExecutor
    public ResponseEnvelopeResultExecutor(OutputFormatterSelector formatterSelector, IHttpResponseStreamWriterFactory writerFactory,
        ILoggerFactory loggerFactory, IOptions<MvcOptions> mvcOptions) : base(formatterSelector, writerFactory, loggerFactory, mvcOptions)
    public override Task ExecuteAsync(ActionContext context, ObjectResult result)
        var response = (ApiOkResponse)(result.Value);
        TypeCode typeCode = Type.GetTypeCode(result.Value.GetType());
        if (typeCode == TypeCode.Object)
            result.Value = response;
        return base.ExecuteAsync(context, result);

I have also implemented the same thing using custom middleware, where there are plenty of findings on the stack overflow.

  • How can I wrap Web API responses(in .net core) for consistency?
  • How to read ASP.NET Core Response.Body?
  • Both ways seem to work fine currently, but the first approach looks clean to me. But I am still not sure which way is good? Can anyone explain to me the difference between both cases and what are its drawbacks?

    And what could be the possible changes that need to be considered in the future using both techniques?

    I have been reading this answer, wherein point 3 (disadvantages) for Explicitly formatting/wrapping your results in your actions, says,

    Your actions are responsible for returning the correctly formatted response. Something like: return new ApiResponse(obj); or you can create extension method and call it like obj.ToResponse() but you always have to think about the correct response format.

    In my case, I have always wrap my response format. After reading that document I found that I implemented it in the same way which states the drawbacks of both techniques.

    What are the proper ways of doing this formatting in dot-net-core5?

    I am also using the same custom wrapper to decorate the Exception as well.

    public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
        private readonly IDictionary<Type, Action<ExceptionContext>> _exceptionHandlers;
        public ApiExceptionFilterAttribute()
            // Register known exception types and handlers.
            _exceptionHandlers = new Dictionary<Type, Action<ExceptionContext>>
                { typeof(NotFoundException), HandleNotFoundException },
                { typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException },
                { typeof(ForbiddenAccessException), HandleForbiddenAccessException },
        public override void OnException(ExceptionContext context)
            HandleException(context);
            base.OnException(context);
        private void HandleException(ExceptionContext context)
            Type type = context.Exception.GetType();
            if (_exceptionHandlers.ContainsKey(type))
                _exceptionHandlers[type].Invoke(context);
                return;
            if (!context.ModelState.IsValid)
                HandleInvalidModelStateException(context);
                return;
            HandleUnknownException(context);
        private void HandleInvalidModelStateException(ExceptionContext context)
            var errorList = (from item in context.ModelState.Values
                             from error in item.Errors
                             select error.ErrorMessage).ToList();
            var details = new ApiOkResponse(StatusCodes.Status400BadRequest, String.Join(" ; ", errorList));
            context.Result = new BadRequestObjectResult(details);
            context.ExceptionHandled = true;
        private void HandleNotFoundException(ExceptionContext context)
            var exception = context.Exception as NotFoundException;
            var details = new ApiOkResponse(StatusCodes.Status404NotFound, exception.Message);
            context.Result = new NotFoundObjectResult(details);
            context.ExceptionHandled = true;
        private void HandleUnauthorizedAccessException(ExceptionContext context)
            var details = new ApiOkResponse(StatusCodes.Status401Unauthorized, "Unauthorized");
            context.Result = new ObjectResult(details)
                StatusCode = StatusCodes.Status401Unauthorized
            context.ExceptionHandled = true;
        private void HandleForbiddenAccessException(ExceptionContext context)
            var details = new ApiOkResponse(StatusCodes.Status403Forbidden, "Forbidden");
            context.Result = new ObjectResult(details)
                StatusCode = StatusCodes.Status403Forbidden
            context.ExceptionHandled = true;
        private void HandleUnknownException(ExceptionContext context)
            var details = new ApiOkResponse(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
            context.Result = new ObjectResult(details)
                StatusCode = StatusCodes.Status500InternalServerError
            context.ExceptionHandled = true;
    

    I want to have my responses return in this json format:

    "statusCode": 200, "requestId": "6b801f87-e985-4092-938e-3723e4c6bb50", "message": "An item has been added.", "result": { "id": 0, "name": "d"

    If there is any exception message it should go into message fields.

    Hi @Aakash Bashyal ,

    First, for the two methods, I prefer to use the clean one, because the method which have stacked overflow issue might cause the performance issue.

    Second, for apps that require specialized exception handling, the Microsoft document suggests using exceptions to modify the response or customizing the exception handling middleware. You could consider using them.

    You could refer the following threads:

    ASP.NET Core Web API exception handling

    How to wrap a route not found exception with the generic response model