Waiting on tasks in ASP.NET WebPages Razor view

2019-06-14 15:09发布

问题:

I am using async/await, and calling an async method from one of my views and I need to wait until it finishes. I've seen a lot of examples for ASP.NET MVC, where you can just put an "async" into the signature of your action. But I haven't seen any examples for ASP.NET WebPages.

Do I just call "Wait()" on the returned task inside my Razor view? I've seen recommendations against Wait().

Please give me some references/examples on how to properly call async methods from within a Razor view in WebPages.

回答1:

calling an async method from one of my views

Don't call methods from within the view. The view should really just be binding to data that's on the model. If there's an asynchronous operation to be performed to fetch the model's data, perform it in the controller when populating the model.

As a contrived example:

public class MyViewModel
{
    public string SomeValue { get; set; }
}

and in the controller:

var model = new MyViewModel
{
    SomeValue = await GetTheValue();
};
return View(model);

and in the view:

@Model.SomeValue

The model should essentially be "complete" when it's given to the view to render, and the view should just be rendering it. The asynchronous operations should be in the controller.


As an alternative to putting too much code in the controller and keeping it in the model, you can move an asynchronous operation to some kind of initialization on the model:

public class MyViewModel
{
    public string SomeValue { get; private set; }

    public async Task Initialize()
    {
        SomeValue = await GetTheValue();
    }
}

Then in your controller you'd invoke that:

var model = new MyViewModel();
await model.Initialize();
return View(model);

Or perhaps an asynchronous factory on the model:

public class MyViewModel
{
    public string SomeValue { get; private set; }

    private MyViewModel() { }

    public static async MyViewModel Create()
    {
        return new MyViewModel
        {
            SomeValue = await GetTheValue()
        };
    }
}

Then in the controller:

var model = await MyViewModel.Create();
return View(model);

There are a number of ways to go about this, really. The main thing is to keep the asynchronous operations out of the view, whose only job should be to render the UI once the model is complete.