ASP.NET Core Razor 语法简述

如果写过 HTML 里嵌 <?php ?>​ 的页面吧?Razor 干的事差不多,只不过嵌入式用的是 C#。Razor 标记可以塞进 .cshtml​(MVC 视图/Razor Pages)或者 .razor​(Blazor 组件),写法跟 Vue 的模板语法有几分神似。下面从最基础的开始,一路讲到那些容易被忽视的坑。

1. 怎么输出 HTML

Razor 的默认语言就是 HTML,你写 <p>Hello</p>​,它就乖乖输出 <p>Hello</p>​。但是想混入 C# 逻辑的时候,就得靠 @ 符号了。

2. @ 符号的用法

@ 是 Razor 的开关------从 HTML 模式切到 C# 模式。

  • 输出 @ 本身 :写 @@,比如 @@Username 输出就是 @Username
  • 邮件地址里的 @ :Razor 不会碰它,Support@contoso.com 照原样输出。
  • 隐式表达式@DateTime.Now,直接跟在 @ 后面的 C# 代码。不能有空格(await 例外),也不能写泛型------<> 会被当成 HTML 标签。
  • 显式表达式@(DateTime.Now - TimeSpan.FromDays(7)),括号里头随便写,泛型也行:@(GenericMethod<int>())

3. SVG 里的 Razor

SVG 的 foreignObject 元素里可以用 Razor 表达式,没什么特别的限制。

4. 表达式编码

字符串表达式默认会被 HTML 编码。@("<span>bold</span>")​ 输出的是 &lt;span&gt;bold&lt;/span&gt; 文本,而不是一个 span 标签。

非要输出原始 HTML,用 @Html.Raw(...)​。但注意 :永远别对用户的输入用 Raw,那是 XSS 漏洞直通车。

5. 代码块

@{ ... } 把多行 C# 代码包起来,里面的代码不会直接输出。但你可以在代码块里嵌套 HTML:

csharp 复制代码
 @{
     var name = "张三";
     <p>你好,@name</p>
 }

你还可以在代码块里定义本地函数:

csharp 复制代码
 @{
     void RenderName(string name) {
         <p>@name</p>
     }
     RenderName("李四");
 }

6. 从 C# 切回 HTML

代码块里想回到 HTML 模式,有 3 种办法:

方式 示例 说明
直接写 HTML <div>内容</div> 碰到 HTML 标签自动切回
<text>标签 <text>纯文本</text> 输出纯文本,不生成 DOM 元素
@:语法 @:这是一行文本 把整行切回 HTML

常见坑 :代码块里多写一个 @ 就会引发诡异的编译器错误,排查起来很头大。

7. 条件属性呈现

属性值是 null​ 或 false​ 时,Razor 会直接省略该属性。比如 class="@false"​ 最终输出 <div>False</div>​(因为 false​ 不是 null​ 也不是 false 这个单词,它是布尔值)。

例外data-​ 属性就算值为 null​ 或 false 也会保留。

8. 控制结构一览

类型 语法
条件 @if​,else if​,else​,@switch
循环 @for​,@foreach​,@while​,@do while
复合语句 @using (Html.BeginForm()) { ... }
异常 @try ... catch ... finally
@lock (SomeLock) { ... }

9. 三种注释

  • C# 注释/* ... */// ...,在服务端处理,不会到客户端。
  • HTML 注释<!-- ... -->,会发送到浏览器。
  • Razor 注释@* ... *@,服务端直接删除,客户端拿不到。适合隐藏敏感逻辑。

10. 指令大全

指令是 Razor 的「元操作」,控制页面怎么编译、怎么跑、从哪拿数据。

指令 干的事 用在哪儿
@attribute 往生成的类上加属性,比如[Authorize] 视图/页面/组件
@code 加 C# 成员(属性、方法) .razor组件
@functions 同上,但用于.cshtml .cshtml视图
@implements 实现接口 所有文件
@inherits 指定自定义基类 所有文件
@inject 依赖注入 所有文件
@layout 指定布局 .razor组件
@model 指定强类型模型 .cshtml
@namespace 设置命名空间 导入文件(_ViewImports.cshtml
@page 声明为可路由的页面/组件 .cshtml​/.razor
@preservewhitespace 控制是否保留多余空白 .razor
@rendermode 设置 Blazor 渲染模式 .razor
@section 定义布局节 .cshtml
@typeparam 泛型类型参数 .razor
@using 添加using指令 所有文件

11. 指令属性

这些属性直接用在 HTML 标签上:

  • @attributes:批量展开任意属性(仅限组件)
  • @bind@bind:culture:双向数据绑定 + 区域性格式
  • @formname:防止表单冲突
  • @on{event}@on{event}:preventDefault@on{event}:stopPropagation:事件处理全家桶
  • @key:保留元素/组件身份(Diff 算法用)
  • @ref:获取组件实例引用

12. 模板化 Razor 委托

可以用 @<tag>...</tag> 定义一段 UI 模板,赋值给委托变量:

csharp 复制代码
 @{
     Func<dynamic, object> itemTemplate = @<li>@item</li>;
 }
 <ul>@itemTemplate("A")@itemTemplate("B")</ul>

也可以当参数传给方法------比如定义一个 Repeat 方法,接收模板委托做内联渲染。

13. 标记帮助程序指令

  • @addTagHelper:注册标记帮助程序
  • @removeTagHelper:移除已注册的
  • @tagHelperPrefix:设置前缀(比如 <vc:...>

14. 保留关键字

有些词 Razor 自己用了,你不能直接拿来当变量名。

Razor 关键字 (需用 @(keyword)​ 转义):page​, namespace​, functions​, inherits​, model​, section​, helper(不支持了但保留)

C# Razor 关键字 (需用 @(@keyword)​ 双转义):case​, do​, default​, for​, foreach​, if​, else​, lock​, switch​, try​, catch​, finally​, using​, while

未使用的保留关键字class

15. 调试小技巧:查看编译器生成的 C# 类

.csproj 里加一行:

csharp 复制代码
 <PropertyGroup>
   <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
 </PropertyGroup>

编译后在 obj/Debug/net9.0/Razor/​ 目录下找 .g.cshtml.cs 文件,能看到 Razor 把你的标记翻译成了什么 C# 代码。排查绑定错误时特别好用。

16. 视图查找与大小写

  • Windows 文件系统不区分大小写,Linux/macOS 区分。但预编译视图不区分。
  • 建议统一用小写命名,跨平台迁移时不踩坑。

17. 默认导入

_ViewImports.cshtml 默认帮你 using 了这些命名空间,开箱即用:

csharp 复制代码
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Mvc.Rendering;
 using Microsoft.AspNetCore.Mvc.ViewFeatures;

一点背景:Razor 最早出现在 ASP.NET MVC 3(2011 年),取代了古老的 Web Forms 视图引擎。到 ASP.NET Core 时代,它不仅是 MVC 的视图引擎,还成了 Blazor 组件的基础。虽然本文描述的某些底层机制在 ASP.NET Core 3.0 后有所调整,但核心语法几乎没有变过。

相关推荐
IT_陈寒17 分钟前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
Jackson__1 小时前
分享一个横向滚动案例,带悬停暂停,通用性很强
前端
MariaH2 小时前
git rebase的使用
前端
_柳青杨2 小时前
深入理解 JavaScript 事件循环
前端·javascript
阡陌Jony2 小时前
关于前端性能优化的一些问题:
前端
用户600071819103 小时前
【翻译】简化 TSRX
前端
IT乐手4 小时前
佛德角逼平西班牙,国足还有啥借口?
前端
JustHappy4 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
星栈4 小时前
Dioxus 的响应式系统:`Signal`、`Memo`、`Effect` 和异步状态到底该怎么分工
前端·前端框架
yingyima4 小时前
Java 正则表达式:比你想象的更强大
前端