Daddoon / BlazorMobile

Create full C# driven hybrid-apps for iOS, Android, UWP & Desktop with Blazor!
MIT License
413 stars 55 forks source link

Calling API #153

Closed ajhena closed 4 years ago

ajhena commented 4 years ago

I tried to call a basic API with a request via HttpClient. I am getting the following errors:

blazor.webassembly.js:1 WASM: Unhandled exception rendering component: p.printErr @ blazor.webassembly.js:1 blazor.webassembly.js:1 WASM: System.NotImplementedException: Cannot invoke method because it was wiped. See stack trace for details. p.printErr @ blazor.webassembly.js:1 blazor.webassembly.js:1 WASM: at System.Net.Http.HttpClientHandler.Dispose (System.Boolean disposing) <0x3bf5ca0 + 0x00004> in :0 p.printErr @ blazor.webassembly.js:1 blazor.webassembly.js:1 WASM: at System.Net.Http.HttpMessageHandler.Dispose () <0x3bf5b50 + 0x00008> in :0

I am essentially calling this function under the Counter.razor sample file right after the increment button. I've tested the API with Postman so I know it isn't the API.

public async Task GetDataLoaded() { RequestModel request = new RequestModel(); request.TargetAmount = 5000;

    //create post data
    var postData = JsonConvert.SerializeObject(request);

    using (HttpClientHandler handler = new HttpClientHandler())
    {
        handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        using (HttpClient client = new HttpClient(handler, false))
        {
            //client.DefaultRequestHeaders.Add("<keyname>", "<value>");
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            // Wrap our JSON inside a StringContent which then can be used by the HttpClient class
            var httpContent = new StringContent(postData, Encoding.UTF8, "application/json");

            var responseFromServer = await client.PostAsync("<personal api URL>", httpContent).Result.Content.ReadAsStringAsync();
            return responseFromServer;
        }
    }
}
Daddoon commented 4 years ago

I never encountered any kind of error of this type before, maybe something similar on Edge browser when using some Polyfills in the past.

First of all:

It may be important, as i don't have personnally updated the Blazor package since some times, and if there is some breaking changes on Microsoft side on the project Startup / Service registration, it must be done on the BlazorMobile template project too.

I never had any problem at the moment (and using it for a client), with BlazorMobile if you respect exactly the requirements mentionned on the documentation.

ajhena commented 4 years ago

@Daddoon Good suggestion on trying it on a regular Blazor project. I tried it on the regular template in VS2019 and got the same errors. It must be something about using HttpClient and HttpClientHandler. Yes it is all client side. I am running Blazor WASM.

ajhena commented 4 years ago

Seems like it is related to Blazor WASM and something with CORS. I tried enabling everything I could on the web service end but still getting the same error. For your template you're essentially taking the Blazor WASM and putting it into the Android/iOS container right?

Daddoon commented 4 years ago

I think you are using the HttpClient API wrongly with Blazor.

As stated in the doc, you must inject the HttpClient object from your page / dependency services, not construct a custom one by yourself as there is some specific implementation made with BCL, depending your are using the server or WASM version. Actually the WASM HttpClient for Blazor is a special implementation of the library, hidden by the BCL process.

Take note of the documentation: https://docs.microsoft.com/en-us/aspnet/core/blazor/call-web-api?view=aspnetcore-3.1

In my opinion your problem should go away if instanciated from an injection on a page or BlazorComponent. Note also that you only need to get the reference of this object once in lifecycle of you application, so you may cache it on a internal helper of your, to call it everywhere when needed.

Otherwise, the CORS issue is variable depending the browser security default parameters. Note also that if you are using HTTPS, you may have some blocking issue on Edge / UWP if the certificate is not really certified (like auto signed or expired).

ajhena commented 4 years ago

I didn't mention before but I tried it with DI before and I am getting the same results. CORS is fully enabled in the web service deployment and on Azure app service. Below is the same function with the HttpClient injected

public async Task GetDataLoaded() { RequestModel request = new RequestModel(); request.TargetAmount = 5000;

    //create post data
    var postData = JsonConvert.SerializeObject(request);

    //client.DefaultRequestHeaders.Add("<keyname>", "<value>");
    Http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    // Wrap our JSON inside a StringContent which then can be used by the HttpClient class
    var httpContent = new StringContent(postData, Encoding.UTF8, "application/json");

    var responseFromServer = await (await Http.PostAsync("<api url>", httpContent)).Content.ReadAsStringAsync();

    return responseFromServer;
}
Daddoon commented 4 years ago

Sorry, but as the problem is occuring on Blazor too, i think it's a Blazor issue, not a BlazorMobile one. Try with a simple Http request to determine what is the issue, maybe it's a Blazor / Mono WASM issue.

Feel free to ask help on the official Blazor issues feed here: https://github.com/dotnet/aspnetcore/issues

Closing.