Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we call an async method from a constructor? [duplicate]

I'm needing to call a third party async method from a mvc app. The name of this async method is ForceClient.QueryAsync. It is from an open source project: https://github.com/developerforce/Force.com-Toolkit-for-NET/.

Below works fine, the model.Opportunity contains expected info when the process is in the View stage of the mvc:

public async Task<ActionResult> MyController(string Id) {
    . . . .
    MyModel model = new MyModel();
    var client = new ForceClient(instanceUrl, accessToken, apiVersion);
    var qry = await client.QueryAsync<MyModel.SFOpportunity>(
            "SELECT Name, StageName FROM Opportunity where  Id='" + Id + "'");
    model.Opportunity = qry.Records.FirstOrDefault();
    . . . .
return View(viewName, myModel);
}

But below does not work. The model.Opportunity is null when the process is in the View stage. I did some debugging and see that the flow goes like this:

1) Step1

2) Step2

3) In the View stage. At this point the model.Opportunity is null, which I need it to be populated.

4) Step3.

public async Task<ActionResult> MyController(string Id) {
    . . . .
    MyModel myModel = await Task.Run(() =>
        {
            var result = new MyModel(Id);
            return result;

        });   // =====> Step 1
    . . . .
return View(viewName, myInfoView);
}    

public class MyModel
{
    public SFOpportunity Opportunity { get; set; }
    public MyModel(string id)
    {
        setOpportunityAsync(id);
    }

    private async void setOpportunityAsync(string id)
    {
        . . .
        var client = new ForceClient(instanceUrl, accessToken, apiVersion);
        var qry = await client.QueryAsync<MyModel.SFOpportunity>(
             "SELECT Name, StageName FROM Opportunity where  Id='" + id + "'");  // ======>  Step2 
        Opportunity = qry.Records.FirstOrDefault();  // =====> step3
    }

So, my question is what do I need to do to get it to execute the steps in the following sequence: 1) Step1

2) Step2

3) Step3

4) In the View stage. At this point the model.Opportunity is should be populated.

like image 619
HockChai Lim Avatar asked Feb 28 '26 09:02

HockChai Lim


1 Answers

You cannot have async constructors.

One alternative is to have async factory methods:

public class MyModel
{
  public SFOpportunity Opportunity { get; set; }
  private MyModel() { }

  public static async Task<MyModel> CreateAsync(string id)
  {
    var result = new MyModel();
    await result.setOpportunityAsync(id);
    return result;
  }

  private async Task setOpportunityAsync(string id)
  {
    ...
  }
}

like image 123
Stephen Cleary Avatar answered Mar 02 '26 21:03

Stephen Cleary