剃刀页面:对所有返回类型以及何时使用它们感到困惑

时间:2018-10-26 18:50:28

标签: c# razor razor-pages

我通常对在Razor Pages中使用某些C#返回类型的“为什么”(而不是“如何”)感到困惑。在某些情况下,我理解“为什么”,但不清楚何时应该使用另一种方法。我最初的困惑始于异步类型,但现在我明白了。 void类型也使它更加复杂,我对此有更好的理解,但仍不能完全理解。

我正在研究几种不同的代码片段,以便更好地掌握它们,并且可以使用一些有用的解释-文档和其他资源并未真正为我带来帮助。

其中一些方法来自某些DI,并且不一定相关(我认为,就我所知,这是使用一种返回类型而不是另一种返回类型的原因,在这种情况下,我很乐意做出解释)。以下是一些摘要,我希望社区可以帮助我更好地理解使用一种返回类型而不是另一种返回类型的“原因”(或者我是否应该坚持使用一种类型,因为它不会影响以下结果)正在做什么)。

第一:

public void OnGet()
{
    ServicesContainer = _helper
        .GetRecentContentItemsByContentTypeAsync("Services")
        .GetAwaiter()
        .GetResult()
        .SingleOrDefault();
    ServicesList = _helper
        .GetRecentContentItemsByContentTypeAsync("Service")
        .GetAwaiter()
        .GetResult()
        .OrderByDescending(c => c.CreatedUtc)
        .Take(3);
}

我对代码本身没有任何了解-正在检索容器并在其中列出项目。我的Razor页面只是使用重复的foreach循环来显示列表项。我也理解代码正在获取此信息,这是最基本的示例。所以我的理解没有问题。

第二:

public async Task OnGetAsync(string projectTitle)
{
    Project = _helper
        .QueryContentItemsAsync(q => q
            .Where(c => c.DisplayText == projectTitle))
        .GetAwaiter()
        .GetResult()
        .SingleOrDefault();

    var relatedProjects = 
        (IEnumerable<string>)Project?
            .Content
            .Project.RelatedProjects?
            .ContentItemIds?.ToObject<string[]>();

    if (relatedProjects?.Count() > 0)
    {
        RelatedProjects = await
            _helper.GetContentItemsByIdAsync(relatedProjects);
    }
}

以上内容还检索了可能包含项目(RelatedProjects)的“容器”,但是在这种情况下,它的做法有所不同,因为除了项目本身以外,没有其他要列出的内容。但是为什么使用Task而不是OnGet

第三:

public async Task<IActionResult> OnGet()
{
    HeaderInfo = await _helper
        .GetContentItemByAliasAsync("alias:fullwidth");

    return Page();
}

这里只是一个项目。但是再一次,为什么在其他所有代码都不需要返回页面的情况下,为什么使用Task并为什么使用<IActionResult>返回页面呢?为什么不使用OnGetAsync

任何项目都没有什么特别的-它们都存储在CMS中(例如,它们没有动态变化)。第一个是带有列表项的容器。第二个是具有潜在相关项目的项目(如果它们存在于CMS中,则不存在)。第三只是一个项目。

为什么要在第一个而不使用

上使用void

预先感谢您分享任何见解。

2 个答案:

答案 0 :(得分:4)

每当对OnGet()发出请求时,IIS必须等待数据返回才能处理其他请求。通过使OnGet()异步,这使IIS在等待数据返回时可以执行其他任务。这样可以减少瓶颈,并使IIS更快,更高效地执行。

只要方法标记为async,它就必须返回一个Task对象。如果您的方法没有任何返回值,则仍必须将其标记为Task OnGetAsync()。如果您的方法确实返回了值,则可以像在Task中一样,在Task<IActionResult> OnGetAsync()对象中指定返回类型。

因此,对于您的方法,正在发生的事情:

public void OnGet()
{
     // Synchronous method that returns nothing
     // IIS stops handling requests here until your method returns
}

public async Task OnGetAsync(string projectTitle)
{
    // Asynchronous method that returns nothing.
    // When your code reaches the await keyword,
    // IIS resumes handling other tasks while awaiting
    // for your method to return
}

public async Task<IActionResult> OnGet()
{
    // Asynchronous method that returns an IActionResult value
    // When your code reaches the await keyword,
    // IIS resumes handling other tasks while awaiting
    // for your method to return
}

答案 1 :(得分:2)

public async Task<IActionResult> OnGet()
{
    HeaderInfo = await _helper
        .GetContentItemByAliasAsync("alias:fullwidth");

    return Page();
}

您实际上不需要从此方法返回任何内容。您可以轻松地编写

public async Task OnGet()
{
    HeaderInfo = await _helper
        .GetContentItemByAliasAsync("alias:fullwidth");
}

调用Page()方法时,将显示当前页面。如果未指定其他返回类型,则在任何情况下都会暗中发生。

通常,您只将Page()方法作为许多可能的返回类型之一调用,而其他返回类型是IActionResults。最常见的示例是表单发布时:

public IActionResult Create()
{
    if(ModelState.IsValid)
    {
        return RedirectToPage("Success"); // redirect as part of PRG
    }
    else
    {
        return Page(); // redisplay the page with validation errors
    }
}

在这种情况下,必须声明一个返回类型(而不是void或Task),因为要使用RedirectToPage方法,该方法返回一个RedirectToResult(一种IActionResult)。在else情况下,还必须提供合适的返回类型,从而调用return Page()