Asp.Net MVC5中Underscore.js模板变量在HTML Helper未解析问题
你遇到的核心问题是Razor视图引擎会优先解析服务器端代码,而Underscore.js的模板语法<%= No%>和Razor的语法撞车了——Razor不认识这个客户端模板变量,所以直接把[<%= No%>].AccountId原样输出到HTML里,根本没轮到Underscore去替换它。
下面给你几个实用的解决办法:
方法一:让Razor跳过Underscore模板语法的解析
用Html.Raw()告诉Razor不要处理Underscore的模板标记,直接把它们原封不动输出到客户端,这样Underscore就能正常替换变量了。修改你的DropDownList代码:
@Html.DropDownList(Html.Raw("[<%= No%>].AccountId"), new SelectList(ViewBag.Accounts, "Id", "AccountName"), new { @class = "form-control select2" })
原理很简单:Html.Raw()会阻止Razor对括号里的内容进行编码或解析,让[<%= No%>].AccountId完整出现在客户端的模板中,Underscore就能识别并替换<%= No%>了。
方法二:修改Underscore的模板分隔符,避开Razor的语法
Underscore允许自定义模板的分隔符,我们可以把默认的<% %>换成Razor不识别的符号,比如{{ }}。在你的JS代码开头加上这段配置:
_.templateSettings = { interpolate: /\{\{=(.+?)\}\}/g, // 用于变量替换的语法 evaluate: /\{\{(.+?)\}\}/g // 用于逻辑代码的语法 };
然后把模板里所有的<%= No%>改成{{= No}},包括DropDownList的参数:
<script type="text/template" id="template"> <div class="row" id="row-{{= No}}"> <div class="col-md-3 form-group"> <label>Account</label> @Html.DropDownList("[{{= No}}].AccountId", new SelectList(ViewBag.Accounts, "Id", "AccountName"), new { @class = "form-control select2" }) </div> <!-- 其他表单字段保持修改后的语法 --> <div class="col-md-1"> <button class="btn btn-danger btn-sm adjust-btn" onclick="RemoveRow('row-{{= No}}')"><i class="glyphicon glyphicon-remove"></i></button> </div> </div> </script>
这样Razor会把{{= No}}当成普通文本输出,Underscore用新的分隔符处理变量替换,完美避免冲突。
方法三:用纯HTML手动构建下拉框,完全绕开Razor的HtmlHelper
如果不想折腾语法,也可以放弃Razor的Html.DropDownList,手动写select标签,把服务器端的Accounts转换成客户端能处理的JSON数据。
首先在Razor视图里把ViewBag.Accounts转成JSON:
<script> // 把服务器端的Accounts集合转成客户端可用的JSON var accounts = @Html.Raw(Json.Encode(ViewBag.Accounts)); </script>
然后修改Underscore模板,用Underscore的循环生成下拉选项:
<script type="text/template" id="template"> <div class="row" id="row-<%= No%>"> <div class="col-md-3 form-group"> <label>Account</label> <select name="[<%= No%>].AccountId" class="form-control select2"> <% _.each(accounts, function(account) { %> <option value="<%= account.Id %>"><%= account.AccountName %></option> <% }); %> </select> </div> <!-- 其他表单字段保持不变 --> </div> </script>
这种方式让所有模板逻辑都由Underscore处理,彻底避免和Razor的语法冲突,适合需要更多客户端控制的场景。
内容的提问来源于stack exchange,提问作者Rizwan Ijaz

