繁体   English   中英

ASP.NET Core Pass可以在Controller上获取操作的对象的数量

[英]ASP.NET Core Pass Enumerable of objects to Get Action on Controller

我试图在ASP.NET Core 2.2中定义一个控制器动作

棘手的部分是我更喜欢这是一个GET端点,它必须接收的数据是一组自定义对象 这是我的示例代码:

[Route("api/example")]
[ApiController]
public class ExampleController : ControllerBase
{
    [HttpGet("getData")]
    [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetMarketData([FromQuery] MyObject[] queryData)
    {
        return this.Ok(0);
    }
}

public class MyObject
{
    public int A { get; set; }

    public int B { get; set; }
}

我希望这能绑定到类似的东西

http://localhost/api/example/getData/?queryData=[A=1,B=1],queryData=[A=2,B=2]

但是我似乎无法让它发挥作用。

(向URL发送请求,不解析对象,我在控制器中收到一个空数组)

我不确定这是否是解决此问题的最佳方式,也许我需要更改绑定数据的位置?

我唯一关心的是能够接收MyObject的数组(或某种集合 ),我可以处理并返回响应。 我也希望这是一个GET请求,因为,毕竟,我正在尝试查询此API并从中获取数据。

我知道我可以使用[FromBody]属性来使用它,但据我所知, GET请求不应该使用正文

任何帮助都很高兴。

您的GET请求必须按如下方式构建:

GET: /api/example/getData?queryData[0].A=1&queryData[0].B=2&queryData[1].A=3

与使用<form> s :)时的模型绑定非常相似

您的QueryString应如下所示:

/TestMe?queryData[0].A=1&queryData[0].B=1&queryData[1].A=2&queryData[1].B=2

如果你的代码如下:

public class MyObject
{
    public int A { get; set; }

    public int B { get; set; }
}

[Route("/TestMe")]
public IActionResult TestMe([FromQuery] MyObject[] queryData)
{ 
    return Json(queryData);
}

请注意,甚至不需要[FromQuery]

它没有用,因为没有集合类型的默认绑定器,你必须使用自定义绑定器。 我自己实现了一个通用数组模型绑定器,它在这里:

// generic array model binder
public class ArrayModelBinder<TType> : IModelBinder {
    public Task BindModelAsync(ModelBindingContext bindingContext) {
        if (bindingContext.ModelMetadata.IsEnumerableType) {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).ToString();
            if (!string.IsNullOrEmpty(value)) {
                var elementType = typeof(TType); 
                var typeConverter = TypeDescriptor.GetConverter(elementType);
                var splittedValues = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                var values = splittedValues.Select(t => typeConverter.ConvertFromString(t.Trim())).ToArray();
                var typedValues = Array.CreateInstance(elementType, values.Length);
                values.CopyTo(typedValues, 0);
                bindingContext.Model = typedValues;
                return SuccessBinding(bindingContext, typedValues);
            }
            return SuccessBinding(bindingContext, null);
        }
        return FailedBinding(bindingContext);
    }

    private static Task SuccessBinding(ModelBindingContext bindingContext, Array typedValues) {
        bindingContext.Result = ModelBindingResult.Success(typedValues);
        return Task.CompletedTask;
    }


    private static Task FailedBinding(ModelBindingContext bindingContext) {
        bindingContext.Result = ModelBindingResult.Failed();
        return Task.CompletedTask;
    }

要在Action上使用它,您只需使用这段代码:


public async Task<IActionResult> GetMarketData([ModelBinder(BinderType = typeof(ArrayModelBinder<object>))] MyObject[] queryData)
{
    return this.Ok(0);
}

我有这个实现的来源和我自己的库的回购中的其他东西随时检查出来CcLibrary.AspNetCore

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM