在Razor中如何定义一个方法?

254

我该如何在Razor中定义一个方法?


2
对于想了解选项的人:有两种方法可以做到。一种是使用"@function",另一种是使用"@helper"。它们之间的区别在这里得到了很好的解释。https://www.mikesdotnetting.com/article/173/the-difference-between-helpers-and-functions-in-webmatrix - b1k
8个回答

355

不管何时(如果有必要)进行操作,@functions 是实现之道。

@functions {

    // Add code here.

}

17
谢谢你的留言,FYI指的是“供你参考”,"practicality"翻译成中文是“实用性”。MVC不是唯一的选择,有些人喜欢简单的Razor和URLRewrite,因为在我看来,MVC需要付出很多的努力,而收益却很少。 - King Friday
6
@functions 是组织视图特定生成代码的好地方。 典型例子:那些丑陋的客户端模板字符串... - user2864740
1
你好David,我该如何在一个文件中定义函数并在另一个文件中使用它? - Georgi Kovachev
Georgi,这被称为“Razor HTML Helper”。基本上,这是在您的代码文件夹中定义的一个类,具有一组静态方法,如此处所建议:https://www.asp.net/mvc/overview/older-versions-1/views/creating-custom-html-helpers-cs。 - jeanie77
Georgi,你可能已经遇到这个问题了...但是为了重用<code>@functions</code>或<code>@helper</code> Razor选项,您可以在App_Code文件夹中使用Shared.cshtml这样的文件。在那里,您可以定义<code>@functions {}</code>或<code>@helper MyFunction() {}</code>并在其他Razor模板中使用它们,例如<code>@Shared.MyFunction()</code>,其中文件名类似于“命名空间”。 - Jamie Altizer

219

您指的是内联辅助函数吗?

@helper SayHello(string name)
{
    <div>Hello @name</div>
}

@SayHello("John")

5
我希望定义一个返回C#类型而不是MvcHtmlString的方法。 - Rookian
5
@Rookian,为什么你需要在视图中编写C#代码?在视图中编写方法是错误的!你完全可以将C#代码写在它应该存在的地方,然后在Razor视图中调用方法,这正是HTML助手所做的。它们并不总是返回MvcHtmlString。 - Darin Dimitrov
1
@Rookian 我建议不要过于惯用语; 有时候你可能想要涉及复杂但仅限于查看的逻辑,产生简单的文本/可转换为字符串的结果--例如作为内置条件类(属性)助手的输入。如果您想将该逻辑移动到其他位置,它很容易进行重构,实际上比将内联助手移动到共享位置更容易,后者必须是app_code,并且没有Html助手的访问权限,需要一些调整:http://weblogs.asp.net/scottgu/asp-net-mvc-3-and-the-helper-syntax-within-razor - Adam Tolley
3
似乎ASP.NET Core不再支持。语法错误。 - ygoe
5
ASP.NET Core的等效功能是标签助手(Tag Helper):https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/authoring - beercohol
显示剩余6条评论

53

在 Razor 内定义函数非常简单。

@functions {

    public static HtmlString OrderedList(IEnumerable<string> items)
    { }
}

所以你可以在任何地方调用函数a。例如:

So you can call a the function anywhere. Like

->

所以你可以在任何地方调用函数a。例如:

@Functions.OrderedList(new[] { "Blue", "Red", "Green" })

但是同样的工作也可以通过helper完成。例如

@helper OrderedList(IEnumerable<string> items){
    <ol>
        @foreach(var item in items){
            <li>@item</li>
        }
    </ol>
}

那么它们之间有什么区别呢?根据这篇文章,@helper和@function共享了一个共同点——它们使得在Web页面中可以实现代码重用。它们还有另一个共同点——乍一看它们看起来相同,这可能会导致对它们的作用产生一些困惑。然而,它们并不相同。本质上,helper是可重用的Razor语法片段,被暴露为方法,并旨在将HTML渲染到浏览器中,而函数是静态实用程序方法,可以从Web页面应用程序的任何地方调用。helper的返回类型始终为HelperResult,而函数的返回类型可以是您想要的任何类型。


4
在.NET Core中,通过省略@Functions前缀直接使用@OrderedList(...)调用函数对我有效。 - Muflix

14
你也可以使用像这样的 Func 来做到这一点。
@{
    var getStyle = new Func<int, int, string>((width, margin) => string.Format("width: {0}px; margin: {1}px;", width, margin));
}

<div style="@getStyle(50, 2)"></div>

声明一个 Func 会分配一个委托并影响性能(稍微一点)。 - Alex from Jitbit

10

Razor只是一个模板引擎。

如果您想创建一个普通的类,请使用常规类。

如果您想在Razor页面中创建方法,请将它们放在@functions中。


3
你也可以使用 @{ } 块来创建函数:
@{
    async Task<string> MyAsyncString(string input)
    {
        return Task.FromResult(input);
    }
}

然后在你的 Razor 页面中稍后加入以下代码:
   <div>@(await MyAsyncString("weee").ConfigureAwait(false))</div>

2
以下是关于ASP.NET Core 3中List Helper的写法:

现在可以在代码块中声明局部方法或@functions块中包含HTML标记。该方法应返回void或Task(如果需要异步处理):

@{
    void Template(string[] listItems, string style)
    {
        <ul>
            @foreach (var listItem in listItems)
            {
            <li class="@style">@listItem</li>
            }
        </ul>
    }
}

1

MyModelVm.cs

public class MyModelVm
{
    public HttpStatusCode StatusCode { get; set; }
}

Index.cshtml

@model MyNamespace.MyModelVm
@functions
{
    string GetErrorMessage()
    {
        var isNotFound = Model.StatusCode == HttpStatusCode.NotFound;
        string errorMessage;
        if (isNotFound)
        {
            errorMessage = Resources.NotFoundMessage;
        }
        else
        {
            errorMessage = Resources.GeneralErrorMessage
        }

        return errorMessage;
    }
}

<div>
    @GetErrorMessage()
</div>

你也可以使用下面的代码块。它更加干净,并且具有更多的功能性。你还可以在上方插入变量,在下方插入函数。而不是使用2个单独的代码块。
@{
    string exampleVariable = "just an example variable";
    string anotherExampleVariable = "just another example variable";

    string GetErrorMessage()
    {
        var isNotFound = Model.StatusCode == HttpStatusCode.NotFound;
        string errorMessage;
        if (isNotFound)
        {
            errorMessage = Resources.NotFoundMessage;
        }
        else
        {
            errorMessage = Resources.GeneralErrorMessage
        }

        return errorMessage;
    }
}

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