在 Razor 页面中使用 @functions 块的错误和警告
Posted
技术标签:
【中文标题】在 Razor 页面中使用 @functions 块的错误和警告【英文标题】:Errors and warnings using @functions block in Razor Pages 【发布时间】:2020-07-02 16:12:52 【问题描述】:由于 ASP.NET Core Razor 页面不再支持 @helper
指令,我一直在使用 @functions
指令。
@functions
void RenderTask(Models.Task task)
<tr>
<td class="@Model.CssClass">
<p class="compact">
<span class="font-weight-bold">@task.Title</span>
@if (!string.IsNullOrWhiteSpace(task.Description))
<br />@task.Description
</p>
</td>
<td class="@Model.CssClass">
<img src="~/images/Edit.png" class="edit-area button-img" data-id="@task.Id" title="Edit" />
<img src="~/images/Delete.png" class="delete-area button-img" data-id="@task.Id" title="Delete" />
</td>
</tr>
这似乎可行,但出现错误:
错误 MVC1006:该方法包含一个 TagHelper,因此必须是异步的并返回一个任务。例如,使用 ~/ 通常会导致 TagHelper 并需要异步任务返回父方法。
所以我把这个函数改成了async
,然后我在任何调用它的地方都使用了await
关键字。
@functions
async System.Threading.Tasks.Task RenderTask(Models.Task task)
<tr>
<td class="@Model.CssClass">
<p class="compact">
<span class="font-weight-bold">@task.Title</span>
@if (!string.IsNullOrWhiteSpace(task.Description))
<br />@task.Description
</p>
</td>
<td class="@Model.CssClass">
<img src="~/images/Edit.png" class="edit-area button-img" data-id="@task.Id" title="Edit" />
<img src="~/images/Delete.png" class="delete-area button-img" data-id="@task.Id" title="Delete" />
</td>
</tr>
这确实有效,但我收到警告:
...\Razor\Pages\Tasks\Index.cshtml.g.cs(286,200,286,202):警告 CS1998:此异步方法缺少“等待”运算符,将同步运行。考虑使用“await”运算符来等待非阻塞 API 调用,或“await Task.Run(...)”在后台线程上执行 CPU 密集型工作。 ...\Razor\Pages\Tasks\Index.cshtml.g.cs(312,200,312,202):警告 CS1998:此异步方法缺少“等待”运算符,将同步运行。考虑使用 'await' 运算符来等待非阻塞 API 调用,或使用 'await Task.Run(...)' 在后台线程上执行 CPU 密集型工作。
Index.cshtml.g.cs 似乎是某种中间文件。但我不知道它后面的数字是什么,双击这些警告不会把我带到违规行。
此时,我不确定问题出在哪里。我已经在 Google 上进行了广泛的搜索,但没有找到一个很好的例子来说明我应该做什么。任何建议表示赞赏。
更新:
这是Index.cshtml.g.cs的一部分:
#nullable restore
#line 86 "D:\Users\Jonathan\source\repos\Bamtok\Bamtok\Pages\Tasks\Index.cshtml"
Write(task.Id);
#line default
#line hidden
#nullable disable
__tagHelperStringValueBuffer = EndWriteTagHelperAttribute();
__tagHelperExecutionContext.AddHtmlAttribute("data-id", Html.Raw(__tagHelperStringValueBuffer), global::Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle.DoubleQuotes);
__tagHelperExecutionContext.AddHtmlAttribute(__tagHelperAttribute_3);
await __tagHelperRunner.RunAsync(__tagHelperExecutionContext); // *** ERROR HERE! ***
if (!__tagHelperExecutionContext.Output.IsContentModified)
await __tagHelperExecutionContext.SetOutputContentAsync();
Write(__tagHelperExecutionContext.Output);
__tagHelperExecutionContext = __tagHelperScopeManager.End();
WriteLiteral("\r\n ");
__tagHelperExecutionContext = __tagHelperScopeManager.Begin("img", global::Microsoft.AspNetCore.Razor.TagHelpers.TagMode.SelfClosing, "5fc6845fce9caf31066e5edd3fc6a51f323364e715810", async() =>
);
【问题讨论】:
【参考方案1】:Microsoft has just confirmed 警告是一个错误。
【讨论】:
【参考方案2】:至少有 4 种解决方法:
解决方案1:返回Task
,但不要成为async
:
您可以放心地忽略编译器说它必须是异步函数,因为编译器所关心的只是函数返回System.Threading.Tasks.Task
。因此,您可以在不使用 await
的情况下返回 System.Threading.Tasks.Task
,但这意味着您需要在某处使用多余的 return Task.CompletedTask;
:
@functions
System.Threading.Tasks.Task RenderTask( Models.Task task )
<tr>
<td class="@Model.CssClass">
<p class="compact">
<span class="font-weight-bold">@task.Title</span>
@if (!string.IsNullOrWhiteSpace(task.Description))
<br />@task.Description
</p>
</td>
<td class="@Model.CssClass">
<img src="~/images/Edit.png" class="edit-area button-img" data-id="@task.Id" title="Edit" />
<img src="~/images/Delete.png" class="delete-area button-img" data-id="@task.Id" title="Delete" />
</td>
</tr>
return Task.CompletedTask;
解决方案 2:或者,使用包装器:
@functions
System.Threading.Tasks.Task ShutUpRazor<T>( Action<T> renderFunc, T arg )
renderFunc( arg );
return Task.CompletedTask;
void RenderTask( Models.Task task )
<tr>
<td class="@Model.CssClass">
<p class="compact">
<span class="font-weight-bold">@task.Title</span>
@if (!string.IsNullOrWhiteSpace(task.Description))
<br />@task.Description
</p>
</td>
<td class="@Model.CssClass">
<img src="~/images/Edit.png" class="edit-area button-img" data-id="@task.Id" title="Edit" />
<img src="~/images/Delete.png" class="delete-area button-img" data-id="@task.Id" title="Delete" />
</td>
</tr>
用法:
<section>
@( this.ShutUpRazor( this.RenderTask, this.Model.MyTask ); )
</section>
解决方案 3:抑制警告:
@ #pragma warning disable 1998
@functions
void RenderTask( etc )
etc
@ #pragma warning enable 1998
解决方案 4:使用 async
函数和 await
仅 Yield
:
@functions
async System.Threading.Tasks.Task RenderTask( Models.Task task )
await Task.Yield();
<tr>
<td class="@Model.CssClass">
<p class="compact">
<span class="font-weight-bold">@task.Title</span>
@if (!string.IsNullOrWhiteSpace(task.Description))
<br />@task.Description
</p>
</td>
<td class="@Model.CssClass">
<img src="~/images/Edit.png" class="edit-area button-img" data-id="@task.Id" title="Edit" />
<img src="~/images/Delete.png" class="delete-area button-img" data-id="@task.Id" title="Delete" />
</td>
</tr>
【讨论】:
解决方案 1 给了我几个警告和错误。 : 错误 CS4032: 'await' 运算符只能在异步方法中使用。考虑使用“async”修饰符标记此方法并将其返回类型更改为“Taskawait
的情况下调用它,我会收到警告警告 CS4014:由于未等待此调用,因此在调用完成之前继续执行当前方法。考虑将“等待”运算符应用于调用结果。.
@JonathanWood 这个错误很有趣——你能找到 Razor 编译器生成的 *.cs 文件(通常在你的 PC 的“Temporary ASP.NET Files”文件夹或项目的“Obj”文件夹中)并添加它到你的问题帖子 - 我想看看。
文件很大,但我在问题中添加了几行。 (评论指出错误的位置。)
@JonathanWood 啊,我现在看到了问题所在。我忘记了 Razor 现在添加的所有 不必要的 async
/await
东西(我希望他们在下一个版本中修复它)。不幸的是,像您一样必须使用async Task<>
- 但您可以安全地添加#pragma warning disable...
以禁止在不使用await
的情况下使用async
的警告(因为Razor 正在添加await
它将您的代码编译到...g.cs
文件中)。【参考方案3】:
@functions
public async Task RenderItem(string date,string time,string id)
<td>@date</td>
<td>@time</td>
<td>
<form method="post" class="form-inline" asp-page-handler="view" asp-route-id="@id">
<button type="submit" class="btn btn-link">@id</button>
</form>
</td>
Usage
<tr>@await RenderItem(@date.ToShortDateString(), time, id);</tr>
【讨论】:
一般建议:通常最好在问题中添加错误和/或警告。【参考方案4】:当前 Razor 错误最适合我的解决方法是创建函数 async
并在 razor 代码范围内使用 await
调用它。示例:
async Task RenderName (string name)
<a asp-action="TagHelperForcesAsync">dear @name</a>
二手
<p>Hello @await RenderName("John");</p>
【讨论】:
以上是关于在 Razor 页面中使用 @functions 块的错误和警告的主要内容,如果未能解决你的问题,请参考以下文章
c#/Razor:如何从 .cshtml 页面引用用户定义的函数?