@helper:返回 HTML 片段

@helper 用来输出 HTML 片段,本质返回 HelperResult。调用方式与普通 C# 方法一致:

@helper WelcomeMessage(string username)
{
    <p>Welcome, @username.</p>
}

@WelcomeMessage("Alice")

特征:

  • 方法体内可以直接写 Razor / HTML
  • 返回类型只能是 HelperResult,没有别的选择
  • 常用于把一段重复 HTML 抽成可复用片段
@helper 是 ASP.NET Web Pages 的特性;MVC 视图里能用但并不常见,PartialView / ViewComponent 才是更标准的复用方式。

@functions:写普通 C#

@functions 块里写普通 C# 方法:

@functions {
    public string GetSomeString()
    {
        return string.Empty;
    }

    public static HtmlString WelcomeMessage(string username)
    {
        return new HtmlString($"<p>Welcome, {username}.</p>");
    }
}

特征:

  • 适合纯计算 / 业务逻辑,不渲染 HTML
  • 如果要返回 HTML,必须显式返回 HtmlString(不能是 string,否则会被 HTML 转义)
  • using System.Web.Mvc; 在 MVC 5 之前需要;在 ASP.NET Core 下是 Microsoft.AspNetCore.Html.HtmlString

对比

@helper@functions
是否必须渲染 HTML是否
返回类型固定 HelperResult任意
适合的场景复用 HTML 片段复用纯逻辑
现代替代Partial View / View Component / Tag Helper服务类 + 依赖注入

现代替代:ASP.NET Core 怎么做

在 ASP.NET Core 中,把"渲染 HTML 片段"和"写业务方法"两件事都拆出去,不再放在视图里:

复用 HTML:Partial View / View Component / Tag Helper

HTML 片段的复用:

// Views/Shared/_Greeting.cshtml
@model string
<p>Welcome, @Model.</p>

@* 调用方式 *@
@await Html.PartialAsync("_Greeting", "Alice")
@* 或 *@
<partial name="_Greeting" model="Alice" />

带逻辑的可复用块用 View Component:

// Components/CartSummaryViewComponent.cs
public class CartSummaryViewComponent : ViewComponent
{
    private readonly ICartService _cart;
    public CartSummaryViewComponent(ICartService cart) => _cart = cart;
    public IViewComponentResult Invoke() => View(_cart.Current());
}

// Views/Shared/Components/CartSummary/Default.cshtml
@model Cart
<div>共 @Model.Items.Count 件商品</div>

// 调用
@await Component.InvokeAsync("CartSummary")

需要自定义标签就用 Tag Helper:

[HtmlTargetElement("greeting")]
public class GreetingTagHelper : TagHelper
{
    public string For { get; set; } = "";
    public override void Process(TagHelperContext ctx, TagHelperOutput output)
    {
        output.TagName = "p";
        output.Content.SetContent($"Welcome, {For}.");
    }
}

// 视图
<greeting for="Alice" />

复用逻辑:服务类 + DI

不要在视图里写业务方法。提到服务类中:

public interface IGreetingFormatter
{
    string Format(string name);
}
public class GreetingFormatter : IGreetingFormatter
{
    public string Format(string name) => $"Welcome, {name}.";
}

// 在控制器中注入
public class HomeController(IGreetingFormatter fmt) : Controller
{
    public IActionResult Index() => View(model: fmt.Format("Alice"));
}

视图只负责渲染,所有"逻辑"都通过 @inject 拿到的服务或者模型本身来完成:

@inject IGreetingFormatter Greeting
<p>@Greeting.Format("Alice")</p>

从老项目迁移时的取舍

  • @helper WelcomeMessage(name) → Partial View _Greeting.cshtml
  • @functions { HtmlString Foo() } → 抽到 service 类,@inject 或通过模型传入
  • 需要修改多个视图的统一逻辑 → Tag Helper
  • 重业务、可单元测试的代码 → View Component 或 Controller 行为

使用准则

  1. @helper / @functions 只能出现在 .cshtml,单元测试困难,能不用就不用。
  2. ASP.NET Core 项目里,HTML 复用首选 <partial> + View Component;业务逻辑用服务类 + DI。
  3. 维护老 MVC 5 项目时,@helper 仅用于纯 HTML 片段;纯逻辑请用 @functions 或抽到 Helper 类。
参考资料