简体   繁体   中英

How to await execution of async in ASP.NET Core API?

I'm using ASP.NET Core API for creating an API which I consume in client side using a React app that relies on Redux and Sagas. The point is that at one point in my client side app, I do two API calls one after the other. One is to register a new user, and the second one is to register a new company that the user specified in the form and to add the newly registered user to that organization. So it basically calls two methods in my backend.

My register function that is called first looks like this:

[AllowAnonymous]
[HttpPost("~/api/account/register")]
public async Task<IActionResult> Register([FromBody]RegisterViewModel model)
{
    var user = new MyUser
    {
        UserName = model.Email,
        Email = model.Email,
    };

    var result = Task.Run(async () => { return await _userManager.CreateAsync(user, model.Password); }).Result;
    if (result.Succeeded)
    {
           // Partially removed for brevity.
    }
}

And my other method that is called as part of the second API call looks like this:

[HttpPost]
public async Task<IActionResult> Post([FromBody]OrganizationModel model)
{
    // Partially removed for brevity.
    try
    {
        var org = _mapper.Map<OrganizationModel, Organization>(model);

        var user = await _userManager.GetUserAsync(HttpContext.User);
        if (user == null) return BadRequest(ErrorMapper.MapError("post_failed"));

        org.Admins.Add(user);

        _repository.Add(org);
        var result = await _repository.SaveAllAsync();
        if (result) return Created($"/api/organizations/{org.Id}", _mapper.Map<Organization, OrganizationModel>(org));
        else return BadRequest(ErrorMapper.MapError("post_failed"));
    }
    catch (Exception ex)
    {
        _logger.LogError($"Failed to add a new organization: {ex}");
    }
}

So, basically as you can see in the second method, I want to get the current user (please note that after registering the user I automatically sign in the user), and add the current user to the list of admins for the organization.

After some debugging what I noticed is that, Register method is called, and the like starting with var result = ... is called, but then the next line if (result.Succeeded) is not called, instead it immediately jumps to the second method shown and it continues to execute it until it reaches var user = ... at which point no user will be logged in and user will be null, so it will go out of this method and move back to the Register method and continue with the line if (result.Succeeded) . I want the whole Register method to execute before it moves to execute the second method. How can I wait that the Register method executes fully before moving to the other one?

EDIT:

Client side code looks like this:

if (!error) {
    // Partially removed for brevity.
    const user = {
        email: emailInput,
        password: passwordInput,
        confirm_password: confirmInput,
    };
    signup(user);

    const org = {
        name: newOrganizationInput,
    };
    addOrganization(org);

    this.resetState();
}

You await the execution of an asynchronous method using the await keyword. However, your problem is not with the backend but the client.

fetch / AJAX calls in JavaScript are asynchronous. So it really don't matter if the backend awaits or not, the client will still hit both endpoints without waiting.

You are probably doing something like:

fetch('/api/account/register', { ... });
fetch('/api/organizations', { ... });

The fetch methods execute asynchronously and return a promise. What you need to do is:

await fetch('/api/account/register', { ... });
await fetch('/api/organizations', { ... });

or

fetch('/api/account/register', { ... }).then(x =>
  fetch('/api/organizations', { ... });
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM