Search code examples
javascriptblazorinterop.net-maui

Net MAUI (Blazor) Inject IJSRuntime into C# Class


I am trying to use javascript outside the razor page. I am trying to inject IJSRuntime in another class that would handle all the javascript:

public class InvokeJavaScriptService 
    {
        private IJSRuntime js;
        public InvokeJavaScriptService(IJSRuntime js)
        {
            this.js = js; 
        }

        public async Task CallJsFromCSharp()
        {
            try
            {
                await js.InvokeAsync<object>("invokeJSfromCS");
            }
            catch(Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
           
        }
    }

I register this service like this:

 builder.Services.AddScoped<InvokeJavaScriptService>();

but when calling CallJsFromCSharp() I get this error:

enter image description here

INSTEAD of the desired outcome of triggering this function invokeJSFromCS in index.html:

<script>
        async function invokeJSfromCS() {
            var value = "C# Method called from JavaScript with parameter";
            // Invoke to call C# function from JavaScript with parameter.
            DotNet.invokeMethodAsync ('MauiBlazorTestApp', 'JStoCSCall', value);
        }
    </script>

and then getting a callback in index.razor:

<!-- language: html -->
@page "/"
<div>
</div>

@code{
    <!-- language: c# -->
    protected override async void OnInitialized()
    {
    }

    private static string content { get; set; }

    [JSInvokable] // Return call back from JavaScript with parameter to C#.
    public static void JStoCSCall(string value)
    {
        content = value;
    }

}

It is possible to inject IJSRuntime into a razor page like this: @inject IJSRuntime, shouldn't it be possible to inject into a c# class well, how do I make this work please?


Solution

  • I have done a sample to test inject IJSRuntime into C# class, and it worked well.

    MyService.cs:

    using Microsoft.JSInterop;
    namespace MauiAppTest.Data
    {
    public class MyService
    {
        private IJSRuntime jSRuntime;
        public MyService(IJSRuntime jSRuntime)
        {
            this.jSRuntime = jSRuntime;
        }
        public void test()
        {
            jSRuntime.InvokeVoidAsync("alert", "Alert");
        }
    }
    }
    

    And the .razor:

    @using MauiAppTest.Data
    @inject MyService myService
    @code {
    protected override async Task OnInitializedAsync()
    {
        myService.test();
    }
    }
    

    And then I try to pass the value from JS to the razor page:

    @inject IJSRuntime js
    private string message{ get; set; }
    protected override async Task OnInitializedAsync()
    {
        await js.InvokeVoidAsync("Myjs", DotNetObjectReference.Create(this));
    }
    [JSInvokable]
    public void Setvalue(string value) => message = value;
    

    And the Js Function:

    <script>
        function Myjs(instance) {
             var value = "hello";
             instance.invokeMethodAsync('Setvalue', value);
        }
    </script>
    

    The value can be passed to the razor page.