Errors and warnings using @functions block in Razor Pages

青春壹個敷衍的年華 提交于 2020-03-23 07:49:26

问题


Because the @helper directive is no longer supported in ASP.NET Core Razor Pages, I've been using the @functions directive instead.

@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>
    }
}

This seems to work but I get an error:

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.

So I changed this function to be async, and I used the await keyword any place it is called.

@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>
    }
}

This actually works but I get warnings:

...\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 appears to be some sort of intermediary file. But I don't know what the numbers are that follow it, and double clicking these warnings does not take me to the offending line.

At this point, I'm not sure what the problem is. I've Googled extensively but haven't found a good example of this that shows what I'm supposed to be doing. Any suggestions appreciated.

Update:

Here's a section of 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:


There's at least 4 workarounds:

Solution 1: Return Task but don't be async:

You can safely ignore the compiler saying it must be an async function because all the compiler cares about is that the function returns System.Threading.Tasks.Task. So you can return a System.Threading.Tasks.Task without using await though it means you'll need a superfluous return Task.CompletedTask; in it somewhere:

@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;
    }
}

Solution 2: Alternatively, use a wrapper:

@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>
    }
}

Usage:

<section>
    @( this.ShutUpRazor( this.RenderTask, this.Model.MyTask ); )
</section>

Solution 3: Suppress the warnings:

@{ #pragma warning disable 1998 }
@functions
{
    void RenderTask( etc )
    {
        etc
    }
}
@{ #pragma warning enable 1998 }

Solution 4: Use async functions and await only a 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>
    }
}


来源:https://stackoverflow.com/questions/60792542/errors-and-warnings-using-functions-block-in-razor-pages

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!