将数组传递给asp net core web api动作方法HttpGet

问题描述 投票:5回答:3

我试图将一个整数数组发送到我的动作方法,代码如下所示:

[HttpGet]
    public async Task<IActionResult> ServicesByCategoryIds([FromQuery] int[] ids)
    {
        var services = await _accountsUow.GetServiceProfilesByCategoryIdsAsync(ids);
        return Ok(services);
    }

我这样称呼方法:https://localhost:44343/api/accounts/servicesbycategoryids?ids=1&ids=2

但是当我调用这个方法时,总是得到空数组,即使我在查询字符串中传递了ids。我正在使用.net核心2.1。

我用Google搜索的所有内容都表明这实际上就是这样做的方式。 。 。这里有什么我想念的吗?

谢谢!

asp.net-core .net-core asp.net-core-webapi
3个回答
6
投票

Array参数的绑定失败是Asp.Net Core 2.1下的一个已知问题,已被记录为Array or List in query string does not get parsed #7712

对于临时解决方法,您可以像下面那样设置FromQuery Name Property

        [HttpGet()]
    [Route("ServicesByCategoryIds")]
    public async Task<IActionResult> ServicesByCategoryIds([FromQuery(Name = "ids")]int[] ids)
    {            
        return Ok();
    }

2
投票

我创建了一个新的web api类,只有一个动作。

[Produces("application/json")]
[Route("api/accounts")]
public class AccountsController : Controller
{
    [HttpGet]
    [Route("servicesbycategoryids")]
    public IActionResult ServicesByCategoryIds([FromQuery] int[] ids)
    {
        return Ok();
    }
}

然后使用与您相同的网址:

http://localhost:2443/api/accounts/servicesbycategoryids?ids=1&ids=2

这是工作。


0
投票

您可以将自定义模型绑定器和ID实现为URI的一部分,而不是查询字符串中的一部分。

您的端点可能如下所示:/ api / accounts / servicesbycategoryids /(1,2)

public class ArrayModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            // Our binder works only on enumerable types
            if (!bindingContext.ModelMetadata.IsEnumerableType)
            {
                bindingContext.Result = ModelBindingResult.Failed();
                return Task.CompletedTask;
            }

            // Get the inputted value through the value provider
            var value = bindingContext.ValueProvider
                .GetValue(bindingContext.ModelName).ToString();

            // If that value is null or whitespace, we return null
            if (string.IsNullOrWhiteSpace(value))
            {
                bindingContext.Result = ModelBindingResult.Success(null);
                return Task.CompletedTask;
            }

            // The value isn't null or whitespace, 
            // and the type of the model is enumerable. 
            // Get the enumerable's type, and a converter 
            var elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
            var converter = TypeDescriptor.GetConverter(elementType);

            // Convert each item in the value list to the enumerable type
            var values = value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => converter.ConvertFromString(x.Trim()))
                .ToArray();

            // Create an array of that type, and set it as the Model value 
            var typedValues = Array.CreateInstance(elementType, values.Length);
            values.CopyTo(typedValues, 0);
            bindingContext.Model = typedValues;

            // return a successful result, passing in the Model 
            bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
            return Task.CompletedTask;
        }
    }

然后在你的行动中使用它:

[HttpGet("({ids})", Name="GetAuthorCollection")]
        public IActionResult GetAuthorCollection(
            [ModelBinder(BinderType = typeof(ArrayModelBinder))] IEnumerable<Guid> ids)
        {          
            //enter code here
        }

从多元化的课程中学到了这一点:使用ASP.NET Core构建RESTful API

© www.soinside.com 2019 - 2024. All rights reserved.