¿Cómo puedo obtener una devolución de llamada de Javascript en .Net Blazor?

5
samtax01 2019-06-17 08:37.

¿Hay alguna manera de agregar devolución de llamada a Javascript y obtener el resultado en Blazor? Aparte de JS Promises.

por ejemplo, digamos que quiero cargar un archivo

Código Javascript

window.readFile = function(filePath, callBack) {
    var reader = new FileReader();
    reader.onload = function (evt) {
        callBack(evt.target.result);
    };
    reader.readAsText(filePath);
}

¿Puedo tener algo como esto en Blazor C #?

    // read file content and output result to console
    void GetFileContent() {
        JsRuntime.InvokeAsync<object>("readFile", "file.txt", (string text) => {
            Console.Write(text);
        });
    }

O tal vez algo como esto

    // read with javascript
    void ReadFileContent() {
        JsRuntime.InvokeAsync<object>("readFile", "file.txt", "resultCallbackMethod");
    }

    // output result callback to console
    void resultCallbackMethod(string text) {
        Console.Write(text);
    }

Gracias

4 answers

4
Henry Rodriguez 2019-06-17 21:14.

ACTUALIZACIÓN 1:

Después de volver a leer su pregunta, creo que esto cubriría su segundo ejemplo

Creo que tiene la opción de implementar una función de proxy JS que maneja la llamada. Algo como esto:

ACTUALIZACIÓN 2:

El código se actualizó con una versión funcional (pero no profundamente probada), también puede encontrar un ejemplo de trabajo en blazorfiddle.com

CÓDIGO JAVASCRIPT

// Target Javascript function
window.readFile = function (filePath, callBack) {

    var fileInput = document.getElementById('fileInput');
    var file = fileInput.files[0];

    var reader = new FileReader();

    reader.onload = function (evt) {
        callBack(evt.target.result);
    };

    reader.readAsText(file);

}

// Proxy function
// blazorInstance: A reference to the actual C# class instance, required to invoke C# methods inside it
// blazorCallbackName: parameter that will get the name of the C# method used as callback
window.readFileProxy = (instance, callbackMethod, fileName) => {

    // Execute function that will do the actual job
    window.readFile(fileName, result => {
        // Invoke the C# callback method passing the result as parameter
        instance.invokeMethodAsync(callbackMethod, result);
    });

}

C # CÓDIGO

@page "/"

@inject IJSRuntime jsRuntime

<div>
    Select a text file:
    <input type="file" id="fileInput" @onchange="@ReadFileContent" />
</div>
<pre>
    @fileContent
</pre>

Welcome to your new app.

@code{

    private string fileContent { get; set; }

    public static object CreateDotNetObjectRefSyncObj = new object();

    public async Task ReadFileContent(UIChangeEventArgs ea)
    {
        // Fire & Forget: ConfigureAwait(false) is telling "I'm not expecting this call to return a thing"
        await jsRuntime.InvokeAsync<object>("readFileProxy", CreateDotNetObjectRef(this), "ReadFileCallback", ea.Value.ToString()).ConfigureAwait(false);
    }


    [JSInvokable] // This is required in order to JS be able to execute it
    public void ReadFileCallback(string response)
    {
        fileContent = response?.ToString();
        StateHasChanged();
    }

    // Hack to fix https://github.com/aspnet/AspNetCore/issues/11159    
    protected DotNetObjectRef<T> CreateDotNetObjectRef<T>(T value) where T : class
    {
        lock (CreateDotNetObjectRefSyncObj)
        {
            JSRuntime.SetCurrentJSRuntime(jsRuntime);
            return DotNetObjectRef.Create(value);
        }
    }

}
1
App Pack 2019-06-17 17:25.

Creo que está buscando la información sobre la documentación aquí: https://docs.microsoft.com/en-us/aspnet/core/blazor/javascript-interop?view=aspnetcore-3.0#invoke-net-methods-from-javascript-functions

Muestra cómo llamar a Razor.Net desde Javascript. La documentación tiene más información, pero esencialmente necesitará el atributo [JSInvokable] en el método en razor y llamar a través de DotNet.invokeMethod en javascript.

0
samtax01 2019-06-20 17:37.

Gracias por eso @Henry Rodriguez. Creé algo a partir de él y pensé que también podría ser útil.

Tenga en cuenta que DotNetObjectRef.Create (esto) todavía funciona bien en otro método. Solo se observa que hay problemas con los eventos del ciclo de vida de Blazor en la vista previa6.https://github.com/aspnet/AspNetCore/issues/11159.

Esta es mi nueva implementación.

<div>
    Load the file content
    <button @click="@ReadFileContent">Get File Content</button>
</div>

<pre>
    @fileContent
</pre>

Welcome to your new app.

@code{
string fileContent;

//The button onclick will call this.
void GetFileContent() {
     JsRuntime.InvokeAsync<object>("callbackProxy", DotNetObjectRef.Create(this), "readFile", "file.txt", "ReadFileCallback");
}


//and this is the ReadFileCallback

[JSInvokable] // This is required for callable function in JS
public void ReadFileCallback(string filedata) {
    fileContent = filedata;
    StateHasChanged();
}

Y en blazor _Host.cshtml o index.html, incluya el conector de proxy de devolución de llamada

// Proxy function that serves as middlemen
 window.callbackProxy =  function(dotNetInstance, callMethod, param, callbackMethod){
    // Execute function that will do the actual job
    window[callMethod](param, function(result){
          // Invoke the C# callback method passing the result as parameter
           return dotNetInstance.invokeMethodAsync(callbackMethod, result);
     });
     return true;
 };



// Then The Javascript function too

 window.readFile = function(filePath, callBack) {
    var reader = new FileReader();
    reader.onload = function (evt) {
        callBack(evt.target.result);
    };
    reader.readAsText(filePath);
}

Esto funciona perfectamente para lo que necesitaba y es reutilizable.

0
LoneSpawn 2020-11-15 23:39.

Usando los consejos de esta página, se me ocurrió una versión más genérica que funciona con casi cualquier función basada en devolución de llamada.

Actualizar:

Ahora puede llamar a cualquier función cuyo último argumento sea una devolución de llamada. Puede pasar cualquier número de argumentos a la función y la devolución de llamada puede tener cualquier número de argumentos devueltos.

La función InvokeJS devuelve una instancia de CallbackerResponse que se puede utilizar para obtener el valor escrito de cualquiera de los argumentos de respuesta. Consulte los ejemplos y el código para obtener más información.

Basado en la devolución de llamada OP (fileContents (string)):

Ejemplo 1 (C # Blazor con await):

var response = await Callbacker.InvokeJS("window.readFile", filename);
var fileContents = response.GetArg<string>(0);
// fileContents available here

Ejemplo 2 (C # Blazor con devolución de llamada):

Callbacker.InvokeJS((response) => { 
    var fileContents = response.GetArg<string>(0);
    // fileContents available here
}, "window.readFile", filename);

Basado en devolución de llamada común (error (cadena), datos (objeto)):

Ejemplo 3 (C # Blazor con await):

// To call a javascript function with the arguments (arg1, arg2, arg3, callback)
// and where the callback arguments are (err, data)
var response = await Callbacker.InvokeJS("window.myObject.myFunction", arg1, arg2, arg3);
// deserialize callback argument 0 into C# string
var err = response.GetArg<string>(0);
// deserialize callback argument 1 into C# object
var data = response.GetArg<MyObjectType>(1);

En su Blazor Program.cs Main agregue singleton (o con alcance si lo desea) Callbacker

builder.Services.AddSingleton<Services.Callbacker>();

Agregue el servicio Callbacker en su página Blazor. Ejemplo: MyPage.razor.cs

[Inject]
public Callbacker Callbacker { get; set; }

C#

using Microsoft.JSInterop;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Home.Services
{
    public class CallbackerResponse
    {
        public string[] arguments { get; private set; }
        public CallbackerResponse(string[] arguments)
        {
            this.arguments = arguments;
        }
        public T GetArg<T>(int i)
        {
            return JsonConvert.DeserializeObject<T>(arguments[i]);
        }
    }

    public class Callbacker
    {
        private IJSRuntime _js = null;
        private DotNetObjectReference<Callbacker> _this = null;
        private Dictionary<string, Action<string[]>> _callbacks = new Dictionary<string, Action<string[]>>();

        public Callbacker(IJSRuntime JSRuntime)
        {
            _js = JSRuntime;
            _this = DotNetObjectReference.Create(this);
        }

        [JSInvokable]
        public void _Callback(string callbackId, string[] arguments)
        {
            if (_callbacks.TryGetValue(callbackId, out Action<string[]> callback))
            {
                _callbacks.Remove(callbackId);
                callback(arguments);
            }
        }

        public Task<CallbackerResponse> InvokeJS(string cmd, params object[] args)
        {
            var t = new TaskCompletionSource<CallbackerResponse>();
            _InvokeJS((string[] arguments) => {
                t.TrySetResult(new CallbackerResponse(arguments));
            }, cmd, args);
            return t.Task;
        }

        public void InvokeJS(Action<CallbackerResponse> callback, string cmd, params object[] args)
        {
            _InvokeJS((string[] arguments) => {
                callback(new CallbackerResponse(arguments));
            }, cmd, args);
        }

        private void _InvokeJS(Action<string[]> callback, string cmd, object[] args)
        {
            string callbackId;
            do
            {
                callbackId = Guid.NewGuid().ToString();
            } while (_callbacks.ContainsKey(callbackId));
            _callbacks[callbackId] = callback;
            _js.InvokeVoidAsync("window._callbacker", _this, "_Callback", callbackId, cmd, JsonConvert.SerializeObject(args));
        }
    }
}

JS

window._callbacker = function(callbackObjectInstance, callbackMethod, callbackId, cmd, args){
    var parts = cmd.split('.');
    var targetFunc = window;
    var parentObject = window;
    for(var i = 0; i < parts.length; i++){
        if (i == 0 && part == 'window') continue;
        var part = parts[i];
        parentObject = targetFunc;
        targetFunc = targetFunc[part];
    }
    args = JSON.parse(args);
    args.push(function(e, d){ 
        var args = [];
        for(var i in arguments) args.push(JSON.stringify(arguments[i]));
        callbackObjectInstance.invokeMethodAsync(callbackMethod, callbackId, args); 
    });
    targetFunc.apply(parentObject, args);
};

Related questions

MORE COOL STUFF

Jana Duggar: Todo lo que ha dicho sobre el amor y su ventana de 5 años para encontrar al 'Elegido'

Jana Duggar: Todo lo que ha dicho sobre el amor y su ventana de 5 años para encontrar al 'Elegido'

Jana Duggar ha sido abierta sobre su búsqueda del amor. Aquí está todo lo que ha dicho sobre el tema y su ventana de cinco años para el matrimonio.

Sam Heughan sabe exactamente lo que tomará del set de 'Outlander': 'Me siento como si fuera Jamie cuando me los pongo'

Sam Heughan sabe exactamente lo que tomará del set de 'Outlander': 'Me siento como si fuera Jamie cuando me los pongo'

La estrella de 'Outlander', Sam Heughan, reveló recientemente qué se llevará del set para recordar a Jamie Fraser, el papel que lo convirtió en una estrella.

La primera canción de los Beatles que fue una de las 'actuaciones más emocionantes' de la banda, según Fab Four Insider

La primera canción de los Beatles que fue una de las 'actuaciones más emocionantes' de la banda, según Fab Four Insider

'She Loves You' fue escrita en una hora, grabada en un día y fue la canción de The Beatles con una de las mejores interpretaciones de su carrera.

Dolly Parton ayudó a su abuela 'inválida' cuando ninguno de los otros nietos lo haría: también le hacía una broma

Dolly Parton ayudó a su abuela 'inválida' cuando ninguno de los otros nietos lo haría: también le hacía una broma

Dolly Parton y su abuela Bessie tenían una relación especial. La abuela Parton estaba muy enferma, pero eso no impidió que Dolly le hiciera una broma.

Las 10 especies de monos más "feas": Belleza poco convencional en los primates

Las 10 especies de monos más "feas": Belleza poco convencional en los primates

Algunos monos tienen mucha suerte con la genética. ¿Otros? No tanto. El mono más feo no es una sola especie, sino toda una galería de primates que te hacen mirar dos veces y preguntarte si la evolución te estaba jugando una broma.

¿Cuál es la madera más dura del mundo?

¿Cuál es la madera más dura del mundo?

Puede que pienses que el roble o el nogal americano son maderas resistentes, pero cuando se trata de las maderas más duras del mundo, ni siquiera se acercan.

10 de las criaturas marinas más aterradoras que acechan en las profundidades del océano

10 de las criaturas marinas más aterradoras que acechan en las profundidades del océano

El océano rebosa belleza, pero también esconde algunas de las criaturas marinas más aterradoras del planeta. Muchos de estos animales acechan en las profundidades oceánicas, en el oscuro y opresivo mundo de alta presión del océano.

Los 10 mejores encantamientos de espada en Minecraft

Los 10 mejores encantamientos de espada en Minecraft

Si te enfrentas a monstruos hostiles o te preparas para combates PvP, conocer los mejores encantamientos para espadas en Minecraft puede darte una gran ventaja. Encantar espadas te permite infligir más daño, aumentar los objetos que sueltan los monstruos y prolongar la durabilidad de tu espada.

Resumen del oso: ¿Es Marcus el hombre más amable, suave y sincero de Chicago?

Resumen del oso: ¿Es Marcus el hombre más amable, suave y sincero de Chicago?

“Children” lanza un cameo de renombre y algunas noticias devastadoras

Por $ 9,800, ¿los 'empacarías' en este Toyota RAV4 2008 de siete plazas?

Por $ 9,800, ¿los 'empacarías' en este Toyota RAV4 2008 de siete plazas?

Se dice que este RAV4 está en excelentes condiciones y preparado para un juego de sillas musicales.

Furgoneta de reparto de Amazon se enciende en una ardiente explosión durante el calor del verano en Houston

Furgoneta de reparto de Amazon se enciende en una ardiente explosión durante el calor del verano en Houston

Imágenes de drones capturaron a los bomberos que parecían tener dificultades para apagar el incendio.

Black Panther Show de Marvel será el programa animado más crucial hasta el momento

Black Panther Show de Marvel será el programa animado más crucial hasta el momento

Eyes of Wakanda se vincula directamente con la MCU, además de actualizaciones sobre X-Men '97, What If..., Daredevil y más.

Todo sobre el impresionante anillo de compromiso de zafiro de Kate Middleton (¡y la reliquia real en la que se inspiró!)

Todo sobre el impresionante anillo de compromiso de zafiro de Kate Middleton (¡y la reliquia real en la que se inspiró!)

El anillo de compromiso de Kate Middleton perteneció a la princesa Diana antes de que el príncipe William le propusiera matrimonio con él. Descubra todo lo que hay que saber sobre esta pieza histórica aquí.

¿Quién es la esposa de John Cleese? Todo sobre Jennifer Wade

¿Quién es la esposa de John Cleese? Todo sobre Jennifer Wade

John Cleese se casó con su esposa, Jennifer Wade, en 2012. Aquí encontrará todo lo que debe saber sobre la esposa de John Cleese, Jennifer Wade.

¿Quién es la esposa de Patton Oswalt? Todo sobre Meredith Salenger

¿Quién es la esposa de Patton Oswalt? Todo sobre Meredith Salenger

Patton Oswalt se casó con su esposa, la también actriz Meredith Salenger, en 2017. Aquí encontrará todo lo que debe saber sobre la esposa de Patton Oswalt, Meredith Salenger.

¿Quién es la esposa de Jason Kennedy? Todo sobre Lauren Scruggs Kennedy

¿Quién es la esposa de Jason Kennedy? Todo sobre Lauren Scruggs Kennedy

Aquí encontrará todo lo que debe saber sobre Lauren Scruggs Kennedy, la bloguera de moda y autora de best sellers del New York Times que espera su segundo hijo con la personalidad de televisión Jason Kennedy.

los pronombres dan mucho miedo

Me llama la atención De repente, como ocurre con tanta frecuencia Es el punto medio de nuevo <No, no el del Pacífico, tú, el del carnaval> Todos los titulares en voz alta...

3 formas comprobadas de mejorar su habilidad de escritura

Los beneficios de escribir y estrategias para ayudarte a hacerlo

3 formas comprobadas de mejorar su habilidad de escritura

En 2022, con el lanzamiento de GPT-3, la habilidad de escritura parece perder importancia. Con IA, las personas con mala escritura también pueden generar personal de calidad.

La erosión lenta: revelando las formas en que las personas se desgastan en sus carreras

La erosión lenta: revelando las formas en que las personas se desgastan en sus carreras

En el mundo acelerado y competitivo de hoy, la carrera de uno juega un papel importante en el crecimiento personal, la estabilidad financiera y la satisfacción general con la vida. Sin embargo, muchas personas se encuentran atrapadas en un ciclo implacable de estancamiento e insatisfacción, y su vida profesional se desvanece gradualmente.

¿Qué hace que un podcast sea influyente?

¿Qué hace que un podcast sea influyente?

La semana pasada noté un comunicado de prensa, enviado a través de PressGazette (un sitio web de noticias de los medios británicos). El artículo anunciaba que Acast, la empresa de publicidad y alojamiento de podcasts de Scandi, lideraría un consorcio de editores "probablemente los más influyentes" en podcasting.

Language