0

我正在使用带有 net-core API 控制器的 react-table,并且在抓取“排序”和“过滤”字段时遇到了一些麻烦。

我正在“onFetchData”方法中发送字段,如下所示:

Axios.get('/api/Dashboard/GetGiftCards', {
    params: {
        page: state.page,
        pageSize: state.pageSize,
        sorted: state.sorted,
        filtered: state.filtered
    }
})

例如,发送的包含 3 种排序类型和 3 个过滤器的查询字符串如下所示:

http://localhost:64963/api/Dashboard/GetGiftCards?page=0&pageSize=10&sorted[]=%7B%22id%22:%22giftCardType%22,%22desc%22:false%7D&sorted[]=%7B%22id%22:%22membershipId%22,%22desc%22:false%7D&sorted[]=%7B%22id%22:%22createdDate%22,%22desc%22:false%7D&filtered[]=%7B%22id%22:%22imisId%22,%22value%22:%223%22%7D&filtered[]=%7B%22id%22:%22giftCardType%22,%22value%22:%22E%22%7D

服务器端,我的控制器设置如下:

[HttpGet("GetGiftCards")]
public async Task<IActionResult> GetCardsAsync([FromQuery] GetGiftCardsRequest request)

我的任何请求对象如下

public class GetGiftCardsRequest
{
    [JsonProperty(PropertyName = "page")]
    public int Page { get; set; }

    [JsonProperty(PropertyName = "pageSize")]
    public int PageSize { get; set; }

    [JsonProperty(PropertyName = "sorted")]
    public IEnumerable<string> sorted { get; set; }

    [JsonProperty(PropertyName = "filtered")]
    public string[] Filters { get; set; }

    public class Sorting
    {
        [JsonProperty(PropertyName = "id")]
        public string Id { get; set; }

        [JsonProperty(PropertyName = "desc")]
        public bool Descending { get; set; }
    }

    // Filtering object not created yet
}

我正在努力让控制器使用 URL,但到目前为止我还没有在网上找到任何东西。我在想我可能应该只使用 Regex 构建自己的自定义过滤器,但我想我会先在这里发布,看看是否有其他人提出了解决方案?

4

1 回答 1

0

我找到了解决方法。我决定手动读取查询字符串并将预期值放在请求对象中。

这是属性在我的方法上的外观

[HttpGet("GetGiftCards")]
[ReactTableFilter("sorted", "filtered", "request")]
public async Task<IActionResult> GetGiftCardsAsync([FromQuery] GetGiftCardsRequest request)

参数是来自 react-table 的对象的“排序”列表、来自 react-table 的对象的“过滤”列表以及我们要填充的 ActionArgument 的名称。

这是属性的代码:

public class ReactTableFilterAttribute : ActionFilterAttribute
{
    /// <summary>
    /// </summary>
    private readonly string _argumentName;

    /// <summary>
    ///     The filter query variable name
    /// </summary>
    private readonly string _filterName;

    /// <summary>
    ///     The sorting query variable name
    /// </summary>
    private readonly string _sortedName;

    /// <summary>
    ///     Creates a new instance of this attribute
    /// </summary>
    /// <param name="sortedName">The name of the sorted variable list</param>
    /// <param name="filterName">The name of the filtered variable list</param>
    /// <param name="argumentName">The name of the <see cref="GetGiftCardsRequest" /> request object we want to full</param>
    public ReactTableFilterAttribute(string sortedName, string filterName, string argumentName)
    {
        if (string.IsNullOrEmpty(sortedName))
        {
            throw new ArgumentException(nameof(sortedName));
        }

        if (string.IsNullOrEmpty(filterName))
        {
            throw new ArgumentException(nameof(filterName));
        }

        if (string.IsNullOrEmpty(argumentName))
        {
            throw new ArgumentException(nameof(argumentName));
        }

        _argumentName = argumentName;
        _filterName = filterName;
        _sortedName = sortedName;
    }

    /// <inheritdoc />
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        GetGiftCardsRequest toFill = (GetGiftCardsRequest) context.ActionArguments[_argumentName];

        toFill.Sorted =
            GetArrayOfObjects<GetGiftCardsRequest.Sorting>(context.HttpContext.Request.QueryString.Value,
                _sortedName);
        toFill.Filters =
            GetArrayOfObjects<GetGiftCardsRequest.Filtering>(context.HttpContext.Request.QueryString.Value,
                _filterName);

        base.OnActionExecuting(context);
    }

    /// <summary>
    ///     Serializes an array of the specified objects from the given <paramref name="queryString" /> that have the given
    ///     <paramref name="name" />
    /// </summary>
    /// <typeparam name="T">The type of the object you want to serialize</typeparam>
    /// <param name="queryString">The query string to seach</param>
    /// <param name="name">Name of the array parameter to pull</param>
    /// <returns>The array of items if any exist</returns>
    private T[] GetArrayOfObjects<T>(string queryString, string name)
    {
        string pattern = name + @"\[\]=(.*?)&";
        MatchCollection matches = Regex.Matches(queryString + "&", pattern);
        List<T> newList = new List<T>();

        foreach (Match m in matches)
        {
            string sortedObj = HttpUtility.UrlDecode(m.Groups[1].Value);
            T deserialized = JsonConvert.DeserializeObject<T>(sortedObj);

            newList.Add(deserialized);
        }

        return newList.ToArray();
    }
}

我意识到这可以被清理很多以使其更加抽象。如果我回到它,我将粘贴更新的代码。

于 2018-03-06T15:53:04.603 回答