核心概念:什么是服务器标记?
在 ASP.NET Web Forms 中,服务器标记是那些以 runat="server" 属性标记的 HTML 元素,这告诉 ASP.NET 引擎,这个元素不是一个普通的静态 HTML 标签,而是一个可以被服务器端代码访问、控制和操作的对象。
<%-- 这是一个普通的 HTML 标签 --%>
<div>你好,世界!</div>
<%-- 这是一个服务器控件 --%>
<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox>
<%-- 这是一个带有服务器端代码块的 HTML 标签 --%>
<div id="myDiv" runat="server">
欢迎, <asp:Label ID="lblWelcome" runat="server" Text="访客"></asp:Label>
</div>
错误原因分析及常见情况
这个错误信息通常指向以下几种语法问题:
最常见的原因:<%= 和 <%#> 的混淆
这是初学者最容易犯的错误。
-
<%=数据绑定表达式:用于在页面渲染时输出一个表达式的值,它必须位于 HTML 标签的内部,在<span>或<div>的内容里。
-
正确用法:
<h1>欢迎, <%= User.Identity.Name %></h1> <asp:Label Text="当前时间: <%= DateTime.Now %>" runat="server" />
-
错误用法 (会导致 "格式不正确"):
<%-- 错误:不能作为顶级标签 --%> <%= DateTime.Now %> <%-- 错误:不能放在另一个服务器控件的属性外面 --%> <asp:TextBox ID="txtDate" Text="<%= DateTime.Now %>" runat="server" />
-
如何修正:
- 如果想给服务器控件的属性赋值,应该使用
OnDataBinding事件或者在后台代码中设置。 - 如果想显示值,就用
<%=包裹,并确保它在 HTML 内容中。
- 如果想给服务器控件的属性赋值,应该使用
-
-
<%#>数据绑定语法:通常与DataBinder.Eval()结合使用,在数据绑定(如GridView,Repeater的ItemDataBound事件)期间执行,它不能在页面加载时直接执行,必须通过DataBind()方法触发。- 正确用法 (在 Repeater 模板中):
<asp:Repeater ID="rptProducts" runat="server"> <ItemTemplate> <div> 产品名: <%# Eval("ProductName") %> 价格: <%# Eval("Price", "{0:C}") %> </div> </ItemTemplate> </asp:Repeater> - 错误用法:
<%-- 错误:在 Repeater 之外使用,且没有触发 DataBind --%> <div>当前产品: <%# Eval("ProductName") %></div> - 如何修正:
- 确认你是在数据绑定场景下使用
<%#>。 - 如果想在页面加载时显示数据,请使用
<%=。
- 确认你是在数据绑定场景下使用
- 正确用法 (在 Repeater 模板中):
服务器端代码块语法错误
<% ... %>:用于执行服务器端代码,但不直接输出任何内容。<%= ... %>:执行代码并输出结果。<%: ... %>:从 .NET 4.0 开始引入,是<%=的安全版本,会自动对输出内容进行 HTML 编码,防止 XSS 攻击。<%@ ... %>:用于页面指令,如Page,Import,Assembly等。
常见错误:
-
缺少结束符
%>:
<% if (IsPostBack) { // 错误:缺少 %} // 一些代码 <%-- 这里会报错 --%> -
符号不匹配:
<% if (true) { // 代码块 } // 缺少结束的 } %> -
在代码块中使用了错误的语法:
<% // 错误:在 C# 中不能使用 'then' if (x > 5) then { // ... } %>
标签属性和值的引号问题
当在服务器控件的属性值中使用服务器端表达式时,很容易出错。
-
错误用法:
<!-- 错误:内外层引号冲突 --> <asp:TextBox ID="txt1" Text="<%= this.SomeMethod() %>" runat="server"></asp:TextBox> <!-- 错误:属性值没有用引号括起来 --> <asp:TextBox ID="txt2" Text= <%= this.SomeMethod() %> runat="server"></asp:TextBox>
-
正确用法:
- 最佳实践:在后台代码(.cs 文件)中设置属性,避免在 aspx 中写复杂的逻辑。
// 在 Page_Load 或其他事件中 txt1.Text = SomeMethod();
- 如果必须在 aspx 中写:对于简单表达式,可以使用
OnDataBinding。<asp:TextBox ID="txt3" runat="server" OnDataBinding="txt3_DataBinding"></asp:TextBox>
protected void txt3_DataBinding(object sender, EventArgs e) { TextBox txt = sender as TextBox; txt.Text = "绑定时的值: " + DateTime.Now; }
- 最佳实践:在后台代码(.cs 文件)中设置属性,避免在 aspx 中写复杂的逻辑。
ASP.NET 服务器控件标签拼写错误
- 错误:
<asp:TexttBox>(多了一个 't') - 错误:
<asp:Lable>(Label 拼写错误) - 错误:
<asp:Button runat="server" />(缺少ID属性虽然不直接导致此错误,但通常是问题的一部分)
解析器遇到它不认识的标签,就会报告“格式不正确”。

如何调试和解决
-
检查行号和列号: 错误信息通常会提供具体的文件名和行号、列号,直接跳转到该位置,这是最高效的定位方法。
-
仔细检查
<%=和<%#>:- 你想输出值吗?用
<%=。 - 你在数据绑定吗?用
<%#>。 - 确保它们没有作为独立的标签出现,也没有放在另一个服务器控件的属性值里(除非使用
OnDataBinding)。
- 你想输出值吗?用
-
检查所有代码块的语法:
- 确保每个
<%都有一个对应的%>。 - 检查 C# 或 VB.NET 代码块内部的语法是否正确(比如括号、分号、关键字拼写等)。
- 确保每个
-
检查服务器控件的拼写:
- 确认
asp:后面的控件名称是正确的(如TextBox,Label,Button,GridView等)。 - 确认所有属性名称的拼写也是正确的(如
runat,ID,Text)。
- 确认
-
简化代码:
如果一个复杂的表达式导致错误,尝试将其拆分成更简单的部分,或者将逻辑移到后台代码中,后台代码更容易调试和阅读。
-
使用智能感知: 在 Visual Studio 或 Visual Studio Code 中编写代码时,充分利用智能提示,它能帮你正确拼写控件和属性名,并提示你何时使用
<%=或<%#>。
| 错误场景 | 错误示例 (错误) | 正确做法 |
|---|---|---|
| 混淆数据绑定 | <asp:TextBox Text="<%= GetDate() %>" /> |
在后台代码中设置 txtDate.Text = GetDate(); 或使用 OnDataBinding 事件。 |
| 顶级表达式 | <%= "Hello" %> |
将表达式放入 HTML 内容中,如 <h1><%= "Hello" %></h1>。 |
| 代码块语法错误 | <% if (x > 5) { ... } (缺少 ) |
检查并补全所有括号、分号和结束符。 |
| 服务器控件拼写错误 | `< |
