微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在查询参数中接收锯齿状数组

如何解决在查询参数中接收锯齿状数组

我目前有一个控制器,其动作可以获取一些信息,该动作接收一个锯齿状数组作为查询参数来过滤信息,例如:[["Day",">=","01.01.2021"],["User","=","SomeUserId"]]

我当前的行动声明:

[HttpGet]
public async Task<object> Get(string[][] filters)
{
     ...
}

当我从客户端发出 AJAX 请求时,URL 按以下方式编码(DevTools 请求标头参数视图):

filters[0][]: Day
filters[0][]: >=
filters[0][]: 01.07.2021
filters[1][]: User
filters[1][]: =
filters[1][]: SomeUserId

网址编码仅供参考:...filters%5B0%5D%5B%5D=Day&filters%5B0%5D%5B%5D=%3E%3D&filters%5B0%5D%5B%5D=01.07.2021&filters%5B1%5D%5B%5D=User&filters%5B1%5D%5B%5D=%3D&filters%5B1%5D%5B%5D=SomeUserId

问题

我收到上述信息时的操作具有两个空字符串数组string[2][]的值。下图是来自过滤器变量的 VS 的调试打印屏幕。

enter image description here

我应该序列化吗?或者使用不同的结构?

解决方法

一种选择是将输入包装在一个类中

public class InputRequest
{
    public string Field { get; set; }
    public string Operator { get; set; }
    public string Value { get; set; }
}

然后使用自定义模型绑定器 -

class InputRequestModelBinder : IModelBinder
{
    static readonly JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType != typeof(List<InputRequest>)) return Task.CompletedTask;

        var modelName = bindingContext.ModelName;

        var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);

        if (valueProviderResult == ValueProviderResult.None) return Task.CompletedTask;

        bindingContext.ModelState.SetModelValue(modelName,valueProviderResult);

        var results = valueProviderResult.Select(t => JsonSerializer.Deserialize<InputRequest>(t,options)).ToList();

        bindingContext.Result = ModelBindingResult.Success(results);

        return Task.CompletedTask;

    }
}

最后,将模型绑定器挂钩到控制器方法 -

[HttpGet]
[Route("show")]
public string Show([ModelBinder(typeof(InputRequestModelBinder))] List<InputRequest> req)
{
    //do something
}

示例用法 -

/SomeController/show?req=%7B%0A%20%20%22field%22%3A%20%22name%22%2C%0A%20%20%22operator%22%3A%20%22%3D%22%2C%0A%20%20%22value%22%3A%20%22tom%22%0A%7D&req=%7B%0A%20%20%22field%22%3A%20%22age%22%2C%0A%20%20%22operator%22%3A%20%22%3C%22%2C%0A%20%20%22value%22%3A%20%2220%22%0A%7D

解码后的网址看起来像这样 -

/SomeController/show?req={
  "field": "name","operator": "=","value": "tom"
}&req={
  "field": "age","operator": "<","value": "20"
}

专业版 -

  • 您可以在 InputRequest
  • 中向 API 使用者明确说明预期值的合同

缺点 -

  • 您的请求查询字符串长度增加,因此您可能很快就会达到限制。虽然您可以将其转换为 POST 方法,但这违反了 REST 原则。
,

这是一个工作演示:

查看:

<button type="button" onclick="SendRequest()">Click</button>
@section Scripts
{
<script>
    function SendRequest() {
        var day = "Day";
        var simble = encodeURIComponent(">=");
        var date = "01.07.2021";
        var user = "UserName";
        var simble2 = "=";
        var id = "1";
        $.ajax({
            //url: "api/values?filters[0][0]=Day&filters[0][1]=>=&filters[0][2]=01.07.2021&filters[1][0]=User&filters[1][1]==&filters[1][2]=2"
            url: "api/values?filters[0][0]=" + day + "&filters[0][1]=" + simble + "&filters[0][2]=" + date + " &filters[1][0]=" + user + "&filters[1][1]=" + simble2 + "&filters[1][2]=" + id + "",type: 'GET',success: function (res) {
                alert("success");
            },error: function () {

            }
        })
    }
</script>
}

控制器:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    public void Get([FromQuery] string[][] filters)
    {

    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。