I'm creating a custom result filter that implements IAsyncResultFilter interface. In this filter I need the actual value returned by the Action, but I also need a parameter from that action (This parameter comes from the query string and is used for pagination). The thing is that I haven't found a way to get the parameter value directly from the ResultExecutingContext that is the variable I have available in the result filter implementation
I've tried to get the parameter value using the context.ActionDescriptor.Parameters, but it's a collection of ParameterDescriptor, and I haven't been able to get the actual value from it, just an instance of ParameterDescriptor
I've been able to get the mediaType from the headers and also the query string itself, but not the query string binded to the PagingModel type.
Is there any way to get this parameter from the ResultExecutingContext variable?
// Action from the ApiController
[HttpGet]
[AddPaginationHeader]
public async Task<IActionResult> Get([FromQuery]PagingModel pagingModel,
[FromHeader(Name = "Accept")]string mediaType) {
var pagedCollection = repository.GetPage(pagingModel);
var shapedCollection = ShapeCollectionOfData(pagedCollection);
return Ok(shapedCollection);
}
// AddPaginationHeader Implementation (Result Filter)
public Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) {
var result = context.Result as ObjectResult;
if (result?.Value != null && result?.StatusCode >= 200 &&
result?.StatusCode < 300) {
// Trying to get the pagingModel (but getting a ParameterDescriptor type)
var pagingModel = context.ActionDescriptor.Parameters.Where(t=>t.Name.Equals("pagingModel")).FirstOrDefault();
//Getting the media type
string mediaType = context.HttpContext.Request.Headers["Accept"]
// Getting the query string itself
string queryString = context.HttpContext.Request.QueryString.ToString();
//Implementation of the actual logic that needs the paging model
// ...
next();
}
return Task.CompletedTask;
}
Based on the answer of Tao I created a nice static method that allows you to get any parameter of any type from a Controller:
private static async Task<TParameter> GetParameterFromAction<TParameter>(ResultExecutingContext context, string parameterName) {
var parameterDescriptor = context.ActionDescriptor.Parameters.Where(t => t.Name.Equals(parameterName)).FirstOrDefault();
ControllerBase controller = context.Controller as ControllerBase;
TParameter parameter = (TParameter)Activator.CreateInstance(parameterDescriptor.ParameterType);
await controller.TryUpdateModelAsync(parameter, parameterDescriptor.ParameterType, string.Empty);
return parameter;
}
For getting PagingModel
, you could try TryUpdateModelAsync
like
public class AddPaginationHeader : Attribute, IAsyncResultFilter
{
// AddPaginationHeader Implementation (Result Filter)
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
//PagingModel model = new PagingModel();
//await controller.TryUpdateModelAsync(model);
var result = context.Result as ObjectResult;
if (result?.Value != null && result?.StatusCode >= 200 &&
result?.StatusCode < 300)
{
// Trying to get the pagingModel (but getting a ParameterDescriptor type)
var controller = context.Controller as Controller;
var parameterDescriptor = context.ActionDescriptor.Parameters.Where(t => t.Name.Equals("pagingModel")).FirstOrDefault();
var parameter = Activator.CreateInstance(parameterDescriptor.ParameterType);
await controller.TryUpdateModelAsync(parameter, parameterDescriptor.ParameterType, "");
var pagingModel = parameter;
//Getting the media type
string mediaType = context.HttpContext.Request.Headers["Accept"];
// Getting the query string itself
string queryString = context.HttpContext.Request.QueryString.ToString();
//Implementation of the actual logic that needs the paging model
// ...
next();
}
//return Task.CompletedTask;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With