Как я могу получить параметр действия из ResultExecutingContext при использовании фильтра - PullRequest
1 голос
/ 05 июня 2019

Я создаю пользовательский фильтр результатов, который реализует интерфейс IAsyncResultFilter . В этом фильтре мне нужно фактическое значение, возвращаемое действием, но мне также нужен параметр из этого действия (этот параметр берется из строки запроса и используется для разбивки на страницы). Дело в том, что я не нашел способа получить значение параметра напрямую из ResultExecutingContext , то есть переменной, которую я имею в наличии в реализации фильтра результатов

Я пытался получить значение параметра, используя context.ActionDescriptor.Parameters, но это набор ParameterDescriptor, и я не смог получить из него фактическое значение, просто экземпляр ParameterDescriptor

Мне удалось получить mediaType из заголовков, а также саму строку запроса, но не строку запроса, связанную с типом PagingModel.

Есть ли способ получить этот параметр из переменной ResultExecutingContext ?


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

Ответы [ 2 ]

1 голос
/ 06 июня 2019

Для получения PagingModel, вы можете попробовать TryUpdateModelAsync как

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;
    }
}
0 голосов
/ 07 июня 2019

Основываясь на ответе Дао, я создал хороший статический метод, который позволяет вам получить любой параметр любого типа из контроллера:

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

...