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

ASP Core Razor序列化ViewModel至JS时含ID属性触发返回undefined

问题核心诱因
  • 本质是ASP Core默认JSON序列化的命名规则和JS端的访问拼写不匹配
    ASP Core内置的Json.Serialize()默认基于System.Text.Json,默认开启驼峰命名转换。这个转换不是把整个字符串转成小写再调整首字母,而是仅把属性名的第一个字符转成小写,后续字符完全保留原大小写。
    你定义的C#属性是TestID,序列化后生成的JS对象键名是testID——首字母T转成小写t,后面的ID保持原大写不变。但你在JS代码里访问的是全小写的testid,和实际存在的键拼写不一致,自然返回undefined。
    这也解释了你的测试结果:只要把属性名里的ID后缀去掉,比如改成TestName,序列化后是testName,只要JS端访问的拼写和键名一致,代码就正常运行,本质和“id字样”没有特殊关联,只是ID后缀的大小写刚好踩中了不匹配的问题。
  • 那个“控制台能拿到、事件里拿不到”的诡异现象,是隐式全局变量的上下文差异导致的
    你代码里的ViewModelJS没有用let/const/var显式声明,属于执行时动态挂到window上的隐式全局变量。内联事件触发时的执行流程是:先给ViewModelJS赋值,再去访问属性;而你在控制台手动测试的时候,已经完成了至少一次事件触发,ViewModelJS已经被挂到全局上了,加上控制台的执行上下文和内联事件的解析规则有区别,就会出现两边结果不一致的错位感。
对应解决方法
  • 先把属性访问的拼写对齐
    要么直接按照序列化后的实际键名改,把ViewModelJS.testid改成ViewModelJS.testID,和驼峰转换的结果完全匹配。
    如果就是想让序列化出来的键名是全小写的testid,可以给C#的TestID属性加强制指定序列化名称的特性:
    [JsonPropertyName("testid")]
    public string TestID { get; set; }
    
    这样不管默认驼峰规则怎么转,序列化出来的键名就是你指定的testid,和JS端的访问完全对齐。
  • 规避隐式全局变量的坑
    给JS里的ViewModelJS加显式声明,比如:
    const ViewModelJS = @Html.Raw(Json.Serialize(Model));
    
    不要靠无声明的隐式全局挂载,减少不同执行上下文的解析歧义。
    尽量换掉内联onclick的绑定方式:给a标签加个固定id,用标准DOM API绑定点击事件,比如:
    <a id="testTrigger" href="#"> 点击此处 </a>
    <script>
      const triggerDom = document.getElementById('testTrigger');
      triggerDom.addEventListener('click', onClickTest);
    </script>
    
    这种绑定方式能彻底避开内联事件的作用域链问题,也能避免浏览器自动把DOM元素的id挂成全局变量导致的命名冲突。

内容的提问来源于stack exchange,提问作者Luca Prodan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 03:45:10