5:27 0 0
Invocar desde JavaScript a Blazor App

Invocar desde JavaScript a Blazor App

  DrUalcman |  julio 242021

Desde Blazor es muy fácil invocar a funciones de JavaScript, pero la cosa se complica un poco cuando lo que necesitamos es que desdde JavaScript invoque algún método que está en nuestro código de C# en Blazor. Un ejemplio es, muy normal, en llamadas a scripts que no manejamos nosotros, como PAYPAL, que tras una operación realizará un callback a alguna función, y claro esta debería de estar en nuestro C#. Por ello de este blog hoy. Como invoicar métodos desde JavaScript a Blazor.

Primero me gustaría comentar que el framwork de Blazor dispone de un objeto DotNet con el cuál podremos hacer ésta interoperabilidad. Los principales métodos para hacer esto son, como se remarcan en la imagen, invokeMethod, que devuelve síncronamente el valor, y invokeMethodAsync, que devuelve una promesa con el valor. 

DotNet Propiedades y métodos

Normalmente utiizaremos el invokeMethodAsync así lo recomienda Microsoft. Este método espera dos parámetros obligatorios y uno opcional:

  • El nombre del assembly, requerido.
  • El nombre del método, requerido.
  • Los parámetros a enviar, opcional. es un params[] por lo que cada parámetro se pasrá separado por comas [,].
DotNet.invokeMethodAsync('{ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});

Luego, como veremos más adelante, hay otra forma de usarlo sin necesidad de enviar el assembly, pero esperemos un poco para no liar ahora esta sección.

Es importante saber correctamente el nombre del assembly y dónde localizarlo, ya que muchas veces tendemos apensar que el el nombre del namespace que estamos usando, y no es exáctamente así, ya que podemos trabajar con un namespace difference del que tenemos como assembly. Para conocer cuál es exáctamente nuestro assembly tenemos que comprobarlo en las propiedades del proyecto en Visual Studio e irnos al campo Assembly Name, siempre que estes trabajando con Visual Studio en inglés. Ese será el nombre que deberás de usar al enviar los parámetros en la llamada al inokeMethosAsync.

Invocar métodos estáticos

Lo más sencillo es invocar a un método estático dentro de nuestra aplicación Blazor. Para ello sólo tenemos que decorar nuestro método con el atributo [JsInvokable] como se muestra en el ejemplo siquiente:
@code {
[JSInvokable]
public static Task{} MethodNameAsync()
{
// your logic
}
}
Para llamar es éste método desde JavaScript sólo tienes que hacer uso del objeto DotNet y del método invokeMethodAsync pasándole todos los parámetros. Como nuestro método de ejemplo no acepta ningún parámetro la llamada sería tan fácil como:
< script>
function CallBlazorMethod {
DotNet.invokeMethodAsync('BlazorSample', 'MethodNameAsync')
.then(data => {
console.log(data);
}
< /script>
Observar que el método va a recibir algún tipo de datos, o está esperando recibir algún tipo de datos, esto sería si, por ejemplo, desde nuestro método en C# vamos a enviar datos a nuestro JavaScript para que continúe con otro proceso.

Invocando métodos de instancia.

Bien aquí es dónde ahora se complica un poco más la cosa. La desventaja que tiene invocar a un método estático es, principalmente, el no poder usar o manejar variables o propiedades de nuestro componente directamente, salvo que también sean estáticas. Otro inconveniente es, que si necesitamos hacer uso de HttpClient, como he visto en otros blogs, pues necesitas hacer una referencia stática y pasarle la referencia de una instancia de HttpClient, por lo que desde mi punto de vista, consume más recursos.

Para resolver este problema tenemos la posibilidad de pasar una instancia de nuestro componente a JavaScript y así poder utilizar directamente todas las variables que tenemos instanciadas en el mismo, por lo que la funcionalidad de la interoperabilidad, ahora, gana mucho sentido. Pero al mismo tiempo nos obliga a un poco más de codigo y al mismo tiempo simplifica un poco más como usarlo desde JavaScript. 

Veamos primero la diferencia con JavaScript. Como estamos enviando una instancia de nuestro objeto dentro de nuestra aplicación, pues ya no es necesario el assembly ya que es desde ese assembly que se está invocando al método invokeMethodAsync o invokeMethod, recuerda que lo recomendado es siempre usar la versión asíncrona.

Declarando una variable de instancia.

Debemos declarar un variable del topo DotNetObjectReference que encapsulará nuestra clase del componente.

@page "/SampleJavaScriptToInstance"
@implements IDisposable
@inject IJSRuntime JS

< h1>Call .NET method instance from JavaScript< /h1>

< p>
< button @onclick="CallJavaScript">
Trigger .NET instance method
< /button>
< /p>

@code {
private DotNetObjectReference ObjRef;

protected async Task CallJavaScript()
{
ObjRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("CallInstanceMethod", ObjRef);
}

[JSInvokable]
public static Task{} MethodNameAsync()
{
// your logic
}

public void Dispose()
{
ObjRef?.Dispose();
}
}

Esto podría ser un ejemplo ce cómo enviar la referencia de nuestro componente a una función en JavaScript para que ésta ejecute su código e invoque a nuestro método dentro del componente. Nuesto método CallJavaScript ejecutará una función la cual volverá a ejecutar otro método dentro de nuestro objeto para que el código contnue su ejecución cuando la función de JavaScript así lo tenga en su lógica.

Llamando al método de instancia de C# desde la función JavaScript

Ahora veamos cómo sería la función de JavaScript que va a hacer la llamada al método de instancia de nuestro componente, es aquí dónde cambia un poco la llamada al invoiceMethodAsync o invokeMethod desde JavaScript. Como ya mencioné antes, ya tenemos un objeto de nuestro componente, ¿y que pasa en este componente? que ya tiene una instancia de IJSRuntime, y, además, ya es una instancia de nuestro assembly. Por lo tanto ya no es necesario utilizar el objeto DotNet porque lo tenemos dentro de nuestro objeto enviado ObjRef. Me explico. ObjRef ya es una instancia de DotNet y por lo tanto, dispone de todas sus propiedades y métodos.

Pasemos a ver como sería nuestro código en JavaScript para esta situación:

< script>
function CallInstanceMethod(dotNetObj)
{
dotNetObj.invokeMethodAsync('MethodNameAsync').then(data => {
console.log(data);}
}
< /script>

A tener en cuenta que la función de JavaScript debe de recibir como parámetro el objeto que encapsula a nuestro componente, y luego podría recibir más parámetros como en cualquier invocación de JavaScript desde C#.

Este objeto implementa DotNet y por lo tanto es éste objeto el que sólo necesita el nombre del método a invocar, ya que el assembly es el que contiene el objeto que estamos referenciando.

Uso del Dispose

Como buenas prácticas es recomendable no olvidarse de usar el Dispose del objeto para que así libreremos correctametne los recursos del navegador cuando el usuario abandone el componente dónde se está haciendo referencia.

Consideraciones

En el atributo [JsInvokable] tenemos la posibilidad de hacer una sobre escritura del nombre del métod de C# a invoicar, esto es, que si por cualquier motivo resulta que no queremos llamar al método de C# tal cual se llama en nuestro código, tenemos la posibilidad de renombrarlo pasando un nuevo nombre cuando lo decoramos.

[JSInvokable("DifferentMethodName")]

Por lo que tenemos mucha flexibilidad para programar. Tener en cuenta que deberemos de usar este nuevo nombre cuando utilicemos el método invokeMethodAsync o invokeMethod para el parámetro MethodName.

Espero que este post os ayude, y cualquier cosa ya saben dónde encontrarme.


#blazor #javascript #interop #interoperabilidad

0 Comentarios

 
 
 

Archivo