Search code examples
.netasp.net-core.net-coresystem.reflection

Return Generic response object/json for all the controllers methods using .NetCore middleware


My controller:

public class MyController : ControllerBase
{
  [HttpGet("/getResponse/{userId}")]
  public async Task<MyResponse> GetResponseAsync(long userId)
  {
     return await _myService.GetResponseAsync(userId);
  }
  [HttpGet("/getUser/{userId}")]
  public async Task<MyUser> GetUserAsync(long userId)
  {
     return await _myService.GetUserAsync(userId);
  }
}

though my controller returns an object of MyResponse or MyUser class, I want to return a custom generic response object i.e.

public class ApiResponse
{
  public object Response { get; set; }
  public bool IsSuccess { get; set; }
  public IList<string> Errors { get; set; }
  public ApiResponse(object response, bool success, IList<string> errors = null)
  {
     this.Response = response;
     this.IsSuccess = success;
     this.Errors = errors;
  }
    
  public ApiResponse()
  {
  }
}

I tried to use IActionFilter's OnActionExecuted(ActionExecutedContext context) to read the response object, but I don't see any response of MyUser or MyResponse object in the body when i debug for variable a.

public void OnActionExecuted(ActionExecutedContext context)
        {
            ApiResponse _response = new ApiResponse();
            var httpResponse = context.HttpContext.Response;
            if (httpResponse != null)
            {
                if (httpResponse.StatusCode == 200)
                {
                   var a = httpResponse.Body;
                }
            }
        }

Is there a way to read the type of object and assign that particular object to the ApiResponse.response proeperty?


Solution

  • There are a few types of MVC filters, and IActionFilter is not the best tool for this job. What you want is ResultFilter.

    Please take a look at official documentation here https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0 for more details.

    An answer provided here may also be useful for you: https://stackoverflow.com/a/64725441/2895299

    However, it is going to work with your filter implementation as well, you're just looking for a response object in wrong place. Your object is going to be accessible under:

    context.Result
    

    Response in HttpContext object is going to be accessible later, not at filter stage of MVC pipeline. Please observe, that context.HttpContext.Response.HasStarted is equal to false.

    What is more, response / request available in HttpContext is not going to be typed (binded to model), it would be for example in JSON format like {"userId": "123", "username": "Foo" }