You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:26:48