Restful Web Api参数作为int数组

本文关键字:int 数组 参数 Web Api Restful | 更新日期: 2023-09-27 18:03:40

理想情况下,我想有一个URL在以下格式:

/api/categories/1,2,3...N/products

这将返回指定类别的所有产品。使用一个具有多个类别id的API调用可以节省多次数据库调用,从而提高性能。

我可以用下面的方法轻松实现它。

public HttpResponseMessage GetProducts(string categoryIdsCsv)
{
    // <1> Split and parse categoryIdsCsv
    // <2> Get products
}

然而,这看起来不像一个干净的解决方案,并且可能违反SRP原则。我也尝试使用ModelBinder,但它添加参数查询字符串。

问题:

  1. 是否有一个干净的方式来实现这样的URL结构?
  2. 或者是否有一种不同的/更好的方法来检索多个类别的所有产品?

如果需要进一步的说明,请告诉我。

Restful Web Api参数作为int数组

我刚刚找到了我问题的答案。使用ModelBinder时,Route属性缺少参数

[Route("api/categories/{categoryIds}/products")]
public HttpResponseMessage GetProducts([ModelBinder(typeof(CategoryIdsModelBinder))] CategoryIds categoryIds)
{
    // <2> Get products using categoryIds.Ids
}

CategoryIds =

public class CategoryIds
{
    public List<int> Ids{ get; set; }
}

CategoryIdsModelBinder则是

public class CategoryIdsModelBinder : IModelBinder
    {
        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType != typeof(CategoryIds))
            {
                return false;
            }
            var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (val == null)
            {
                return false;
            }
            var key = val.RawValue as string;
            if (key == null)
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Wrong value type");
                return false;
            }
            var values = val.AttemptedValue.Split(',');
            var ids = new List<int>();
            foreach (var value in values)
            {
                int intValue;
                int.TryParse(value.Trim(), out intValue);
                if (intValue > 0)
                {
                    ids.Add(intValue);
                }
            }
            if (ids.Count > 0)
            {
                var result = new CategoryIds
                {
                    Ids= ids
                };
                bindingContext.Model = result;
                return true;
            }
            bindingContext.ModelState.AddModelError(
                bindingContext.ModelName, "Cannot convert value to Location");
            return false;
        }

我们可以使用Post方法

[RoutePrefix ("api/categories")]公共类TestController{(HttpPost)[Route ("getProducts")]

    public HttpResponseMessage GetProducts ( HttpRequestMessage request )
    {
        HttpResponseMessage  message               = null;
        string               input                 = string.Empty;
        input  = request.Content.ReadAsStringAsync ().Result;
         var ids = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>> ( input );
    }
}

不幸的是,Web API不能将数据解析为数组或某种自定义对象。

如果你想将url参数解析为数组,你可以尝试这样做:

  1. 写你自己的路由约束,它将读取和转换你的参数从字符串到int/string/任何数组;

  2. 编写您的自定义类型转换器,并使用它与您的数据模型;

  3. 写你的值提供者,也使用它与你的数据模型

  4. 使用参数绑定

此外,您可以始终使用查询参数,这永远不会违反REST原则:)

请查看此处和此处的更多详细信息

希望有帮助