我正在尝试使用ApiController建模使用非顺序列表绑定复杂对象。除列表之外的所有字段都已正确设置,但列表包含一个元素(即使已发布两个列表元素)且元素为null。如果我使用完全相同的代码并将其指向我的操作方法中使用相同参数类型的MVC控制器,则一切都按预期工作。
由于我使用的是非顺序列表,因此我使用隐藏的“.Index”输入,如Phil Haack所述(http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx)
如果删除“.Index”输入并将列表作为从0开始的顺序列表发送,ApiController也会正确绑定列表。(此选项适用于测试,但在生产中不是一个很好的选项作为列表项可以由用户添加和删除,这就是我想使用非顺序列表的原因。)
据我所知,Web API控制器的参数绑定与MVC控制器不同,如here所述,但似乎非顺序列表应该在Web API控制器中正确绑定。我错过了什么吗?为什么相同的代码适用于MVC控制器而不适用于Web API控制器?如何在Web API中正确绑定非顺序列表?
以下是我的帖子参数:
Parameters application/x-www-form-urlencoded
BatchProductLots.Index 1
BatchProductLots.Index 2
BatchProductLots[1].BrandId 1
BatchProductLots[1].ContainerId 9
BatchProductLots[1].ContainerLot 123
BatchProductLots[1].PackageId 2
BatchProductLots[1].PlannedQuantity 0
BatchProductLots[1].ProducedQuantity 20
BatchProductLots[2].BrandId 1
BatchProductLots[2].ContainerId 9
BatchProductLots[2].ContainerLot 123
BatchProductLots[2].PackageId 1
BatchProductLots[2].PlannedQuantity 0
BatchProductLots[2].ProducedQuantity 1
BatchStatusId 1
LotNumber 070313
ProductionDate 07/03/2013
RecipeId 1
RecipeQuantity 1
SauceId 22
X-Requested-With XMLHttpRequest
以下是我的Web API控制器操作:
(request.BatchProductLots列表设置为一个元素(即使发布了两个元素)并且一个元素为null)
public Response Create(BatchCreateRequest request)
{
Response response = new Response();
try
{
Batch batch = Mapper.Map<Batch>(request);
batchService.Save(batch);
response.Success = true;
}
catch (Exception ex)
{
response.Message = ex.Message;
response.Success = false;
}
return response;
}
以下是我尝试绑定的列表的复杂对象:
public class BatchCreateRequest
{
public int BatchStatusId { get; set; }
public DateTime ProductionDate { get; set; }
public string LotNumber { get; set; }
public int SauceId { get; set; }
public int RecipeId { get; set; }
public int RecipeQuantity { get; set; }
public List<BatchProductLot> BatchProductLots { get; set; }
public class BatchProductLot
{
public int BrandId { get; set; }
public int ContainerId { get; set; }
public string ContainerLot { get; set; }
public int PackageId { get; set; }
public int PlannedQuantity { get; set; }
public int ProducedQuantity { get; set; }
}
}
答案 0 :(得分:1)
简短的回答,使用Web Api的Model Binder是不可能的。 MVC和Web Api使用不同的模型绑定器,Web Api模型绑定器仅适用于简单类型。
有关进一步说明的链接以及可能的解决方案,请参阅this answer。
更长的答案,创建System.Web.Http.ModelBinding.IModelBinder的自定义实现,并将Action的签名更改为以下
public Response Create([ModelBinder(CustomModelBinder)]BatchCreateRequest request)
答案 1 :(得分:0)
你真的需要设置Index
吗?在这种情况下,一种可能的解决方案可能是Index
类的BatchProductLot
部分。列表顺序无关紧要,Web Api应该能够绑定它。
另一个想法是使用application/json
内容类型并发送JSON。您可以使用Json.Net进行反序列化,模型绑定也可以。
如果您不想进行手动布线,请阅读Using an alternate JSON Serializer in ASP.NET Web API甚至使用此Nuget包WebApi Json.NET MediaTypeFormatter。