1

I have two projects

First is Mobile App with Xamarin.Forms

Second is Windows Form Application

and both have the same API that was created using Azure Mobile App.

in Windows form when I'm trying to update a row in the database with a.Net HttpClient using the following code :

private void BtnUpdateUser_Click(object sender, EventArgs e)
    {
        UserRepository userRepository = new UserRepository();
        var user = userRepository.GetAllUsers().FirstOrDefault(w => w.UserId == 1)

        user.UserName = "UpdateUserName";

        var result = userRepository.UpdateUser(user.Id, user);
    }

In UserRepository class I have a method called UpdateUser

public User UpdateUser(string id, User user)
    {
        var result = Task.Run(async () => await azureServices.UpdateAsync(id, user)).Result;
        return result;
    }

In AzureServices class I have a method called UpdateAsync

public async Task<T> UpdateAsync(string id, T instance)
    {

        var Uri= new Uri(baseAddress + id + zumoAddition); //"http://localhost:55040/tables/User/48D68C86-6EA6-4C25-AA33-223FC9A27959?zumo-api-version=2.0.0
        var content = JsonConvert.SerializeObject(instance);
        await _httpClient.PatchAsync(Uri, new StringContent(content, Encoding.UTF8, "application/json"));

        return instance;
    }

PatchAsync is an extension method to do a PATCH request with the Windows.Web.Http.HttpClient

public static async Task<HttpResponseMessage> PatchAsync(this HttpClient Client, Uri requestUri, HttpContent contnet)
    {

        var method = new HttpMethod("PATCH");
        var httpRequestMessage = new HttpRequestMessage(method, requestUri)
        {
            Content = contnet
        };

        var httpResponseMessage = new HttpResponseMessage();
        try
        {
            httpResponseMessage = await Client.SendAsync(httpRequestMessage);
        }
        catch (TaskCanceledException e)
        {
            Debug.WriteLine("Error: " + e.ToString());
        }
        return httpResponseMessage;
    }

in this line httpResponseMessage = await Client.SendAsync(httpRequestMessage); I get this error:

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { x-zumo-server-version: net-2.0.0 X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcQW5hc1xEZXNrdG9wXFB1cmNoYXNlT3JkZXJzQmFja2VuZFxQdXJjaGFzZU9yZGVyc0JhY2tlbmRcdGFibGVzXFVzZXJcNTA1NzdBOTMtOEEzRi00OTEwLUJBOEYtM0MwMkMyOUFDMDUx?= Date: Thu, 29 Nov 2018 10:20:59 GMT Server: Microsoft-IIS/10.0 X-Powered-By: ASP.NET Content-Length: 188 Content-Type: application/json; charset=utf-8 }}

In the backend I have a controller with a Patch method:

public Task<User> PatchUser(string id, Delta<User> patch)
    {
         return UpdateAsync(id, patch);
    }

when I try debugging the backend I get this:

Id = 179, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"

enter image description here

The question is:How I can get rid of this error and why it appears.

Anas Alweish
  • 2,818
  • 4
  • 30
  • 44
  • 1
    How and where is `UpdateUser` invoked. You are mixing async and blocking calls which can lead to deadlocks. Since you are using HttpClient then you should aim to keep the code async all the way through – Nkosi Dec 03 '18 at 13:10
  • What type is the controller. Include its definition. – Nkosi Dec 03 '18 at 13:26
  • What does `UpdateAsync` called by the controller look like ? – Nkosi Dec 03 '18 at 13:27
  • @Nkosi Thanks for your quick reply, the `UpdateUser` invoke when the event `BtnUpdateUser_click` is clicked, I have modified my question the type of the controller is `Table Controller` – Anas Alweish Dec 03 '18 at 14:18

2 Answers2

3

On the client side (Windows form) you are mixing async and blocking calls like .Result, which can lead to deadlocks.

Since you are using HttpClient then you should aim to keep the code async all the way through.

UserRepository needs to be update to allow non blocking async calls

public Task<User> UpdateUserAsync(string id, User user) {
    return azureServices.UpdateAsync(id, user);
}

Event handlers allow for async calls so that would need to be refactored to

private asyc void BtnUpdateUser_Click(object sender, EventArgs e) {
    UserRepository userRepository = new UserRepository();
    var user = userRepository.GetAllUsers().Where(w => w.UserId == 1).FirstOrDefault();

    user.UserName = "UpdateUserName";

    var result = await  userRepository.UpdateUserAsync(user.Id, user);
}

That should help mitigate any deadlocks that could occur on the client side.

On the back-end the TableController action is expecting a Delta<User>, which based on what is send from the client may not be formatted correctly.

The client is sending a plain aplication/json User as content, which may not bind correctly to Delta<User> which is expecting to handle only changes to be made to the model.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • you are right, the client is sending a plain `application/json` `User` as content, and not bind correctly to `Delta`. so the question must be **how to Serialize Delta to JSON ?** – Anas Alweish Dec 04 '18 at 08:06
  • 1
    @Anas I am curious why you are sending the data manually and not using [the managed client for Azure Mobile Apps](https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-dotnet-how-to-use-client-library) which was designed to interact with the service. – Nkosi Dec 04 '18 at 10:45
  • thank you, I tried to use [UpdateAsync](https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-dotnet-how-to-use-client-library#modifying) which was designed to interact with the service by Microsoft. it works fine. Soon I will post an answer about the first problem – Anas Alweish Dec 05 '18 at 06:35
0

How I can get rid of this error and why it appears.

You can simplify your code by calling and awaiting in the following single statement.

public async Task<User> PatchUser(string id, Delta<User> patch)
{
    return await UpdateAsync(id, patch);
}

For more inforamtion please refer to Asynchronous programming with async and await (C#)

Tom Sun - MSFT
  • 24,161
  • 3
  • 30
  • 47