如何在CSHTML中将含列表与参数的ViewModel绑定到控制器Action
问题描述
我有如下包含列表和嵌套类的ViewModel:
public class MyViewModel { public List<Guid> Ids{ get; set; } public History HistoryRecord{ get; set; } } public class History { public string UserName{ get; set; } public string Email{ get; set; } }
需要将上述数据提交到以下控制器Action:
public async Task<IActionResult> myAction([Bind("Ids","UserName","Email")] MyViewModel viewModel) { // 业务逻辑 }
我通过以下输入框获取UserName和Email的值:
<input type="text" class="form-control child " name="name" id="nameTextbox" placeholder="name" required /> <input type="text" class="form-control child " name="email" id="emailTextbox" placeholder="email" required />
尝试用Url.Action实现数据提交但未成功,不清楚如何传递多值:
<button type="submit" class="btn btn-primary" id="confirm" onclick="location.href='@Url.Action("myAction","myController", values: new {Ids= @Model.Ids.ToList(), Name = ? , Emil = ? })'">confirm</button>
解决方案
方式一:表单提交(推荐)
这是ASP.NET Core中处理复杂模型提交的常规方案,能自动完成模型绑定:
- 修正输入框的name属性
要匹配Action中Bind指定的字段名,把输入框的name改成UserName和Email:
<input type="text" class="form-control child" name="UserName" id="nameTextbox" placeholder="name" required /> <input type="text" class="form-control child" name="Email" id="emailTextbox" placeholder="email" required />
- 添加隐藏字段传递Ids列表
为每个Guid生成一个隐藏输入框,名称设为Ids,表单提交时会自动绑定到ViewModel的Ids列表:
@foreach (var id in Model.Ids) { <input type="hidden" name="Ids" value="@id.ToString()" /> }
- 用表单包裹控件并提交
不需要用onclick跳转,直接通过表单指定目标Action:
<form asp-action="myAction" asp-controller="myController" method="post"> <input type="text" class="form-control child" name="UserName" id="nameTextbox" placeholder="name" required /> <input type="text" class="form-control child" name="Email" id="emailTextbox" placeholder="email" required /> @foreach (var id in Model.Ids) { <input type="hidden" name="Ids" value="@id.ToString()" /> } <button type="submit" class="btn btn-primary" id="confirm">confirm</button> </form>
提示:POST请求比GET更适合传递复杂数据,避免列表参数的格式问题。
方式二:AJAX提交(无刷新场景)
如果需要页面不刷新提交数据,可以用JavaScript收集数据后发送AJAX请求:
- 保留输入框和按钮(移除onclick)
<input type="text" class="form-control child" name="UserName" id="nameTextbox" placeholder="name" required /> <input type="text" class="form-control child" name="Email" id="emailTextbox" placeholder="email" required /> <button type="button" class="btn btn-primary" id="confirm">confirm</button> @Html.AntiForgeryToken() <!-- 添加防伪令牌,防止跨站伪造请求 -->
- 编写JavaScript提交逻辑
收集输入框值和Ids列表,通过POST请求提交到Action:
document.getElementById('confirm').addEventListener('click', function() { // 组装提交数据 var data = { Ids: @Json.Serialize(Model.Ids), UserName: document.getElementById('nameTextbox').value, Email: document.getElementById('emailTextbox').value }; // 发送AJAX请求 fetch('@Url.Action("myAction", "myController")', { method: 'POST', headers: { 'Content-Type': 'application/json', 'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value }, body: JSON.stringify(data) }) .then(response => response.json()) .then(result => { // 处理返回结果 console.log(result); }) .catch(error => { console.error('提交失败:', error); }); });
你之前的方式失败原因
Url.Action是服务器端渲染生成的,无法获取客户端输入框的动态值(用户输入的名称、邮箱),所以没法直接在values参数里填写这些内容。- GET请求传递列表参数需要特殊格式(比如
Ids[0]、Ids[1]),用Url.Action生成会非常繁琐,POST请求则不需要额外处理列表的格式问题。
内容的提问来源于stack exchange,提问作者dros
相关产品推荐
相关产品推荐

