ASP.NET Core中如何通过JavaScript将值从View传递到Controller方法?
问题分析与解决方案
首先得指出你当前代码里的核心问题:你在JavaScript里直接给@Model赋值是行不通的。@Model是Razor在服务器端渲染页面时使用的变量,页面渲染完成后,客户端的JavaScript无法直接修改服务器端的Model对象——两者运行在完全不同的上下文里。当用户点击联系人时,你的JS代码里的@Model.PhoneNr = contactNumber在页面渲染时就已经被解析成服务器端的初始值了,根本不会在客户端触发时更新Model。
下面给你两种可行的解决方案,根据你的需求选择:
方案一:使用表单提交(适合需要同步刷新页面的场景)
这个方案会把选中的联系人信息存储在隐藏表单字段里,提交时一起传给SendMessage方法:
1. 修改页面的联系人渲染代码
保持foreach循环,但调整onclick事件,让它把选中的手机号和ContactId填充到表单的隐藏字段中:
<!-- 先添加一个隐藏表单,用来存储选中的联系人信息和消息内容 --> <form id="messageForm" asp-action="SendMessage" method="post"> <input type="hidden" id="selectedPhoneNumber" asp-for="PhoneNr" /> <input type="hidden" id="selectedContactId" asp-for="ContactId" /> <div class="message-input"> <input type="text" asp-for="MessageBody" placeholder="输入消息..." /> <button type="submit">发送消息</button> </div> </form> <!-- 联系人列表渲染 --> @foreach (var contact in Model.Contacts) { <div class="chatperson" onclick="selectContact('@contact.PhoneNumber', '@contact.ContactId')"> <div class="namechat"> <div class="pname"> @contact.Name <a asp-action="ContactDetails" asp-route-id="@contact.ContactId" class="glyphicon glyphicon-info-sign"></a> <a asp-action="EditContact" asp-route-id="@contact.ContactId" class="glyphicon glyphicon-pencil "></a> </div> <div class="lastmsg">@contact.PhoneNumber</div> </div> </div> }
2. 编写JavaScript方法填充表单字段
function selectContact(contactNumber, contactId) { // 把选中的值填充到表单的隐藏字段中 document.getElementById('selectedPhoneNumber').value = contactNumber; document.getElementById('selectedContactId').value = contactId; }
3. 优化Controller的SendMessage方法
可以简化参数,直接从ViewModel里获取所需值(确保你的MessengerViewModel包含PhoneNr、ContactId、MessageBody属性):
public IActionResult SendMessage(MessengerViewModel model) { var currentUserId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value; if (ModelState.IsValid) { var newMessage = new Message { UserId = currentUserId, ContactId = model.ContactId, Body = model.MessageBody, Date = DateTime.Now, isDelivered = true }; _messageService.AddMessage(newMessage); var smsSender = new AtSmsSender(); smsSender.SendSms(model.PhoneNr, model.MessageBody); return RedirectToAction("Index", "Messenger"); } return RedirectToAction("Index", "Messenger"); }
方案二:使用AJAX异步发送(适合无刷新发送消息的场景)
如果不想刷新页面,可以用AJAX把数据异步提交到Controller:
1. 修改联系人点击事件和添加发送按钮
<!-- 添加防伪令牌,防止CSRF攻击 --> @Html.AntiForgeryToken() <!-- 消息输入区域 --> <div class="message-input"> <input type="text" id="messageBody" placeholder="输入消息..." /> <button onclick="sendMessage()">发送消息</button> </div> <!-- 联系人列表 --> @foreach (var contact in Model.Contacts) { <div class="chatperson" onclick="selectContact('@contact.PhoneNumber', '@contact.ContactId')"> <!-- 内容和之前一致 --> <div class="namechat"> <div class="pname"> @contact.Name <a asp-action="ContactDetails" asp-route-id="@contact.ContactId" class="glyphicon glyphicon-info-sign"></a> <a asp-action="EditContact" asp-route-id="@contact.ContactId" class="glyphicon glyphicon-pencil "></a> </div> <div class="lastmsg">@contact.PhoneNumber</div> </div> </div> }
2. JavaScript代码
// 存储选中的联系人信息 let selectedPhoneNumber = ''; let selectedContactId = ''; function selectContact(contactNumber, contactId) { selectedPhoneNumber = contactNumber; selectedContactId = contactId; } function sendMessage() { const messageBody = document.getElementById('messageBody').value; // 验证是否选中了联系人并输入消息 if (!selectedPhoneNumber || !selectedContactId || !messageBody) { alert('请先选择联系人并输入消息内容'); return; } // 发送AJAX请求 fetch('/Messenger/SendMessage', { method: 'POST', headers: { 'Content-Type': 'application/json', 'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value }, body: JSON.stringify({ PhoneNr: selectedPhoneNumber, ContactId: selectedContactId, MessageBody: messageBody }) }) .then(response => { if (response.ok) { // 发送成功后的操作:清空输入框、提示用户 document.getElementById('messageBody').value = ''; alert('消息发送成功'); } else { alert('消息发送失败,请重试'); } }) .catch(error => { console.error('请求出错:', error); alert('请求出错,请稍后再试'); }); }
3. 调整Controller方法支持AJAX
需要确保方法可以接收JSON格式的参数,并且返回合适的JSON结果:
[HttpPost] public IActionResult SendMessage([FromBody] MessengerViewModel model) { var currentUserId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value; if (ModelState.IsValid) { var newMessage = new Message { UserId = currentUserId, ContactId = model.ContactId, Body = model.MessageBody, Date = DateTime.Now, isDelivered = true }; _messageService.AddMessage(newMessage); var smsSender = new AtSmsSender(); smsSender.SendSms(model.PhoneNr, model.MessageBody); return Json(new { success = true }); } return Json(new { success = false, errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage) }); }
额外注意点
- 确保你的
MessengerViewModel类包含PhoneNr、ContactId、MessageBody这三个属性,这样ASP.NET Core的Model绑定才能正常工作。 - 使用AJAX时必须携带防伪令牌(
RequestVerificationToken),否则会被ASP.NET Core的CSRF防护机制拦截。
内容的提问来源于stack exchange,提问作者Daniel Žeimo
相关产品推荐
相关产品推荐

