理想情况下,我希望获得以下格式的网址:
/api/categories/1,2,3...N/products
这将返回指定类别的所有产品。使用多个类别ID进行一次API调用可以节省几次数据库调用,从而提高性能。
我可以通过以下方式轻松实现这一点。
public HttpResponseMessage GetProducts(string categoryIdsCsv)
{
// <1> Split and parse categoryIdsCsv
// <2> Get products
}
然而,这看起来并不像一个干净的解决方案,并且可能违反SRP原则。我也尝试使用ModelBinder
,但它会在查询字符串中添加参数。
问题:
如果您需要进一步澄清,请与我们联系。
答案 0 :(得分:1)
我刚刚找到了问题的答案。使用Route
时,ModelBinder
属性缺少参数。
[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;
}
答案 1 :(得分:0)
我们可以使用Post方法
[RoutePrefix(&#34; api / categories&#34;)] 公共类TestController { [HttpPost] [路线(&#34; getProducts&#34;)]
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 );
}
}
答案 2 :(得分:0)