Search code examples
javascripthtml.netrazorblazor

Methods that don't work because they don't recognize it


My intention was to make a page for modifying a map, where I take the positions of each element (they are images of tables) and make a real-time editor.

However, when trying to move a table from one point to another, despite calling the functions correctly, I get errors that I am not making calls.

I have looked at possible errors such as that the methods should not be static, but they are not.

Code complete:

https://github.com/MarcomedSoltel/Problem/blob/main/SalonModify.razor


@page "/minimal-example"
@inject IJSRuntime JSRuntime
@inject ILogger<MinimalExample> Logger

<h3>Minimal Example Component</h3>

<button @onclick="InvokeJS">Click me to trigger JS</button>

@code {
    private bool isDragging = false;

    [JSInvokable]
    public Task SetDraggingState(bool dragging)
    {
        // Lógica para actualizar el estado de arrastre
        isDragging = dragging;
        Logger.LogInformation($"Dragging state updated to: {dragging}");
        return Task.CompletedTask;
    }

    [JSInvokable]
    public async Task UpdateElementPositionAsync(int dibujoId, int newX, int newY)
    {
        Logger.LogInformation($"Element {dibujoId} moved to new position: (X: {newX}, Y: {newY})");
        // Lógica simplificada para actualizar la posición
        await Task.CompletedTask;
    }

    private async Task InvokeJS()
    {
        await JSRuntime.InvokeVoidAsync("initializeSortable");
    }
}

<script>
    window.initializeSortable = () => {
        DotNet.invokeMethodAsync('RMSuit_v2', 'SetDraggingState', true)
            .then(() => console.log("Dragging state set to true"))
            .catch(error => console.error('Error setting dragging state:', error));

        let elementId = 1; // Simulando un elemento con ID 1
        let newX = 100;
        let newY = 200;

        DotNet.invokeMethodAsync('RMSuit_v2', 'UpdateElementPositionAsync', elementId, newX, newY)
            .then(() => console.log(`Element ${elementId} position updated`))
            .catch(error => console.error('Error updating position:', error));
    };
</script>

The error:

Mensaje registrado: Error al actualizar estado de arrastre: Error: System.ArgumentException: The assembly 'RMSuit_v2' does not contain a public invokable method with [JSInvokableAttribute("SetDraggingState")]. at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.GetCachedMethodInfo(AssemblyKey assemblyKey, String methodIdentifier) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously(JSRuntime jsRuntime, DotNetInvocationInfo& callInfo, IDotNetObjectReference objectReference, String argsJson) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, String argsJson) VM15:11 Mensaje registrado: Elemento 101 movido a X: 303, Y: 164 VM15:11 Mensaje registrado: Error al actualizar la posición: Error: System.ArgumentException: The assembly 'RMSuit_v2' does not contain a public invokable method with [JSInvokableAttribute("UpdateElementPositionAsync")]. at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.GetCachedMethodInfo(AssemblyKey assemblyKey, String methodIdentifier) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously(JSRuntime jsRuntime, DotNetInvocationInfo& callInfo, IDotNetObjectReference objectReference, String argsJson) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, String argsJson) VM15:11 Mensaje registrado: Error al actualizar estado de arrastre: Error: System.ArgumentException: The assembly 'RMSuit_v2' does not contain a public invokable method with [JSInvokableAttribute("SetDraggingState")]. at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.GetCachedMethodInfo(AssemblyKey assemblyKey, String methodIdentifier) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously(JSRuntime jsRuntime, DotNetInvocationInfo& callInfo, IDotNetObjectReference objectReference, String argsJson) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, String argsJson)

I am trying to get these methods to work so that it works with the objective of being able to drag the elements of the images that I am recreating, to create a real-time editor of the map.


Solution

  • You have two options:

    1. use a static method
    2. pass a reference to a DotNetObjectReference to your Javascript, and reference it when accessing the instance method.

    You can create a DotNetObjectReference either to a class instance or to the Blazor page itself (which technically IS a class instance). The following is not runnable, just showing some syntax:

    MyClass myclassinstance = new(); // Obviously, must have the method you want.
    private DotNetObjectReference<Example> dotNetRef;
    
    // probably in OnAfterRender or on a button click
    dotNetRef = DotNetObjectReference.Create(myclassinstance );
    dotNetRef = DotNetObjectReference.Create(this); // i.e. this page / component
    
    async Task MyPageMethod(){
    }
    
    // Call like this:
    await JSRuntime.InvokeVoidAsync("MyPageMethod", dotNetRef);
    await JSRuntime.InvokeVoidAsync("MyClassMethod", dotNetRef);
    

    If you need to pass parameters, just put them after dotNetRef separated by commas.

    Reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript?view=aspnetcore-8.0

    Note: I don't usually use ChatGPT, but it's now really good at giving examples of stuff like this when the documentation is unclear (as the above is IMO). Not sure if I'm allowed to say that on SO or not.