如何在cshtml模板中创建一个函数?

249

我需要创建一个仅在一个 cshtml 文件中使用的函数。您可以将我的情况看作是 ASP.NET 页面方法,它们是在页面中实现的最小 Web 服务,因为它们仅适用于一个页面。我知道 HTML 帮助程序(扩展方法),但我的函数仅在一个 cshtml 文件中需要。我不知道如何在视图中创建函数签名。 注意:我正在使用 Razor 模板引擎。


请参阅Helpers和Functions之间的区别 - Michael Freidgeim
6个回答

474
为什么不直接在cshtml文件中声明该函数呢?
@functions{
    public string GetSomeString(){
        return string.Empty;
    }
}

<h2>index</h2>
@GetSomeString()

37
应将此标记为答案,因为 @functions 指令特别符合 OP 的要求。Helpers 功能旨在通过将带有 @helper 指令的文件放入 App_Code 目录中来供多个模板文件共享使用。而 @functions 指令允许仅由声明它的模板使用函数。 - Jon Davis
7
请注意,辅助方法似乎倾向于返回字符串,就像其他Razor辅助程序一样,因此“functions”解决方案为其他返回类型提供了更多的灵活性。尽管两种答案都有用,但在我的书中都会得到+1分。 - AaronLS
9
公平地说,Helpers(辅助方法)并不返回字符串,而是返回IHtmlString类型的值,这个类型会为您处理HTML编码,保护您的应用免受XSS攻击。同时,Helper还提供了Razor语法在Helper本身中的便利性,但这种便利性无法使用函数实现。换句话说,使用Helper可以这样写<p>Welcome, @username.</p>,而使用函数则需要这样写return new HtmlString("<p>Welcome, " + Html.Encode(username) + ".</p>"); - Daniel Liuzzi
9
在单个视图中使用@helper并不会使其在其他视图中可用。我更喜欢@helper的原因是你可以在花括号之间放置HTML代码,而@functions则无法(轻松地)实现这一点。 - jfren484
5
仅供记录:@helper@functions都可以在多个视图之间共享,也可以在单个视图中声明并使用(我个人在共享和单独场景中都发现了它们的用途)。在我看来,它们之间唯一的实际区别在于,视图助手为返回呈现的HTML片段(或者更合适的是HelperResult实例)添加语法糖,而视图函数通常仅对返回简单的引用或值类型有用。 - rsenna
显示剩余10条评论

314

您可以使用@helper Razor指令:

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

然后你可以这样调用它:

@WelcomeMessage("John Smith")

14
您不能在 @functions 方法内部放置标记,因此我喜欢这个答案。 - jfren484
1
是的,这比声明一个函数要好得多。更加直接明了。 - muglio
2
但是你不能返回变量(因此使用了函数这个词)。 - Paul
4
ASP.NET Core也支持@helper吗? - MuM6oJuM6o
3
不,它并没有。您可以在本文ASP.NET Core中的Helper到哪里去了?中找到列出的替代方案。 - Bruno Martins
显示剩余4条评论

30

如果你的方法不需要返回 HTML ,而需要执行其他操作,那么在 Razor 中可以使用 lambda 表达式代替辅助方法。

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";

    Func<int,int,int> Sum = (a, b) => a + b;
}

<h2>Index</h2>

@Sum(3,4)

如果您需要在函数中访问页面的全局变量,这是很有用的。不过,还有其他方法吗? :/ - Alexandre Daubricourt


7
在ASP.NET Core Razor Pages中,你可以在函数中将C#和HTML组合起来:
@model PagerModel
@{
}

@functions 
{
    void PagerNumber(int pageNumber, int currentPage)
    {
        if (pageNumber == currentPage)
        {
            <span class="page-number-current">@pageNumber</span>
        }
        else
        {
            <a class="page-number-other" href="/table/@pageNumber">@pageNumber</a>
        }
    }
}

<p>@PagerNumber(1,2) @PagerNumber(2,2) @PagerNumber(3,2)</p>

2

如果你想要访问页面的全局变量,可以这样做:

Original Answer翻译成“最初的回答”

@{
    ViewData["Title"] = "Home Page";

    var LoadingButtons = Model.ToDictionary(person => person, person => false);

    string GetLoadingState (string person) => LoadingButtons[person] ? "is-loading" : string.Empty;
}

自C# 7.0以来,这是唯一正确的答案。GetLoadingState()在此处是本地函数。 - Wolfrevok Cats

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接