6

First, my JS:

class MyClass {
    static myMethod() {
        alert("TEST");
    }
}

I have my JS runtime injected like this:

[Inject] protected IJSRuntime Js { get; set; }

I want to call a static method like this:

Js.InvokeVoidAsync("MyClass.myMethod");

but I get an error:

Microsoft.JSInterop.JSException: Could not find 'MyClass' in 'window'.

Is there a sane, reasonable way around this, or only by adding window.MyClass = MyClass to my JS?

2
  • 4
    Nope that's the way to do it. learn.microsoft.com/en-us/aspnet/core/blazor/… Commented Nov 16, 2019 at 8:10
  • Make a wrapper function in JS that calls the class. This way has it's flaws but when you have a million lines of code left to debug, fast and simple has it's benefits as well. Commented Dec 16, 2022 at 4:39

2 Answers 2

4

Try this (assuming server side Blazor).

In your _Host.cshtml file:

(function () {
    window.MyClass = {
        myMethod: function () {
            return alert('TEST');
        }
    };
})();

in .razor file (at top):

@*Inject JSRuntime to allow JavaScript Interop *@
@inject IJSRuntime JSRuntime

In a method in your .razor file:

await JSRuntime.InvokeAsync<string>(
            "MyClass.myMethod", null
            );

See: Blazor JavaScript Interop

Sign up to request clarification or add additional context in comments.

1 Comment

What is the benefit wrapping it into an IIFE? You still register MyClass into global scope, so the encapsulation is useless, isn't it?
0

Yes, registering your method with the window object is correct.

The relevant part of the source code can be found here:

https://github.com/aspnet/Extensions/tree/master/src/JSInterop

Peeking into it you will find:

invokeJSFromDotNet: (identifier: string, argsJson: string) => { ... }

where

@param identifier Identifies the globally-reachable function to invoke.

Taking a look at the findJSFunction you see the part that checks if the given identifier is registered with the window object and if not generates the error you see:

function findJSFunction(identifier: string): Function {

(...)

    let result: any = window;
    let resultIdentifier = 'window';
    let lastSegmentValue: any;
    identifier.split('.').forEach(segment => {
      if (segment in result) {
        lastSegmentValue = result;
        result = result[segment];
        resultIdentifier += '.' + segment;
      } else {
        throw new Error(`Could not find '${segment}' in '${resultIdentifier}'.`);
      }
    });

1 Comment

Hm, classes are reachable via eval, which is not evil when used correctly. I made my own version of "call static" and "create instance" code, I wonder if there is a way to extend JSInterop to use those methods. I mean I made an extension class, but it uses extra JS to work.

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.