在 Razor Pages 中使用 @functions 块的错误和警告
Errors and warnings using @functions block in Razor Pages
因为 @helper
指令在 ASP.NET Core Razor Pages 中不再受支持,我一直在使用 @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>
}
}
这似乎有效,但出现错误:
Error MVC1006: The method contains a TagHelper and therefore must be async and return a Task. For instance, usage of ~/ typically results in a TagHelper and requires an async Task returning parent method.
所以我将此函数更改为 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): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
...\Razor\Pages\Tasks\Index.cshtml.g.cs(312,200,312,202): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Index.cshtml.g.cs 似乎是某种中间文件。但我不知道它后面的数字是多少,双击这些警告并没有把我带到违规行。
此时,我不确定问题出在哪里。我已经广泛搜索但没有找到一个很好的例子来说明我应该做什么。任何建议表示赞赏。
更新:
这是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() => {
}
);
至少有 4 个解决方法:
解决方案 1:Return Task
但不要 async
:
您可以安全地忽略编译器说它必须是异步函数,因为编译器只关心函数 returns System.Threading.Tasks.Task
。所以你可以 return 一个 System.Threading.Tasks.Task
而不使用 await
虽然这意味着你需要一个多余的 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>
}
}
Microsoft has just confirmed 警告是错误。
当前 Razor bug 最适合我的解决方法是创建函数 async
并在 Razor 代码范围内使用 await
调用它。示例:
async Task RenderName (string name)
{
<a asp-action="TagHelperForcesAsync">dear @name</a>
}
二手
<p>Hello @{await RenderName("John");}</p>
@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>
因为 @helper
指令在 ASP.NET Core Razor Pages 中不再受支持,我一直在使用 @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>
}
}
这似乎有效,但出现错误:
Error MVC1006: The method contains a TagHelper and therefore must be async and return a Task. For instance, usage of ~/ typically results in a TagHelper and requires an async Task returning parent method.
所以我将此函数更改为 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): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
...\Razor\Pages\Tasks\Index.cshtml.g.cs(312,200,312,202): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Index.cshtml.g.cs 似乎是某种中间文件。但我不知道它后面的数字是多少,双击这些警告并没有把我带到违规行。
此时,我不确定问题出在哪里。我已经广泛搜索但没有找到一个很好的例子来说明我应该做什么。任何建议表示赞赏。
更新:
这是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() => {
}
);
至少有 4 个解决方法:
解决方案 1:Return Task
但不要 async
:
您可以安全地忽略编译器说它必须是异步函数,因为编译器只关心函数 returns System.Threading.Tasks.Task
。所以你可以 return 一个 System.Threading.Tasks.Task
而不使用 await
虽然这意味着你需要一个多余的 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>
}
}
Microsoft has just confirmed 警告是错误。
当前 Razor bug 最适合我的解决方法是创建函数 async
并在 Razor 代码范围内使用 await
调用它。示例:
async Task RenderName (string name)
{
<a asp-action="TagHelperForcesAsync">dear @name</a>
}
二手
<p>Hello @{await RenderName("John");}</p>
@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>