jQuery.ajax Extension for CSHTML5

JS-Support @Userware
Site Admin
Posts: 1142
Joined: Tue Apr 08, 2014 3:42 pm

jQuery.ajax Extension for CSHTML5

Postby JS-Support @Userware » Sat Dec 31, 2016 5:54 am

Dear CSHTML5 users,

We are pleased to inform you of the release of this extension that adds "jQuery.ajax" support to CSHTML5.


To use it, simply add a new class named "jQueryAjaxHelper.cs" to your project, and copy/paste the following code:

Code: Select all

using System;
using System.Threading.Tasks;

//------------------------------------
// This extension adds "jQuery.ajax" support to C#/XAML for HTML5 (www.cshtml5.com)
//
// It is licensed under The open-source MIT license:
// https://opensource.org/licenses/MIT
//
// Copyright 2017 Userware / CSHTML5
//------------------------------------

namespace CSHTML5.Extensions
{
    public static class jQueryAjaxHelper
    {
        public static async Task<string> MakeAjaxCall(string url, string data, string type = "post")
        {
            // Load JQuery if it is not already loaded:
            if (!IsJQueryLoaded())
            {
                await Interop.LoadJavaScriptFile("https://code.jquery.com/jquery-3.1.1.min.js");
            }

            // Make the ajax call:
            return await MakeAjaxCall_AssumingJQueryIsLoaded(url, data, type);
        }

        public static bool IsJQueryLoaded()
        {
            return Convert.ToBoolean(Interop.ExecuteJavaScript("(typeof window.jQuery != 'undefined')"));
        }

        private static Task<string> MakeAjaxCall_AssumingJQueryIsLoaded(string url, string data, string type = "post")
        {
            // Prepare the object that allows this method to be called using the "async/await" pattern of C#:
            var taskCompletionSource = new TaskCompletionSource<string>();

            // Make the JavaScript call to jQuery.ajax:
            Interop.ExecuteJavaScript(@"
                window.jQuery.ajax({
                    url: $0,
                type: $2,     
                data: ""html="" + $1,     
                cache: false,
                success: function(returnhtml){                         
                    ($3)(returnhtml);
                    },
                error: function(xhr, status, error) {
                    ($4)();
                    }
                });
            ",
            url, // This is "$0" in the code above
            data, // This is "$1" in the code above
            type, // This is "$2" in the code above
            (Action<string>)(result => // This is "$3" in the code above
            {
                //-----------
                // SUCCESS
                //-----------
                taskCompletionSource.SetResult(result);
            }),
            (Action)(() => // This is "$4" in the code above
            {
                //-----------
                // FAILURE
                //-----------
                if (Interop.IsRunningInTheSimulator)
                    taskCompletionSource.TrySetException(new Exception("An error has occurred during the call to jQuery.Ajax. For details, please run the application in the browser and view the browser console log."));
                else
                    taskCompletionSource.TrySetException(new Exception("An error has occurred during the call to jQuery.Ajax. A common cause is a cross-domain issue. Please view the browser console log for details (press  Ctrl+Shift+I  or  F12)."));
            }));

            return taskCompletionSource.Task;
        }
    }
}


Please note that, to avoid cross-domain errors, the app and the service must run on the same URL, port, and protocol. Alternatively, you can allow cross-domain calls by implementing CORS on the server, as documented at:
http://cshtml5.com/links/wcf-limitations-and-tutorials.aspx#cors



This extension works by calling the JavaScript method "jQuery.ajax()" from C# using the method "Interop.ExecuteJavaScript(...)".


You can test it with code like this:

Code: Select all

private async void Button_Click(object sender, RoutedEventArgs e)
{
    try
    {
        string result = await CSHTML5.Extensions.jQueryAjaxHelper.MakeAjaxCall(
            url: "http://fiddle.jshell.net/echo/html/",
            data: "some sample text",
            type: "post");

        MessageBox.Show("The server returned the following result: " + result);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Note that the test method is "async".

Attached is a sample project for Visual Studio.


Regards,
JS-Support
Attachments
Cshtml5JQueryAjaxDemo.zip
(13.8 KiB) Downloaded 2036 times

TaterJuice
Posts: 147
Joined: Thu Mar 16, 2017 5:40 am
Contact:

Re: jQuery.ajax Extension for CSHTML5

Postby TaterJuice » Fri Sep 22, 2017 11:50 am

Is this expected to work in Simulator?

I'm getting an error...

Code: Select all

Object of type 'CSHTML5.Types.INTERNAL_JSObjectReference' cannot be converted to type 'System.String'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckVlaue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeArguments)
... at CSHTML5.INTERNAL_InteropImplementation.OnCallback(JSValue[] e)


I had to change the following block from:

Code: Select all

(Action<string>)(result => // This is "$3" in the code above
{
    //-----------
    // SUCCESS
    //-----------
    taskCompletionSource.SetResult(result);
}),

to

Code: Select all

(Action<object>)(result => // This is "$3" in the code above
{
    //-----------
    // SUCCESS
    //-----------
    taskCompletionSource.SetResult(result.ToString());
}),


Now it works.

User avatar
TooTallTommyT
Posts: 19
Joined: Tue Aug 21, 2018 6:51 am
Location: Las Vegas, NV

Re: jQuery.ajax Extension for CSHTML5

Postby TooTallTommyT » Wed Sep 12, 2018 2:42 pm

I've tried modifying this extension to download various binary files: images, .obj fiiles, and other binary files. I've tried setting a responseType on the ajax call to 'arraybuffer', and to 'blob', and setting the Action to 'Action<byte[]>, but the method keeps erring out saying "CSHTML5.Types.INTERNAL_JSObjectReference cannot be converted to 'System.Byte[]'."

If I leave the Action set to Action<object> it makes it to the success function and I can see the result is a JSArray. I think I'm close, but.....
It ain't easy being green!

TaterJuice
Posts: 147
Joined: Thu Mar 16, 2017 5:40 am
Contact:

Re: jQuery.ajax Extension for CSHTML5

Postby TaterJuice » Wed Sep 12, 2018 2:57 pm

TooTallTommyT wrote:I've tried modifying this extension to download various binary files: images, .obj fiiles, and other binary files. I've tried setting a responseType on the ajax call to 'arraybuffer', and to 'blob', and setting the Action to 'Action<byte[]>, but the method keeps erring out saying "CSHTML5.Types.INTERNAL_JSObjectReference cannot be converted to 'System.Byte[]'."

If I leave the Action set to Action<object> it makes it to the success function and I can see the result is a JSArray. I think I'm close, but.....

Now you've got me curious...
I've seen this before, too - but it only happens to me in the simulator. In Chrome, I never receive this error. What do you see in the browser?

User avatar
TooTallTommyT
Posts: 19
Joined: Tue Aug 21, 2018 6:51 am
Location: Las Vegas, NV

Re: jQuery.ajax Extension for CSHTML5

Postby TooTallTommyT » Wed Sep 12, 2018 3:05 pm

I can never get passed the simulator, so it won’t build the js files, and consequently I never get a chance to run it in a browser.
It ain't easy being green!

User avatar
TooTallTommyT
Posts: 19
Joined: Tue Aug 21, 2018 6:51 am
Location: Las Vegas, NV

Re: jQuery.ajax Extension for CSHTML5

Postby TooTallTommyT » Wed Sep 12, 2018 5:05 pm

I found the way to compile the js without the simulator, and running it in the browser seems to work okay. At least, I am getting data back now, though I have yet to verify the contents. But, it's a step in the right direction.
It ain't easy being green!

TaterJuice
Posts: 147
Joined: Thu Mar 16, 2017 5:40 am
Contact:

Re: jQuery.ajax Extension for CSHTML5

Postby TaterJuice » Thu Sep 13, 2018 10:41 am

TooTallTommyT wrote:I found the way to compile the js without the simulator, and running it in the browser seems to work okay. At least, I am getting data back now, though I have yet to verify the contents. But, it's a step in the right direction.


Ahhh - see, my app loads before making any ajax\API calls, so the simulator loads and transpiles to html\js, but in Simulator I randomly get those Internal JSObject conversion errors when deserializing ajax response data. I have never seen the error in a browser, though. Only simulator (and it's terribly intermittent)


Return to “Extensions and Plugins for CSHTML5”

Who is online

Users browsing this forum: No registered users and 0 guests