blazor-webassemblyjavascript-interop

Blazor Unmarshalled JavaScript interop


To improve performance in Blazor JS Interop calls, synchronous and unmarshalled apis are available

I struggle to find more information regarding the unmarshalled.

For example:

//javascript
JSFunctions.f1 = function (fields) {
    var f1 = Blazor.platform.readStringField(fields, 0);
    var f2 = Blazor.platform.readStringField(fields, 4);
    var f3 = Blazor.platform.readStringField(fields, 8);
};


//F#
[<Inject>]
member val Js: IJSRuntime
let js = this.Js :?> IJSUnmarshalledRuntime
js.InvokeUnmarshalled<ElementReference, string, unit>("JSFunctions.f1", er, txt)
  1. Where are the functions Blazor.platform.* defined?
  2. Which one should be used to retrieve an argument of type ElementReference?
  3. What is the second int parameter of the function readStringField and how should it be used?

Solution

  • Blazor object is a JavaScript object in global namespace (window) which added by blazor.webassembly.js in Blazor WebAssembly or blazor.server.js in Blazor Server. It added at the default template of Blazor Apps at the end of index.html (or _Host.cshtml) by following script:

    <script autostart="false" src="_framework/blazor.webassembly.js"></script>
    

    The Blazor object provide Blazor.platform and some useful api for example start() for manual start of Blazor. This script also add another object named BINDING to global namespace (window.BINDING or simply BINDING). They provide methods for working with .NET objects directly from JavaScript in unmarshalled way. for example you can read different type of data using

    Blazor.platform.read....
    

    You can read objects like ElementReference type object using:

    Blazor.platform.readObjectField(fields,index)
    

    Here fields is the input (struct or class) passed to JS function when you invoke it and index is its field offset in struct/class definition. You can read more about field offset in Microsoft documentations here. Here is some example:

    [StructLayout(LayoutKind.Explicit)]
        public struct InteropStruct
        {
            [FieldOffset(0)]
            public string Name;
    
            [FieldOffset(8)]
            public int Year;
        }
    

    You can also return a .Net object directly from JavaScript functions using BINDING as below:

    return BINDING.js_string_to_mono_string(`Hello, ${name} (${year})!`);
    

    You can discover more about these two objects in your browser developer tool for example by writing Blazor.platform. or BINDING.: