5

The Issue:

I'm attempting to call a C# Web Method from jQuery to update a user's profile.

When I implement async and await, the call is made to the Web Method but the call never completes. Chrome forever shows the response as "(Pending)", and the Timing tab shows that the call is "Stalled".

Any input is greatly appreciated.


I've Tried:

  • Not using async and await

    It works! However this entirely defeats the purpose of what I'm trying to achieve.


  • Changing Task<bool> to void:

    "An asynchronous operation cannot be started at this time."

    (Yes, my page is marked Async="true")


  • Googling and searching SO:

    I've found a few similar questions but the resulting answers were either "Just make it synchronous instead!" (which entirely defeats the purpose) or they were MVC solutions that I'd rather not employ in my current project.


Code:

$.ajax({
    type: "POST",
    url: "Profiles.aspx/updateProfileName",
    data: JSON.stringify({
        profileName: $input.val(),
        customer_profile_id: cp_id
    }),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: callSuccessful,
    error: callFailed
});
[WebMethod]
public static async Task<bool> updateProfileName(string profileName, string customer_profile_id)
{
    User user = (User) HttpContext.Current.Session["user"];
    if (profileName.Trim().Length == 0) return false;
    int customerProfileId = int.Parse(customer_profile_id);

    CustomerProfileViewModel profile = new CustomerProfileViewModel();
    profile.profile_name = profileName;
    profile.customer_profile_id = customerProfileId;
    profile.customer_id = user.customerId;

    bool profileUpdated =  await ExampleApi.UpdateProfile(profile);
    return profileUpdated;
}
3
  • 1) What version of .NET are you using?, and 2) What is the type of SynchronizationContext.Current within updateProfileName? Commented Aug 3, 2017 at 18:46
  • @StephenCleary 4.5, how would I go about finding the type? I threw a QuickWatch in the Web.Method to evaluate SynchronizationContext.Current but I'm not finding much that seems useful. Commented Aug 6, 2017 at 4:12
  • You can either type that into the immediate window or change your watch to SynchronizationContext.Current.GetType().Name. Commented Aug 7, 2017 at 13:15

3 Answers 3

2

I'm both sorry and relieved that I'm able to post a solution to my own question such a short time after asking it, but I've come up with a solution for the time being. Although, I'm not going to accept my own answer as I'd still like some input if available.

I've re-factored my Web Method to be a standard public static bool instead of an async. Instead of including the await, it now uses Task.Run() to call the async await function:

public static bool updateProfileWebMethod(string profileName, string customer_profile_id)
{
    User user = (User) HttpContext.Current.Session["user"];
    if (profileName.Trim().Length == 0) return false;
    int customerProfileId = int.Parse(customer_profile_id);

    CustomerProfileViewModel profile = new CustomerProfileViewModel();
    profile.profile_name = profileName;
    profile.customer_profile_id = customerProfileId;
    profile.customer_id = user.customerId;

    //CALL THE ASYNC METHOD
    Task.Run(() => { updateProfileName(profile); });
    return true;
}

public static async void updateProfileName(CustomerProfileViewModel profile)
{
    bool profileUpdated = await ExampleApi.UpdateProfile(profile);
}
Sign up to request clarification or add additional context in comments.

3 Comments

That going to return true no matter what the result of ExampleApi.UpdateProfile(profile) is. Is that really what you want? Not to mention that it will likely return before ExampleApi.UpdateProfile(profile) is even completed.
Well if there were a different way I'd take the advice for sure. As it stands, to truly retrieve the result from updateProfileName, I'd need to await my Task.Run() - the same issue that raised the question in the first place. The $.ajax callbacks are merely for catching 200 vs 500 at this point.
async void is very dangerous path, and that method could be suspended before it finishes.
1

Pretty sad after 2 years nobody has provided an answer. Basically:

bool profileUpdated =  await ExampleApi.UpdateProfile(profile).ConfigureAwait(false);

This configures the task so that it can resume on a different thread than it started on. After resuming, your session will no longer be available. If you don't use ConfigureAwait(false), then it waits forever for the calling thread to be available, which it won't be because it is also still waiting further back in the call chain.

However, I run into a problem where the return value doesn't get sent. the asp.net engine that calls the WebMethod is supposed to await the result if Async=true, but that doesn't seem to happen for me.

Comments

0

In this line>

bool profileUpdated = await ExampleApi.UpdateProfile(profile);

This method must also be static and asynchronous, in addition to all others that follow the call stack.

Another important point is to mark your ajax call with async: true,

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.