ASP.NET MVC参数绑定:如何将列表或数组发布到控制器方法?

问题描述:

我似乎无法弄清楚如何通过POST将一个GUID数组作为参数传递给ASP.NET MVC控制器。我错过了什么?有没有更简单的方法来做到这一点?ASP.NET MVC参数绑定:如何将列表或数组发布到控制器方法?

在我AngularJS标记:

<form method="post" action="/Foo/Bar" > 
    <input name="itemIds" type="hidden" value="{{ ctrl.itemIds }}"> 
    <button type="submit">Submit</button> 
</form> 

导致HTML:

<form method="post" action="/Foo/Bar" > 
    <input name="itemIds" type="hidden" value="[&quot;8cd52539-c371-402a-b8be-12775f03ab68&quot;,&quot;8c97f9e0-666c-41ba-a914-72815745d1f0&quot;]"> 
    <button type="submit">Submit</button> 
</form> 

在我FooController的:

[System.Web.Mvc.HttpPost] 
public ActionResult Bar([FromBody]Guid[] itemIds) => ... 

当调试上面,我的HTTP POST似乎是正确的,但我在Bar得到空itemIds。你能帮我改变这个工作吗?考虑到我的JS模型中已经有了一组GUID,是否有更好的方法来填充我的请求体?

+0

我相信'Guid'会出现一个'string',那么你会投入一个'Guid'。出于某种奇怪的原因,当你像上面那样使用默认的MVC参数时,它通常不会安全地转换类型。 – Greg

+0

这让我难过。将参数更改为字符串而不是Guid []会导致带有反斜线,括号和逗号的单个字符串,这更糟糕。任何想法的更优雅的方式 - 至少有一个我可以得到一个字符串数组或列表而不是一个单一的字符串? –

+0

你可以创建一个基本的Json对象,然后通过它。使用单个反序列化,以避免一些疯狂的编码。'{Id =''}'类型的对象,一个具有Id属性的基本对象。显然有效的Json会有所帮助。 – Greg

这里是真的发生了:

itemIds被发布为一个单一的字符串到控制器。为什么?因为itemIds不被解释为数组。如果你想要一个数组,你需要有多个名为itemIds[0]itemsIds[1]等的隐藏值。这里是一个快速测试,证明我所说的实际上是发生了什么:

创建一个这样的表单。看看我们创建了一个名为itemIdsOld一个隐藏的价值,然后2个命名为itemIds[0]itemIds[1]更多隐藏值:

<form method="post" action="/Foo/Bar"> 
    <input name="itemIdsOld" type="hidden" value="[&quot;f8b21933-419c-4bdd-b5b6-75295ff65612&quot;,&quot;67bb1d75-ae78-49e4-bc29-ee82a51bb9a1&quot;]"> 
    <input name="itemIds[0]" type="hidden" value="f8b21933-419c-4bdd-b5b6-75295ff65612"> 
    <input name="itemIds[1]" type="hidden" value="67bb1d75-ae78-49e4-bc29-ee82a51bb9a1"> 
    <button type="submit">Submit</button> 
</form> 

创建这样一个控制器:

[System.Web.Mvc.HttpPost] 
public ActionResult Index(string[] itemIdsOld, Guid[] itemIds) 
{ 
    return null; 
} 

当您发布以上表格,你会发现,在itemIdsOld中创建单个字符串,并且它将具有作为string的两个Guid。然而,第二个,因为我们创建的控件名为itemIds[0]itemIds[1]将按照您的预期转换为Guid[] itemIds

我不知道如何在角做到这一点,但与C#和剃刀,一个办法做到这一点会是这样:

@using System.Collections.Generic 
@{ 
    var guids = new List<Guid> { Guid.NewGuid(), Guid.NewGuid() }; 
} 
<form method="post" action="/Test/Index"> 
    <input name="itemIdsOld" type="hidden" value="[&quot;f8b21933-419c-4bdd-b5b6-75295ff65612&quot;,&quot;67bb1d75-ae78-49e4-bc29-ee82a51bb9a1&quot;]"> 
    @{ 
     for (int i = 0; i < guids.Count; i++) 
     { 
      <input name="itemIds[@i]" type="hidden" value="@guids[i]"> 
     } 
    } 
    <button type="submit">Submit</button> 
</form> 

我硬编码的GUID,但你可以从得到这个模型......你明白了。


或者,你可以使用JavaScript拦截表单提交和itemIds检索值,并把它变成一个数组,并提交到控制器,将工作过。

+0

是的。我可以使用ng-repeat与Angular做到这一点,谢谢 - 这可能是最好的方法。有什么办法可以考虑做一个POST,只提供JSON正文,而不是彻底隐藏表单域? –

+0

我不确定我是否通过隐藏的表单字段获取了您的意思。 – CodingYoshi

+0

它看起来像一个Rube Goldberg机器,通过AngularJS设置隐藏表单域,这样当我拥有所有需要在我的Javascript代码状态下执行POST的数据时,我可以POST。如果这是AJAX,我只需创建AJAX请求并完成,但是我收集不到使用Javascript代码创建非AJAX POST请求的方法。 –