Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Note
Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.
Warning
A ASP.NET Core ezen verziója már nem támogatott. További információt a .NET és a .NET Core támogatási szabályzatában talál. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .
Ez a cikk bemutatja, hogyan hívhat meg .NET-metódusokat a JavaScriptből (JS).
A függvények .NET-ből való meghívásáról JS további információt a .NET-metódusok JavaScript-függvényeinek meghívása a ASP.NET Core-ban Blazorcímű témakörben talál.
Statikus .NET-metódus meghívása
Ha statikus .NET-metódust szeretne meghívni a JavaScriptből (JS), használja a JS függvényeket:
-
DotNet.invokeMethodAsync(ajánlott): Aszinkron mind a kiszolgálóoldali, mind az ügyféloldali összetevők esetében. -
DotNet.invokeMethod: Csak ügyféloldali összetevők esetén szinkron.
Adja meg a metódust tartalmazó szerelvény nevét, a statikus .NET metódus azonosítóját és az argumentumokat.
Az alábbi példában:
- A
{PACKAGE ID/ASSEMBLY NAME}helyőrző a projekt csomagazonosítója (<PackageId>a projektfájlban) egy alkalmazás kódtárának vagy szerelvénynevének. - A
{.NET METHOD ID}helyőrző a .NET metódusazonosító. - A
{ARGUMENTS}helyőrző nem kötelező, vesszővel tagolt argumentumokat ad át a metódusnak, amelyek mindegyikének JSON-szerializálhatónak kell lennie.
DotNet.invokeMethodAsync('{PACKAGE ID/ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});
DotNet.invokeMethodAsync A művelet eredményét képviselő értéket ad JS Promise vissza.
DotNet.invokeMethod (ügyféloldali összetevők) a művelet eredményét adja vissza.
Important
Kiszolgálóoldali összetevők esetén az aszinkron függvényt (invokeMethodAsync) javasoljuk a szinkron verzió (invokeMethod) felett.
A .NET metódusnak nyilvánosnak, statikusnak és attribútummal kell rendelkeznie[JSInvokable].
Az alábbi példában:
- A
{<T>}helyőrző a visszatérési típust jelzi, amely csak az értékeket visszaadó metódusokhoz szükséges. - A
{.NET METHOD ID}helyőrző a metódus azonosítója.
@code {
[JSInvokable]
public static Task{<T>} {.NET METHOD ID}()
{
...
}
}
Note
A nyitott általános metódusok meghívása statikus .NET-metódusokkal nem támogatott, de a példánymetelyekkel támogatott. További információt a .NET általános osztály metódusainak hívása című szakaszban talál.
A következő összetevőben a ReturnArrayAsync C# metódus egy tömböt int ad vissza. Az [JSInvokable] attribútum a metódusra lesz alkalmazva, így a metódus invokábilissá JSválik.
CallDotnet1.razor:
@page "/call-dotnet-1"
@implements IAsyncDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 1</PageTitle>
<h1>Call .NET Example 1</h1>
<p>
<button id="btn">Trigger .NET static method</button>
</p>
<p>
See the result in the developer tools console.
</p>
@code {
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/Pages/CallDotnet1.razor.js");
await module.InvokeVoidAsync("addHandlers");
}
}
[JSInvokable]
public static Task<int[]> ReturnArrayAsync() =>
Task.FromResult(new int[] { 11, 12, 13 });
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
}
}
CallDotnet1.razor.js:
export function returnArrayAsync() {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
console.log(data);
});
}
export function addHandlers() {
const btn = document.getElementById("btn");
btn.addEventListener("click", returnArrayAsync);
}
A addHandlersJS függvény egy eseményt click ad hozzá a gombhoz. A returnArrayAsyncJS függvény kezelőként van hozzárendelve.
A returnArrayAsyncJS függvény meghívja az ReturnArrayAsync összetevő .NET metódusát, amely naplózza az eredményt a böngésző webfejlesztői eszközeinek konzolján.
BlazorSample az alkalmazás szerelvényének neve.
CallDotnet1.razor:
@page "/call-dotnet-1"
@implements IAsyncDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 1</PageTitle>
<h1>Call .NET Example 1</h1>
<p>
<button id="btn">Trigger .NET static method</button>
</p>
<p>
See the result in the developer tools console.
</p>
@code {
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/Pages/CallDotnet1.razor.js");
await module.InvokeVoidAsync("addHandlers");
}
}
[JSInvokable]
public static Task<int[]> ReturnArrayAsync() =>
Task.FromResult(new int[] { 11, 12, 13 });
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
}
}
CallDotnet1.razor.js:
export function returnArrayAsync() {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
console.log(data);
});
}
export function addHandlers() {
const btn = document.getElementById("btn");
btn.addEventListener("click", returnArrayAsync);
}
A addHandlersJS függvény egy eseményt click ad hozzá a gombhoz. A returnArrayAsyncJS függvény kezelőként van hozzárendelve.
A returnArrayAsyncJS függvény meghívja az ReturnArrayAsync összetevő .NET metódusát, amely naplózza az eredményt a böngésző webfejlesztői eszközeinek konzolján.
BlazorSample az alkalmazás szerelvényének neve.
CallDotNetExample1.razor:
@page "/call-dotnet-example-1"
<h1>Call .NET Example 1</h1>
<p>
<button onclick="returnArrayAsync()">
Trigger .NET static method
</button>
</p>
@code {
[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
{
return Task.FromResult(new int[] { 1, 2, 3 });
}
}
CallDotNetExample1.razor:
@page "/call-dotnet-example-1"
<h1>Call .NET Example 1</h1>
<p>
<button onclick="returnArrayAsync()">
Trigger .NET static method
</button>
</p>
@code {
[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
{
return Task.FromResult(new int[] { 1, 2, 3 });
}
}
CallDotNetExample1.razor:
@page "/call-dotnet-example-1"
<h1>Call .NET Example 1</h1>
<p>
<button onclick="returnArrayAsync()">
Trigger .NET static method
</button>
</p>
@code {
[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
{
return Task.FromResult(new int[] { 1, 2, 3 });
}
}
CallDotNetExample1.razor:
@page "/call-dotnet-example-1"
<h1>Call .NET Example 1</h1>
<p>
<button onclick="returnArrayAsync()">
Trigger .NET static method
</button>
</p>
@code {
[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
{
return Task.FromResult(new int[] { 1, 2, 3 });
}
}
Az <button> elem onclick HTML-attribútuma a JavaScript onclick eseménykezelőjének hozzárendelése az click események feldolgozására, és nem a(z) Blazor@onclick direktíva attribútuma. A returnArrayAsyncJS függvény kezelőként van hozzárendelve.
Az alábbi returnArrayAsyncJS függvény meghívja az ReturnArrayAsync összetevő .NET metódusát, amely naplózza az eredményt a böngésző webfejlesztői eszközeinek konzolján.
BlazorSample az alkalmazás szerelvényének neve.
<script>
window.returnArrayAsync = () => {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
console.log(data);
});
};
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Ha a Trigger .NET static method gomb ki van jelölve, a böngésző fejlesztői eszközeinek konzoljának kimenete megjeleníti a tömbadatokat. A kimenet formátuma némileg eltér a böngészőktől. Az alábbi kimenet a Microsoft Edge által használt formátumot mutatja be:
Array(3) [ 11, 12, 13 ]
Adatok átadása .NET-metódusnak a invokeMethodAsync függvény meghívásakor az adatok argumentumként való átadásával.
Az adatok .NET-nek való átadásának bemutatásához adja át a kiindulási pozíciót annak a ReturnArrayAsync metódusnak, amelyben a metódus meghívása JStörténik:
export function returnArrayAsync() {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync', 14)
.then(data => {
console.log(data);
});
}
<script>
window.returnArrayAsync = () => {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync', 14)
.then(data => {
console.log(data);
});
};
</script>
Az összetevő invokable ReturnArrayAsync metódusa megkapja a kiindulási pozíciót, és abból építi ki a tömböt. A rendszer a következő tömböt adja vissza a konzolra való naplózáshoz:
[JSInvokable]
public static Task<int[]> ReturnArrayAsync(int startPosition) =>
Task.FromResult(Enumerable.Range(startPosition, 3).ToArray());
Az alkalmazás újrafordítása és a böngésző frissítése után a következő kimenet jelenik meg a böngésző konzolján a gomb kiválasztásakor:
Array(3) [ 14, 15, 16 ]
A hívás .NET metódusazonosítója a JS .NET metódus neve, de az attribútumkonstruktor használatával [JSInvokable] megadhat egy másik azonosítót. Az alábbi példában a DifferentMethodName metódust a ReturnArrayAsync metódusazonosítóval jelölték:
[JSInvokable("DifferentMethodName")]
A DotNet.invokeMethodAsync (kiszolgálóoldali vagy ügyféloldali összetevők) vagy DotNet.invokeMethod (csak ügyféloldali összetevők esetén) hívásban hívja meg a DifferentMethodName a ReturnArrayAsync .NET metódus végrehajtására.
DotNet.invokeMethodAsync('BlazorSample', 'DifferentMethodName');-
DotNet.invokeMethod('BlazorSample', 'DifferentMethodName');(csak ügyféloldali összetevők)
Note
A ReturnArrayAsync metódus-példa ebben a szakaszban a Task eredményét adja vissza explicit C# async és await kulcsszavak használata nélkül. Azoknál a metódusoknál, amelyek a async kulcsszót használják az aszinkron műveletek értékének visszaadására, jellemző a await és await használatával történő kódolási módszer.
ReturnArrayAsync módszer, amely async és await kulcsszavakkal van összeállítva:
[JSInvokable]
public static async Task<int[]> ReturnArrayAsync() =>
await Task.FromResult(new int[] { 11, 12, 13 });
További információért lásd a Aszinkron programozás async és await használatával című részt a C# útmutatóban.
JavaScript-objektum és adathivatkozások létrehozása a .NET-nek való továbbításhoz
A DotNet.createJSObjectReference(jsObject) objektumhivatkozás létrehozása érdekében hívja meg a JS, hogy azt át lehessen adni a .NET-nek, ahol a jsObject az a JS Object, amelyet a JS objektumhivatkozás létrehozásához használnak. Az alábbi példa egy nem szerializálható window objektumra mutató hivatkozást ad át a .NET-nek, amely a ReceiveWindowObject C# metódusban fogadja a következőként IJSObjectReference:
DotNet.invokeMethodAsync('{PACKAGE ID/ASSEMBLY NAME}', 'ReceiveWindowObject',
DotNet.createJSObjectReference(window));
[JSInvokable]
public static void ReceiveWindowObject(IJSObjectReference objRef)
{
...
}
Az előző példában a {PACKAGE ID/ASSEMBLY NAME} helyőrző a projekt csomagazonosítója (<PackageId> a projektfájlban) egy alkalmazás kódtárának vagy szerelvénynevének.
Note
Az előző példa nem követeli meg az JSObjectReferenceobjektum eltávolítását, mivel az objektumra mutató hivatkozás nem található a window fájlban JS.
Egy JSObjectReference hivatkozás fenntartása megköveteli annak felszabadítását, hogy elkerüljük a JS memória szivárgását a kliensnél. Az alábbi példa újraadja az előző kódot, hogy rögzítse a JSObjectReferencehivatkozásra mutató hivatkozást, majd a hivatkozás megsemmisítésére DotNet.disposeJSObjectReference() irányuló hívást:
var jsObjectReference = DotNet.createJSObjectReference(window);
DotNet.invokeMethodAsync('{PACKAGE ID/ASSEMBLY NAME}', 'ReceiveWindowObject', jsObjectReference);
DotNet.disposeJSObjectReference(jsObjectReference);
Az előző példában a {PACKAGE ID/ASSEMBLY NAME} helyőrző a projekt csomagazonosítója (<PackageId> a projektfájlban) egy alkalmazás kódtárának vagy szerelvénynevének.
DotNet.createJSStreamReference(streamReference) Hívás egy adatfolyam-hivatkozás JS létrehozásához, hogy az átadható legyen a .NET-nek, ahol streamReference egy ArrayBuffer, Blob vagy bármilyen típusú tömb, például Uint8Array vagy Float32Array, amit a JS streamhivatkozás létrehozásához használtak.
Példány .NET-metódus meghívása
Példány .NET-metódusának meghívása JavaScriptből (JS):
Adja át a .NET-példányt hivatkozásként JS úgy, hogy csomagolja be a példányt egy DotNetObjectReference objektumba, és hívja meg a Create-t rajta.
A .NET példány egy metódusának meghívása az átadott JS-ból történik az
invokeMethodAsync(ajánlott) vagyinvokeMethod(csak ügyféloldali összetevők) használatával. Adja meg a példány .NET metódusának azonosítóját és az argumentumokat. A .NET-példány argumentumként is átadható más .NET-metódusok JSmeghívásakor.Az alábbi példában:
-
dotNetHelperDotNetObjectReference egy. - A
{.NET METHOD ID}helyőrző a .NET metódusazonosító. - A
{ARGUMENTS}helyőrző nem kötelező, vesszővel tagolt argumentumokat ad át a metódusnak, amelyek mindegyikének JSON-szerializálhatónak kell lennie.
dotNetHelper.invokeMethodAsync('{.NET METHOD ID}', {ARGUMENTS});Note
invokeMethodAsyncésinvokeMethodne fogadj el szerelvénynévparamétert egy példánymetódus meghívásakor.invokeMethodAsyncA művelet eredményét képviselő értéket ad JSPromisevissza.invokeMethod(csak ügyféloldali összetevők esetén) a művelet eredményét adja vissza.Important
Kiszolgálóoldali összetevők esetén az aszinkron függvényt (
invokeMethodAsync) javasoljuk a szinkron verzió (invokeMethod) felett.-
Dobja el a DotNetObjectReference.
A cikk következő szakaszai a .NET-metódus példányának meghívására szolgáló különböző megközelítéseket mutatják be:
Kerülje a JavaScript által meghívható .NET metódusok eltávolítását.
Ez a szakasz az ügyféloldali alkalmazásokra vonatkozik, amelyeken engedélyezve van az idő előtti fordítás ésa futásidejű újrakapcsolás .
A következő szakaszokban szereplő példák közül több is egy osztálypéldány-megközelítésen alapul, ahol az attribútummal[JSInvokable] megjelölt JavaScript-invokable .NET metódus egy olyan osztály tagja, amely nem Razor összetevő. Ha az ilyen .NET-metódusok egy Razor összetevőben találhatók, akkor védve vannak a futtatókörnyezet újrakapcsolása vagy vágása ellen. Annak érdekében, hogy megvédje a .NET-metódusokat az összetevőkön kívüli Razor vágástól, implementálja a metódusokat az DynamicDependency osztály konstruktorának attribútumával, ahogy az alábbi példa is mutatja:
using System.Diagnostics.CodeAnalysis;
using Microsoft.JSInterop;
public class ExampleClass {
[DynamicDependency(nameof(ExampleJSInvokableMethod))]
public ExampleClass()
{
}
[JSInvokable]
public string ExampleJSInvokableMethod()
{
...
}
}
További információért lásd: .NET-könyvtárak előkészítése trimmeléshez: DynamicDependency.
Egy DotNetObjectReference átadása egy adott JavaScript-függvénynek
Az ebben a szakaszban szereplő példa bemutatja, hogyan adhat át egy DotNetObjectReference egy adott JavaScript-függvénynek.JS
Az alábbi sayHello1JS függvény DotNetObjectReference fogad, és a invokeMethodAsync segítségével meghívja egy összetevő GetHelloMessage .NET-metódusát.
<script>
window.sayHello1 = (dotNetHelper) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage');
};
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
A következő összetevőhöz:
- Az összetevő egy JS-invokable .NET metódust tartalmaz, amelynek neve
GetHelloMessage. - Ha a
Trigger .NET instance methodgombot kiválasztják, akkor a JS függvény hívódik meg asayHello1-dal. -
sayHello1:- Meghívja
GetHelloMessage, majd megkapja az üzenet eredményét. - Visszaadja az üzenet eredményét a hívási
TriggerDotNetInstanceMethodmetódusnak.
- Meghívja
- A beküldött
sayHello1resultüzenet megjelenik a felhasználó számára. - A memóriaszivárgás elkerülése és a szemétgyűjtés lehetővé tétele érdekében a DotNetObjectReference által létrehozott .NET objektum hivatkozást a
Disposemetódusban szabadítjuk fel.
CallDotnet2.razor:
@page "/call-dotnet-2"
@implements IDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 2</PageTitle>
<h1>Call .NET Example 2</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotnet2>? objRef;
protected override void OnInitialized() =>
objRef = DotNetObjectReference.Create(this);
public async Task TriggerDotNetInstanceMethod() =>
result = await JS.InvokeAsync<string>("sayHello1", objRef);
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
public void Dispose() => objRef?.Dispose();
}
CallDotnet2.razor:
@page "/call-dotnet-2"
@implements IDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 2</PageTitle>
<h1>Call .NET Example 2</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotnet2>? objRef;
protected override void OnInitialized() =>
objRef = DotNetObjectReference.Create(this);
public async Task TriggerDotNetInstanceMethod() =>
result = await JS.InvokeAsync<string>("sayHello1", objRef);
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
public void Dispose() => objRef?.Dispose();
}
CallDotNetExample2.razor:
@page "/call-dotnet-example-2"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 2</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotNetExample2>? objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
public void Dispose()
{
objRef?.Dispose();
}
}
CallDotNetExample2.razor:
@page "/call-dotnet-example-2"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 2</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotNetExample2>? objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
public void Dispose()
{
objRef?.Dispose();
}
}
CallDotNetExample2.razor:
@page "/call-dotnet-example-2"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 2</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
private DotNetObjectReference<CallDotNetExample2> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
public void Dispose()
{
objRef?.Dispose();
}
}
CallDotNetExample2.razor:
@page "/call-dotnet-example-2"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 2</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
private DotNetObjectReference<CallDotNetExample2> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
public void Dispose()
{
objRef?.Dispose();
}
}
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
Az alábbi útmutatással argumentumokat adhat át egy példánymetódusnak:
Adjon hozzá paramétereket a .NET metódus meghívásához. Az alábbi példában egy nevet ad át a metódusnak. Szükség szerint adjon hozzá további paramétereket a listához.
<script>
window.sayHello2 = (dotNetHelper, name) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage', name);
};
</script>
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
Adja meg a paraméterlistát a .NET metódusnak.
CallDotnet3.razor:
@page "/call-dotnet-3"
@implements IDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 3</PageTitle>
<h1>Call .NET Example 3</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotnet3>? objRef;
protected override void OnInitialized() =>
objRef = DotNetObjectReference.Create(this);
public async Task TriggerDotNetInstanceMethod() =>
result = await JS.InvokeAsync<string>("sayHello2", objRef, name);
[JSInvokable]
public string GetHelloMessage(string passedName) => $"Hello, {passedName}!";
public void Dispose() => objRef?.Dispose();
}
CallDotnet3.razor:
@page "/call-dotnet-3"
@implements IDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 3</PageTitle>
<h1>Call .NET Example 3</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotnet3>? objRef;
protected override void OnInitialized() =>
objRef = DotNetObjectReference.Create(this);
public async Task TriggerDotNetInstanceMethod() =>
result = await JS.InvokeAsync<string>("sayHello2", objRef, name);
[JSInvokable]
public string GetHelloMessage(string passedName) => $"Hello, {passedName}!";
public void Dispose() => objRef?.Dispose();
}
CallDotNetExample3.razor:
@page "/call-dotnet-example-3"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 3</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotNetExample3>? objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello2", objRef, name);
}
[JSInvokable]
public string GetHelloMessage(string passedName) => $"Hello, {passedName}!";
public void Dispose()
{
objRef?.Dispose();
}
}
CallDotNetExample3.razor:
@page "/call-dotnet-example-3"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 3</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private DotNetObjectReference<CallDotNetExample3>? objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello2", objRef, name);
}
[JSInvokable]
public string GetHelloMessage(string passedName) => $"Hello, {passedName}!";
public void Dispose()
{
objRef?.Dispose();
}
}
CallDotNetExample3.razor:
@page "/call-dotnet-example-3"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 3</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
private DotNetObjectReference<CallDotNetExample3> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello2", objRef, name);
}
[JSInvokable]
public string GetHelloMessage(string passedName) => $"Hello, {passedName}!";
public void Dispose()
{
objRef?.Dispose();
}
}
CallDotNetExample3.razor:
@page "/call-dotnet-example-3"
@implements IDisposable
@inject IJSRuntime JS
<h1>Call .NET Example 3</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
private DotNetObjectReference<CallDotNetExample3> objRef;
protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
}
public async Task TriggerDotNetInstanceMethod()
{
result = await JS.InvokeAsync<string>("sayHello2", objRef, name);
}
[JSInvokable]
public string GetHelloMessage(string passedName) => $"Hello, {passedName}!";
public void Dispose()
{
objRef?.Dispose();
}
}
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
Adjon át egy DotNetObjectReference osztályt, amely több JavaScript-függvényt tartalmaz.
Az ebben a szakaszban található példa bemutatja, hogyan adhat át egy DotNetObjectReference JavaScript-osztályt többJS függvényt tartalmazó osztálynak.
Hozzon létre és adjon át egy DotNetObjectReferenceéletciklus-metódusbólOnAfterRenderAsync egy JS osztályt több függvény számára. Győződjön meg arról, hogy a .NET-kód az alábbi példában látható módon felszabadítja a DotNetObjectReference erőforrást.
A következő összetevőben a Trigger JS function gombok a JS függvényeket a JSonclick tulajdonság beállításával hívják meg, nem pedig a Blazor@onclick direktíva attribútuma által.
CallDotNetExampleOneHelper.razor:
@page "/call-dotnet-example-one-helper"
@implements IAsyncDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET Example</PageTitle>
<h1>Pass <code>DotNetObjectReference</code> to a JavaScript class</h1>
<p>
<label>
Message: <input @bind="name" />
</label>
</p>
<p>
<button id="sayHelloBtn">
Trigger JS function <code>sayHello</code>
</button>
</p>
<p>
<button id="welcomeVisitorBtn">
Trigger JS function <code>welcomeVisitor</code>
</button>
</p>
@code {
private IJSObjectReference? module;
private string? name;
private DotNetObjectReference<CallDotNetExampleOneHelper>? dotNetHelper;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/Pages/CallDotNetExampleOneHelper.razor.js");
dotNetHelper = DotNetObjectReference.Create(this);
await module.InvokeVoidAsync("GreetingHelpers.setDotNetHelper",
dotNetHelper);
await module.InvokeVoidAsync("addHandlers");
}
}
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
[JSInvokable]
public string GetWelcomeMessage() => $"Welcome, {name}!";
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
dotNetHelper?.Dispose();
}
}
Az előző példában:
-
JSegy injektált IJSRuntime példány. A IJSRuntime-t a Blazor keretrendszer regisztrálja. - A változó neve
dotNetHelpertetszőleges, és bármely előnyben részesített névre módosítható. - Az összetevőnek explicit módon el kell végeznie a DotNetObjectReference szemétgyűjtést, és meg kell akadályoznia a memóriaszivárgást.
-
JSDisconnectedException a modul ártalmatlanítása során megszorul, ha BlazorSignalR áramköre elvész. Ha az előző kódot egy Blazor WebAssembly alkalmazásban használják, nincs SignalR kapcsolat, amit elveszíthetne, így eltávolíthatja a
try-catchblokkot, és meghagyhatja a sort, amely megsemmisíti a modult (await module.DisposeAsync();). További információ: ASP.NET Core Blazor JavaScript-együttműködés (JS interop).
CallDotNetExampleOneHelper.razor.js:
export class GreetingHelpers {
static dotNetHelper;
static setDotNetHelper(value) {
GreetingHelpers.dotNetHelper = value;
}
static async sayHello() {
const msg =
await GreetingHelpers.dotNetHelper.invokeMethodAsync('GetHelloMessage');
alert(`Message from .NET: "${msg}"`);
}
static async welcomeVisitor() {
const msg =
await GreetingHelpers.dotNetHelper.invokeMethodAsync('GetWelcomeMessage');
alert(`Message from .NET: "${msg}"`);
}
}
export function addHandlers() {
const sayHelloBtn = document.getElementById("sayHelloBtn");
sayHelloBtn.addEventListener("click", GreetingHelpers.sayHello);
const welcomeVisitorBtn = document.getElementById("welcomeVisitorBtn");
welcomeVisitorBtn.addEventListener("click", GreetingHelpers.welcomeVisitor);
}
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
@page "/call-dotnet-example-one-helper"
@implements IDisposable
@inject IJSRuntime JS
<h1>Pass <code>DotNetObjectReference</code> to a JavaScript class</h1>
<p>
<label>
Message: <input @bind="name" />
</label>
</p>
<p>
<button onclick="GreetingHelpers.sayHello()">
Trigger JS function <code>sayHello</code>
</button>
</p>
<p>
<button onclick="GreetingHelpers.welcomeVisitor()">
Trigger JS function <code>welcomeVisitor</code>
</button>
</p>
@code {
private string? name;
private DotNetObjectReference<CallDotNetExampleOneHelper>? dotNetHelper;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
dotNetHelper = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("GreetingHelpers.setDotNetHelper",
dotNetHelper);
}
}
[JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!";
[JSInvokable]
public string GetWelcomeMessage() => $"Welcome, {name}!";
public void Dispose()
{
dotNetHelper?.Dispose();
}
}
Az előző példában:
-
JSegy injektált IJSRuntime példány. A IJSRuntime-t a Blazor keretrendszer regisztrálja. - A változó neve
dotNetHelpertetszőleges, és bármely előnyben részesített névre módosítható. - Az összetevőnek explicit módon el kell végeznie a DotNetObjectReference szemétgyűjtést, és meg kell akadályoznia a memóriaszivárgást.
<script>
class GreetingHelpers {
static dotNetHelper;
static setDotNetHelper(value) {
GreetingHelpers.dotNetHelper = value;
}
static async sayHello() {
const msg =
await GreetingHelpers.dotNetHelper.invokeMethodAsync('GetHelloMessage');
alert(`Message from .NET: "${msg}"`);
}
static async welcomeVisitor() {
const msg =
await GreetingHelpers.dotNetHelper.invokeMethodAsync('GetWelcomeMessage');
alert(`Message from .NET: "${msg}"`);
}
}
window.GreetingHelpers = GreetingHelpers;
</script>
Az előző példában:
- A
GreetingHelpersosztály hozzáadódik azwindowobjektumhoz, hogy globálisan definiálja az osztályt, amely lehetővé teszi Blazor-nak az osztály megkeresését az JS interop során. - A változó neve
dotNetHelpertetszőleges, és bármely előnyben részesített névre módosítható.
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Általános .NET-osztály metódusok meghívása
A JavaScript (JS) függvények meghívhatják a .NET általános osztály metódusait, ahol egy JS függvény egy általános osztály .NET-metódusát hívja meg.
A következő általános típusosztályban (GenericType<TValue>):
- Az osztály egyetlen típusparaméterrel (
TValue) rendelkezik egyetlen általánosValuetulajdonsággal. - Az osztály két nem általános metódust jelölt meg az
[JSInvokable]attribútummal, mindegyikhez tartozik egy általános típusparaméter nevenewValue:-
Updateszinkron módon frissíti aValueértékét anewValuealapján. -
UpdateAsyncaszinkron módon frissíti aValueértékét anewValue-ben, miután létrehozza a Task.Yield várható feladatot, amely aszinkron módon visszatér a jelenlegi környezetbe, amikor az várakozik.
-
- Az osztály metódusai a konzolra írják a típust
TValueés az értéketValue. A konzolra való írás csak bemutató célokra használható. Az éles alkalmazások általában nem írnak a konzolra az alkalmazásnaplózás helyett. További információért lásd: Blazor és NAPLÓZÁS A .NET ÉS ASP.NET Core RENDSZEREKBEN.
Note
A nyitott általános típusok és metódusok nem adnak meg típushelyőrzőket. Ezzel szemben a zárt generikusok minden típushelyőrzőhöz biztosítanak típustípusokat. Az ebben a szakaszban szereplő példák a zárt generikusokat mutatják be, de JS az interop instance metódusok meghívása nyílt generikusokkal támogatott. A nyílt generikusok használata nem támogatott statikus .NET-metódushívásokhoz, amelyeket a cikk korábbi részében ismertettünk.
További információkért lásd a következő cikkeket:
- Általános osztályok és metódusok (C# dokumentáció)
- Általános osztályok (C# programozási útmutató)
- Általános összetevők a .NET-ben (.NET-dokumentáció)
GenericType.cs:
using Microsoft.JSInterop;
public class GenericType<TValue>
{
public TValue? Value { get; set; }
[JSInvokable]
public void Update(TValue newValue)
{
Value = newValue;
Console.WriteLine($"Update: GenericType<{typeof(TValue)}>: {Value}");
}
[JSInvokable]
public async Task UpdateAsync(TValue newValue)
{
await Task.Yield();
Value = newValue;
Console.WriteLine($"UpdateAsync: GenericType<{typeof(TValue)}>: {Value}");
}
}
A következő invokeMethodsAsync függvényben:
- Az általános típusosztályok
UpdateésUpdateAsyncmetódusok sztringeket és számokat jelölő argumentumokkal vannak meghívva. - Az ügyféloldali összetevők támogatják a .NET-metódusok szinkron hívását.
invokeMethodsyncInteroplogikai értéket kap, amely jelzi, hogy az JS interop az ügyfélen történik-e. AmikorsyncInteropvantrue,invokeMethodbiztonságosan meghívható. Ha az értéksyncInteropazfalse, a rendszer csak az aszinkron függvénytinvokeMethodAsynchívja meg, mert az JS interop egy kiszolgálóoldali összetevőben fut. - Bemutató célokra a DotNetObjectReference függvényhívás (
invokeMethodvagyinvokeMethodAsync), a .NET metódus neve (UpdatevagyUpdateAsync) és az argumentum a konzolra lesz írva. Az argumentumok véletlenszerű szám használatával teszik lehetővé a JS függvényhívásnak a .NET metódushíváshoz való egyeztetését (a .NET oldalán lévő konzolra is írva). A gyártási kód általában nem ír ki a konzolra, sem az ügyfélen, sem a kiszolgálón. Az éles alkalmazások általában alkalmazásnaplózásra támaszkodnak. További információért lásd: Blazor és NAPLÓZÁS A .NET ÉS ASP.NET Core RENDSZEREKBEN.
<script>
const randomInt = () => Math.floor(Math.random() * 99999);
window.invokeMethodsAsync = async (syncInterop, dotNetHelper1, dotNetHelper2) => {
var n = randomInt();
console.log(`JS: invokeMethodAsync:Update('string ${n}')`);
await dotNetHelper1.invokeMethodAsync('Update', `string ${n}`);
n = randomInt();
console.log(`JS: invokeMethodAsync:UpdateAsync('string ${n}')`);
await dotNetHelper1.invokeMethodAsync('UpdateAsync', `string ${n}`);
if (syncInterop) {
n = randomInt();
console.log(`JS: invokeMethod:Update('string ${n}')`);
dotNetHelper1.invokeMethod('Update', `string ${n}`);
}
n = randomInt();
console.log(`JS: invokeMethodAsync:Update(${n})`);
await dotNetHelper2.invokeMethodAsync('Update', n);
n = randomInt();
console.log(`JS: invokeMethodAsync:UpdateAsync(${n})`);
await dotNetHelper2.invokeMethodAsync('UpdateAsync', n);
if (syncInterop) {
n = randomInt();
console.log(`JS: invokeMethod:Update(${n})`);
dotNetHelper2.invokeMethod('Update', n);
}
};
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Az alábbi GenericsExample összetevőben:
- A JS függvény
invokeMethodsAsyncakkor lesz meghívva, amikor a gombotInvoke Interopkiválasztják. - A rendszer létrehoz egy típuspárt DotNetObjectReference, és átadja az JS függvénynek az
GenericTypepéldányaihozstring-ként ésint-ként.
GenericsExample.razor:
@page "/generics-example"
@implements IDisposable
@inject IJSRuntime JS
<p>
<button @onclick="InvokeInterop">Invoke Interop</button>
</p>
<ul>
<li>genericType1: @genericType1?.Value</li>
<li>genericType2: @genericType2?.Value</li>
</ul>
@code {
private GenericType<string> genericType1 = new() { Value = "string 0" };
private GenericType<int> genericType2 = new() { Value = 0 };
private DotNetObjectReference<GenericType<string>>? objRef1;
private DotNetObjectReference<GenericType<int>>? objRef2;
protected override void OnInitialized()
{
objRef1 = DotNetObjectReference.Create(genericType1);
objRef2 = DotNetObjectReference.Create(genericType2);
}
public async Task InvokeInterop()
{
var syncInterop = OperatingSystem.IsBrowser();
await JS.InvokeVoidAsync(
"invokeMethodsAsync", syncInterop, objRef1, objRef2);
}
public void Dispose()
{
objRef1?.Dispose();
objRef2?.Dispose();
}
}
@page "/generics-example"
@implements IDisposable
@inject IJSRuntime JS
<p>
<button @onclick="InvokeInterop">Invoke Interop</button>
</p>
<ul>
<li>genericType1: @genericType1?.Value</li>
<li>genericType2: @genericType2?.Value</li>
</ul>
@code {
private GenericType<string> genericType1 = new() { Value = "string 0" };
private GenericType<int> genericType2 = new() { Value = 0 };
private DotNetObjectReference<GenericType<string>>? objRef1;
private DotNetObjectReference<GenericType<int>>? objRef2;
protected override void OnInitialized()
{
objRef1 = DotNetObjectReference.Create(genericType1);
objRef2 = DotNetObjectReference.Create(genericType2);
}
public async Task InvokeInterop()
{
var syncInterop = OperatingSystem.IsBrowser();
await JS.InvokeVoidAsync(
"invokeMethodsAsync", syncInterop, objRef1, objRef2);
}
public void Dispose()
{
objRef1?.Dispose();
objRef2?.Dispose();
}
}
Az előző példában JS egy injektált IJSRuntime példány. A IJSRuntime-t a Blazor keretrendszer regisztrálja.
Az alábbi ábra az előző példa jellemző kimenetét mutatja be, amikor a Invoke Interop gombot egy ügyféloldali összetevőben választja ki:
JS: invokeMethodAsync:Update('string 37802')
.NET: Frissítés: GenericType<System.String>: string 37802
JS: invokeMethodAsync:UpdateAsync('string 53051')
JS: invokeMethod:Update('string 26784')
.NET: Frissítés: GenericType<System.String>: string 26784
JS: invokeMethodAsync:Update(14107)
.NET: Frissítés: GenericType<System.Int32>: 14107
JS: invokeMethodAsync:UpdateAsync(48995)
JS: invokeMethod:Update(12872)
.NET: Frissítés: GenericType<System.Int32>: 12872
.NET: UpdateAsync: GenericType<System.String>: string 53051
.NET: UpdateAsync: GenericType<System.Int32>: 48995
Ha az előző példa egy kiszolgálóoldali összetevőben van implementálva, a szinkron hívások invokeMethod elkerülhetők. Kiszolgálóoldali összetevők esetén az aszinkron függvényt (invokeMethodAsync) javasoljuk a szinkron verzió (invokeMethod) felett.
Kiszolgálóoldali összetevő jellemző kimenete:
JS: invokeMethodAsync:Update('string 34809')
.NET: Frissítés: GenericType<System.String>: string 34809
JS: invokeMethodAsync:UpdateAsync('string 93059')
JS: invokeMethodAsync:Update(41997)
.NET: Frissítés: GenericType<System.Int32>: 41997
JS: invokeMethodAsync:UpdateAsync(24652)
.NET: UpdateAsync: GenericType<System.String>: karakterlánc 93059
.NET: UpdateAsync: GenericType<System.Int32>: 24652
Az előző kimeneti példák azt mutatják, hogy az aszinkron metódusok különböző tényezőktől függően tetszőleges sorrendben hajtódnak végre és teljesülnek, beleértve a szálütemezést és a metódus végrehajtásának sebességét. Az aszinkron metódushívások befejezési sorrendjének megbízható előrejelzése nem lehetséges.
Osztálypéldány példák
A következő sayHello1JS függvény:
- Meghívja a
GetHelloMessage.NET metódust az átadott DotNetObjectReference. - Visszaadja az üzenetet a
GetHelloMessagehívónaksayHello1.
<script>
window.sayHello1 = (dotNetHelper) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage');
};
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
Az alábbi HelloHelper osztály rendelkezik egy JS-ként meghívható .NET metódussal, amelynek neve GetHelloMessage. Amikor HelloHelper létrejön, a Name tulajdonságban lévő névvel egy üzenetet ad vissza a rendszer a GetHelloMessage-ből.
HelloHelper.cs:
using Microsoft.JSInterop;
namespace BlazorSample;
public class HelloHelper(string? name)
{
public string? Name { get; set; } = name ?? "No Name";
[JSInvokable]
public string GetHelloMessage() => $"Hello, {Name}!";
}
using Microsoft.JSInterop;
namespace BlazorSample;
public class HelloHelper(string? name)
{
public string? Name { get; set; } = name ?? "No Name";
[JSInvokable]
public string GetHelloMessage() => $"Hello, {Name}!";
}
using Microsoft.JSInterop;
public class HelloHelper
{
public HelloHelper(string? name)
{
Name = name ?? "No Name";
}
public string? Name { get; set; }
[JSInvokable]
public string GetHelloMessage() => $"Hello, {Name}!";
}
using Microsoft.JSInterop;
public class HelloHelper
{
public HelloHelper(string? name)
{
Name = name ?? "No Name";
}
public string? Name { get; set; }
[JSInvokable]
public string GetHelloMessage() => $"Hello, {Name}!";
}
using Microsoft.JSInterop;
public class HelloHelper
{
public HelloHelper(string name)
{
Name = name;
}
public string Name { get; set; }
[JSInvokable]
public string GetHelloMessage() => $"Hello, {Name}!";
}
using Microsoft.JSInterop;
public class HelloHelper
{
public HelloHelper(string name)
{
Name = name;
}
public string Name { get; set; }
[JSInvokable]
public string GetHelloMessage() => $"Hello, {Name}!";
}
A következő CallHelloHelperGetHelloMessage osztály JsInteropClasses3 metódusa meghívja a JS függvényt sayHello1 egy új HelloHelper példányával.
JsInteropClasses3.cs:
using Microsoft.JSInterop;
namespace BlazorSample;
public class JsInteropClasses3(IJSRuntime js)
{
private readonly IJSRuntime js = js;
public async ValueTask<string> CallHelloHelperGetHelloMessage(string? name)
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
return await js.InvokeAsync<string>("sayHello1", objRef);
}
}
using Microsoft.JSInterop;
namespace BlazorSample;
public class JsInteropClasses3(IJSRuntime js)
{
private readonly IJSRuntime js = js;
public async ValueTask<string> CallHelloHelperGetHelloMessage(string? name)
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
return await js.InvokeAsync<string>("sayHello1", objRef);
}
}
using Microsoft.JSInterop;
public class JsInteropClasses3
{
private readonly IJSRuntime js;
public JsInteropClasses3(IJSRuntime js)
{
this.js = js;
}
public async ValueTask<string> CallHelloHelperGetHelloMessage(string? name)
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
return await js.InvokeAsync<string>("sayHello1", objRef);
}
}
using Microsoft.JSInterop;
public class JsInteropClasses3
{
private readonly IJSRuntime js;
public JsInteropClasses3(IJSRuntime js)
{
this.js = js;
}
public async ValueTask<string> CallHelloHelperGetHelloMessage(string? name)
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
return await js.InvokeAsync<string>("sayHello1", objRef);
}
}
using System.Threading.Tasks;
using Microsoft.JSInterop;
public class JsInteropClasses3
{
private readonly IJSRuntime js;
public JsInteropClasses3(IJSRuntime js)
{
this.js = js;
}
public async ValueTask<string> CallHelloHelperGetHelloMessage(string name)
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
return await js.InvokeAsync<string>("sayHello1", objRef);
}
}
using System.Threading.Tasks;
using Microsoft.JSInterop;
public class JsInteropClasses3
{
private readonly IJSRuntime js;
public JsInteropClasses3(IJSRuntime js)
{
this.js = js;
}
public async ValueTask<string> CallHelloHelperGetHelloMessage(string name)
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
return await js.InvokeAsync<string>("sayHello1", objRef);
}
}
A memóriaszivárgás elkerülése és a szemétgyűjtés engedélyezése érdekében a létrehozott .NET-objektumhivatkozást DotNetObjectReference töröljük, amikor az objektumhivatkozás a using var szintaxissal kilép a hatókörből.
Ha a Trigger .NET instance method gombot választják ki a következő összetevőben, a JsInteropClasses3.CallHelloHelperGetHelloMessage függvényt meghívják a name értékkel.
CallDotnet4.razor:
@page "/call-dotnet-4"
@inject IJSRuntime JS
<PageTitle>Call .NET 4</PageTitle>
<h1>Call .NET Example 4</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private JsInteropClasses3? jsInteropClasses;
protected override void OnInitialized() =>
jsInteropClasses = new JsInteropClasses3(JS);
private async Task TriggerDotNetInstanceMethod()
{
if (jsInteropClasses is not null)
{
result = await jsInteropClasses.CallHelloHelperGetHelloMessage(name);
}
}
}
CallDotnet4.razor:
@page "/call-dotnet-4"
@inject IJSRuntime JS
<PageTitle>Call .NET 4</PageTitle>
<h1>Call .NET Example 4</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private JsInteropClasses3? jsInteropClasses;
protected override void OnInitialized() =>
jsInteropClasses = new JsInteropClasses3(JS);
private async Task TriggerDotNetInstanceMethod()
{
if (jsInteropClasses is not null)
{
result = await jsInteropClasses.CallHelloHelperGetHelloMessage(name);
}
}
}
CallDotNetExample4.razor:
@page "/call-dotnet-example-4"
@inject IJSRuntime JS
<h1>Call .NET Example 4</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private JsInteropClasses3? jsInteropClasses;
protected override void OnInitialized()
{
jsInteropClasses = new JsInteropClasses3(JS);
}
private async Task TriggerDotNetInstanceMethod()
{
if (jsInteropClasses is not null)
{
result = await jsInteropClasses.CallHelloHelperGetHelloMessage(name);
}
}
}
CallDotNetExample4.razor:
@page "/call-dotnet-example-4"
@inject IJSRuntime JS
<h1>Call .NET Example 4</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
private JsInteropClasses3? jsInteropClasses;
protected override void OnInitialized()
{
jsInteropClasses = new JsInteropClasses3(JS);
}
private async Task TriggerDotNetInstanceMethod()
{
if (jsInteropClasses is not null)
{
result = await jsInteropClasses.CallHelloHelperGetHelloMessage(name);
}
}
}
CallDotNetExample4.razor:
@page "/call-dotnet-example-4"
@inject IJSRuntime JS
<h1>Call .NET Example 4</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
private JsInteropClasses3 jsInteropClasses;
protected override void OnInitialized()
{
jsInteropClasses = new JsInteropClasses3(JS);
}
private async Task TriggerDotNetInstanceMethod()
{
result = await jsInteropClasses.CallHelloHelperGetHelloMessage(name);
}
}
CallDotNetExample4.razor:
@page "/call-dotnet-example-4"
@inject IJSRuntime JS
<h1>Call .NET Example 4</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
private JsInteropClasses3 jsInteropClasses;
protected override void OnInitialized()
{
jsInteropClasses = new JsInteropClasses3(JS);
}
private async Task TriggerDotNetInstanceMethod()
{
result = await jsInteropClasses.CallHelloHelperGetHelloMessage(name);
}
}
Az alábbi képen a Amy Pond mezőben látható a Name nevű renderelt összetevő. A gomb kiválasztása Hello, Amy Pond! után megjelenik a felhasználói felületen:
Az osztályban JsInteropClasses3 látható előző minta teljes egészében implementálható egy összetevőben is.
CallDotnet5.razor:
@page "/call-dotnet-5"
@inject IJSRuntime JS
<PageTitle>Call .NET 5</PageTitle>
<h1>Call .NET Example 5</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
public async Task TriggerDotNetInstanceMethod()
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
}
CallDotnet5.razor:
@page "/call-dotnet-5"
@inject IJSRuntime JS
<PageTitle>Call .NET 5</PageTitle>
<h1>Call .NET Example 5</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
public async Task TriggerDotNetInstanceMethod()
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
}
CallDotNetExample5.razor:
@page "/call-dotnet-example-5"
@inject IJSRuntime JS
<h1>Call .NET Example 5</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
public async Task TriggerDotNetInstanceMethod()
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
}
CallDotNetExample5.razor:
@page "/call-dotnet-example-5"
@inject IJSRuntime JS
<h1>Call .NET Example 5</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string? name;
private string? result;
public async Task TriggerDotNetInstanceMethod()
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
}
CallDotNetExample5.razor:
@page "/call-dotnet-example-5"
@inject IJSRuntime JS
<h1>Call .NET Example 5</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
public async Task TriggerDotNetInstanceMethod()
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
}
CallDotNetExample5.razor:
@page "/call-dotnet-example-5"
@inject IJSRuntime JS
<h1>Call .NET Example 5</h1>
<p>
<label>
Name: <input @bind="name" />
</label>
</p>
<p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p>
<p>
@result
</p>
@code {
private string name;
private string result;
public async Task TriggerDotNetInstanceMethod()
{
using var objRef = DotNetObjectReference.Create(new HelloHelper(name));
result = await JS.InvokeAsync<string>("sayHello1", objRef);
}
}
A memóriaszivárgás elkerülése és a szemétgyűjtés engedélyezése érdekében a létrehozott .NET-objektumhivatkozást DotNetObjectReference töröljük, amikor az objektumhivatkozás a using var szintaxissal kilép a hatókörből.
Az összetevő által megjelenített kimenet az Hello, Amy Pond! , amikor a név Amy Pond meg van adva a name mezőben.
Az előző összetevőben a .NET-objektumhivatkozás el lesz osztva. Ha egy osztály vagy komponens nem szabadítja fel a DotNetObjectReference, akkor az ügyfélen keresztül a megadott dispose hívásával a DotNetObjectReference kezelő funkciót alkalmazva felszabadíthatja azt.
window.{JS FUNCTION NAME} = (dotNetHelper) => {
dotNetHelper.invokeMethodAsync('{.NET METHOD ID}');
dotNetHelper.dispose();
}
Az előző példában:
- A
{JS FUNCTION NAME}helyőrző a JS függvény neve. - A változó neve
dotNetHelpertetszőleges, és bármely előnyben részesített névre módosítható. - A
{.NET METHOD ID}helyőrző a .NET metódusazonosító.
Komponenspéldány .NET-metódusokhoz tartozó segédosztály
A segédosztály meghívhat egy .NET-példány metódust Action. A segédosztályok olyan helyzetekben hasznosak, amikor a statikus .NET-metódusok nem alkalmazhatók:
- Ha több azonos típusú összetevő jelenik meg ugyanazon a lapon.
- Kiszolgálóoldali alkalmazásokban, amelyek több felhasználóval egyidejűleg ugyanazt az összetevőt használják.
Az alábbi példában:
- Az összetevő több
ListItem1összetevőt tartalmaz. - Minden
ListItem1összetevő egy üzenetből és egy gombból áll. - Amikor kiválasztják a
ListItem1típusú komponens gombját, az aListItem1metódus módosítja aUpdateMessagelistaelem szövegét, és elrejti a gombot.
Az alábbi MessageUpdateInvokeHelper osztály egy JS-invokable .NET metódust tart fenn, UpdateMessageCaller amely az osztály példányosításakor megadott Action-t hívja meg.
MessageUpdateInvokeHelper.cs:
using Microsoft.JSInterop;
namespace BlazorSample;
public class MessageUpdateInvokeHelper(Action action)
{
private readonly Action action = action;
[JSInvokable]
public void UpdateMessageCaller() => action.Invoke();
}
using Microsoft.JSInterop;
namespace BlazorSample;
public class MessageUpdateInvokeHelper(Action action)
{
private readonly Action action = action;
[JSInvokable]
public void UpdateMessageCaller() => action.Invoke();
}
using Microsoft.JSInterop;
public class MessageUpdateInvokeHelper
{
private Action action;
public MessageUpdateInvokeHelper(Action action)
{
this.action = action;
}
[JSInvokable]
public void UpdateMessageCaller()
{
action.Invoke();
}
}
using Microsoft.JSInterop;
public class MessageUpdateInvokeHelper
{
private Action action;
public MessageUpdateInvokeHelper(Action action)
{
this.action = action;
}
[JSInvokable]
public void UpdateMessageCaller()
{
action.Invoke();
}
}
using System;
using Microsoft.JSInterop;
public class MessageUpdateInvokeHelper
{
private Action action;
public MessageUpdateInvokeHelper(Action action)
{
this.action = action;
}
[JSInvokable]
public void UpdateMessageCaller()
{
action.Invoke();
}
}
using System;
using Microsoft.JSInterop;
public class MessageUpdateInvokeHelper
{
private Action action;
public MessageUpdateInvokeHelper(Action action)
{
this.action = action;
}
[JSInvokable]
public void UpdateMessageCaller()
{
action.Invoke();
}
}
Az alábbi updateMessageCallerJS függvény meghívja a UpdateMessageCaller .NET metódust.
<script>
window.updateMessageCaller = (dotNetHelper) => {
dotNetHelper.invokeMethodAsync('UpdateMessageCaller');
dotNetHelper.dispose();
}
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
A következő ListItem1 összetevő egy megosztott összetevő, amely tetszőleges számú alkalommal használható egy szülőösszetevőben, és listaelemeket (<li>...</li>) hoz létre egy HTML-lista (<ul>...</ul> vagy <ol>...</ol>). Minden ListItem1 összetevőpéldány létrehoz egy MessageUpdateInvokeHelper példányt, amelynek Action a UpdateMessage metódushoz van beállítva.
Amikor egy ListItem1 komponens InteropCall gombja ki van választva, meghívásra kerül updateMessageCaller egy létrehozott DotNetObjectReference, amely a(z) MessageUpdateInvokeHelper példányhoz tartozik. Ez lehetővé teszi a keretrendszernek, hogy meghívja a UpdateMessageCallerListItem1 példányának MessageUpdateInvokeHelper-jét. Az átadott DotNetObjectReference megsemmisítésre kerül JS-ban (dotNetHelper.dispose()).
ListItem1.razor:
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code {
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper? messageUpdateInvokeHelper;
protected override void OnInitialized()
{
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
}
protected async Task InteropCall()
{
if (messageUpdateInvokeHelper is not null)
{
await JS.InvokeVoidAsync("updateMessageCaller",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
}
}
private void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
}
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code {
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper? messageUpdateInvokeHelper;
protected override void OnInitialized()
{
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
}
protected async Task InteropCall()
{
if (messageUpdateInvokeHelper is not null)
{
await JS.InvokeVoidAsync("updateMessageCaller",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
}
}
private void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
}
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code {
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper? messageUpdateInvokeHelper;
protected override void OnInitialized()
{
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
}
protected async Task InteropCall()
{
if (messageUpdateInvokeHelper is not null)
{
await JS.InvokeVoidAsync("updateMessageCaller",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
}
}
private void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
}
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code {
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper? messageUpdateInvokeHelper;
protected override void OnInitialized()
{
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
}
protected async Task InteropCall()
{
if (messageUpdateInvokeHelper is not null)
{
await JS.InvokeVoidAsync("updateMessageCaller",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
}
}
private void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
}
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code {
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper messageUpdateInvokeHelper;
protected override void OnInitialized()
{
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
}
protected async Task InteropCall()
{
await JS.InvokeVoidAsync("updateMessageCaller",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
}
private void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
}
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code {
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper messageUpdateInvokeHelper;
protected override void OnInitialized()
{
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
}
protected async Task InteropCall()
{
await JS.InvokeVoidAsync("updateMessageCaller",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
}
private void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
}
StateHasChanged a rendszer meghívja a felhasználói felület frissítésére, amikor message be van állítva a UpdateMessage. Ha a StateHasChanged nincs meghívva, Blazor nem tudja, hogy frissíteni kell a felhasználói felületet, amikor a Action meghívásra kerül.
A következő szülőösszetevő négy listaelemet tartalmaz, amelyek mindegyike az ListItem1 összetevő egy-egy példánya.
CallDotnet6.razor:
@page "/call-dotnet-6"
<PageTitle>Call .NET 6</PageTitle>
<h1>Call .NET Example 6</h1>
<ul>
<ListItem1 />
<ListItem1 />
<ListItem1 />
<ListItem1 />
</ul>
CallDotnet6.razor:
@page "/call-dotnet-6"
<PageTitle>Call .NET 6</PageTitle>
<h1>Call .NET Example 6</h1>
<ul>
<ListItem1 />
<ListItem1 />
<ListItem1 />
<ListItem1 />
</ul>
CallDotNetExample6.razor:
@page "/call-dotnet-example-6"
<h1>Call .NET Example 6</h1>
<ul>
<ListItem1 />
<ListItem1 />
<ListItem1 />
<ListItem1 />
</ul>
CallDotNetExample6.razor:
@page "/call-dotnet-example-6"
<h1>Call .NET Example 6</h1>
<ul>
<ListItem1 />
<ListItem1 />
<ListItem1 />
<ListItem1 />
</ul>
CallDotNetExample6.razor:
@page "/call-dotnet-example-6"
<h1>Call .NET Example 6</h1>
<ul>
<ListItem1 />
<ListItem1 />
<ListItem1 />
<ListItem1 />
</ul>
CallDotNetExample6.razor:
@page "/call-dotnet-example-6"
<h1>Call .NET Example 6</h1>
<ul>
<ListItem1 />
<ListItem1 />
<ListItem1 />
<ListItem1 />
</ul>
Az alábbi képen a renderelt szülőösszetevő látható a második InteropCall gomb kiválasztása után:
- A második
ListItem1összetevő megjeleníti azUpdateMessage Called!üzenetet. - A második
InteropCallösszetevőListItem1gombja nem látható, mert a gombdisplayCSS-tulajdonsága be van állítvanone.
Elemtulajdonsághoz rendelt összetevőpéldány .NET metódusa DotNetObjectReference
Egy HTML-elem tulajdonságához való hozzárendelés DotNetObjectReference lehetővé teszi a .NET-metódusok meghívását egy összetevőpéldányon:
- A rendszer rögzít egy elemhivatkozást (ElementReference).
- Az összetevő
OnAfterRender{Async}metódusában egy JavaScript (JS) függvény kerül meghívásra az elem hivatkozásával és az összetevő példányával, mint DotNetObjectReference. A JS függvény egy DotNetObjectReference tulajdonság eleméhez csatolja a függvényt. - Amikor egy elemeseményt hív meg JS (például
onclick), az elem csatolt DotNetObjectReference eleme egy .NET-metódus meghívására szolgál.
A Komponenspéldány .NET metódus segédosztályában ismertetett megközelítéshez hasonlóan ez a megközelítés olyan esetekben hasznos, amikor a statikus .NET-metódusok nem alkalmazhatók:
- Ha több azonos típusú összetevő jelenik meg ugyanazon a lapon.
- Kiszolgálóoldali alkalmazásokban, amelyek több felhasználóval egyidejűleg ugyanazt az összetevőt használják.
- A .NET metódus meghívása eseményből JS történik (például
onclick), nem eseményből Blazor (például@onclick).
Az alábbi példában:
- Az összetevő több
ListItem2összetevőt tartalmaz, amely egy megosztott összetevő. - Minden
ListItem2összetevő egy listaelem-üzenetből<span>és egy második<span>elemből áll, amelynél adisplayCSS-tulajdonságinline-blockmódon van beállítva a megjelenítés céljából. - Ha egy
ListItem2összetevőlistaelem van kijelölve, akkor aListItem2UpdateMessagemetódusa módosítja a listaelem szövegét az első<span>-ban, és elrejti a második<span>-t úgy, hogy beállítja annakdisplaytulajdonságát anoneértékre.
Az alábbi assignDotNetHelperJS függvény hozzárendeli a DotNetObjectReference-t egy dotNetHelper nevű tulajdonság egyik eleméhez. Az alábbi interopCallJS függvény a DotNetObjectReference az átadott elemhez használja, hogy meghívjon egy .NET metódust UpdateMessage névvel.
ListItem2.razor.js:
export function assignDotNetHelper(element, dotNetHelper) {
element.dotNetHelper = dotNetHelper;
}
export async function interopCall(element) {
await element.dotNetHelper.invokeMethodAsync('UpdateMessage');
}
ListItem2.razor.js:
export function assignDotNetHelper(element, dotNetHelper) {
element.dotNetHelper = dotNetHelper;
}
export async function interopCall(element) {
await element.dotNetHelper.invokeMethodAsync('UpdateMessage');
}
<script>
window.assignDotNetHelper = (element, dotNetHelper) => {
element.dotNetHelper = dotNetHelper;
}
window.interopCall = async (element) => {
await element.dotNetHelper.invokeMethodAsync('UpdateMessage');
}
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
Az előző példában a változó neve dotNetHelper tetszőleges, és bármely előnyben részesített névre módosítható.
A következő ListItem2 összetevő egy megosztott összetevő, amely tetszőleges számú alkalommal használható egy szülőösszetevőben, és listaelemeket (<li>...</li>) hoz létre egy HTML-lista (<ul>...</ul> vagy <ol>...</ol>).
Minden ListItem2 összetevőpéldány meghívja a assignDotNetHelper található JSOnAfterRenderAsync függvényt egy elemhivatkozással (a listaelem első <span> eleme), és összetevőpéldányként szerepel mint DotNetObjectReference.
Ha egy ListItem2 összetevő üzenete <span> ki van választva, interopCall hívódik meg, ami paraméterként megkapja az <span> elemet (this), és amely meghívja a UpdateMessage .NET metódust. A UpdateMessage belül meghívják a StateHasChanged-t a felhasználói felület frissítésére, amikor message be van állítva, és a második display<span> tulajdonsága frissül. Ha StateHasChanged nincs meghívva, Blazor nem tudja, hogy a felhasználói felületet frissíteni kell a metódus meghívásakor.
A DotNetObjectReference ártalmatlanná válik, amikor az összetevő ártalmatlanítva van.
ListItem2.razor:
@inject IJSRuntime JS
@implements IAsyncDisposable
<li>
<span style="font-weight:bold;color:@color" @ref="elementRef"
@onclick="CallJSToInvokeDotnet">
@message
</span>
<span style="display:@display">
Not Updated Yet!
</span>
</li>
@code {
private IJSObjectReference? module;
private DotNetObjectReference<ListItem2>? objRef;
private ElementReference elementRef;
private string display = "inline-block";
private string message = "Select one of these list items.";
private string color = "initial";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/ListItem2.razor.js");
objRef = DotNetObjectReference.Create(this);
await module.InvokeVoidAsync("assignDotNetHelper", elementRef, objRef);
}
}
public async Task CallJSToInvokeDotnet()
{
if (module is not null)
{
await module.InvokeVoidAsync("interopCall", elementRef);
}
}
[JSInvokable]
public void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
color = "MediumSeaGreen";
StateHasChanged();
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
objRef?.Dispose();
}
}
@inject IJSRuntime JS
@implements IAsyncDisposable
<li>
<span style="font-weight:bold;color:@color" @ref="elementRef"
@onclick="CallJSToInvokeDotnet">
@message
</span>
<span style="display:@display">
Not Updated Yet!
</span>
</li>
@code {
private IJSObjectReference? module;
private DotNetObjectReference<ListItem2>? objRef;
private ElementReference elementRef;
private string display = "inline-block";
private string message = "Select one of these list items.";
private string color = "initial";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/ListItem2.razor.js");
objRef = DotNetObjectReference.Create(this);
await module.InvokeVoidAsync("assignDotNetHelper", elementRef, objRef);
}
}
public async Task CallJSToInvokeDotnet()
{
if (module is not null)
{
await module.InvokeVoidAsync("interopCall", elementRef);
}
}
[JSInvokable]
public void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
color = "MediumSeaGreen";
StateHasChanged();
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
objRef?.Dispose();
}
}
@inject IJSRuntime JS
<li>
<span @ref="elementRef" onclick="interopCall(this)">@message</span>
<span style="display:@display">Not Updated Yet!</span>
</li>
@code {
private DotNetObjectReference<ListItem2>? objRef;
private ElementReference elementRef;
private string display = "inline-block";
private string message = "Select one of these list items.";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
objRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("assignDotNetHelper", elementRef, objRef);
}
}
[JSInvokable]
public void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
public void Dispose() => objRef?.Dispose();
}
@inject IJSRuntime JS
<li>
<span @ref="elementRef" onclick="interopCall(this)">@message</span>
<span style="display:@display">Not Updated Yet!</span>
</li>
@code {
private DotNetObjectReference<ListItem2>? objRef;
private ElementReference elementRef;
private string display = "inline-block";
private string message = "Select one of these list items.";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
objRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("assignDotNetHelper", elementRef, objRef);
}
}
[JSInvokable]
public void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
public void Dispose() => objRef?.Dispose();
}
@inject IJSRuntime JS
<li>
<span @ref="elementRef" onclick="interopCall(this)">@message</span>
<span style="display:@display">Not Updated Yet!</span>
</li>
@code {
private DotNetObjectReference<ListItem2> objRef;
private ElementReference elementRef;
private string display = "inline-block";
private string message = "Select one of these list items.";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
objRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("assignDotNetHelper", elementRef, objRef);
}
}
[JSInvokable]
public void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
public void Dispose() => objRef?.Dispose();
}
@inject IJSRuntime JS
<li>
<span @ref="elementRef" onclick="interopCall(this)">@message</span>
<span style="display:@display">Not Updated Yet!</span>
</li>
@code {
private DotNetObjectReference<ListItem2> objRef;
private ElementReference elementRef;
private string display = "inline-block";
private string message = "Select one of these list items.";
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
objRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("assignDotNetHelper", elementRef, objRef);
}
}
[JSInvokable]
public void UpdateMessage()
{
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
}
public void Dispose() => objRef?.Dispose();
}
A következő szülőösszetevő négy listaelemet tartalmaz, amelyek mindegyike az ListItem2 összetevő egy-egy példánya.
CallDotnet7.razor:
@page "/call-dotnet-7"
<PageTitle>Call .NET 7</PageTitle>
<h1>Call .NET Example 7</h1>
<ul>
<ListItem2 />
<ListItem2 />
<ListItem2 />
<ListItem2 />
</ul>
CallDotnet7.razor:
@page "/call-dotnet-7"
<PageTitle>Call .NET 7</PageTitle>
<h1>Call .NET Example 7</h1>
<ul>
<ListItem2 />
<ListItem2 />
<ListItem2 />
<ListItem2 />
</ul>
CallDotNetExample7.razor:
@page "/call-dotnet-example-7"
<h1>Call .NET Example 7</h1>
<ul>
<ListItem2 />
<ListItem2 />
<ListItem2 />
<ListItem2 />
</ul>
CallDotNetExample7.razor:
@page "/call-dotnet-example-7"
<h1>Call .NET Example 7</h1>
<ul>
<ListItem2 />
<ListItem2 />
<ListItem2 />
<ListItem2 />
</ul>
CallDotNetExample7.razor:
@page "/call-dotnet-example-7"
<h1>Call .NET Example 7</h1>
<ul>
<ListItem2 />
<ListItem2 />
<ListItem2 />
<ListItem2 />
</ul>
CallDotNetExample7.razor:
@page "/call-dotnet-example-7"
<h1>Call .NET Example 7</h1>
<ul>
<ListItem2 />
<ListItem2 />
<ListItem2 />
<ListItem2 />
</ul>
Szinkron JS interoperabilitás az ügyféloldali elemekben
Ez a szakasz csak az ügyféloldali összetevőkre vonatkozik.
A JS interop hívások aszinkron módon történnek, függetlenül attól, hogy a hívott kód szinkron vagy aszinkron. A hívások aszinkron módon biztosítják, hogy az összetevők kompatibilisek legyenek a kiszolgálóoldali és az ügyféloldali renderelési módok között. A kiszolgálón minden JS interop-hívásnak aszinkronnak kell lennie, mert hálózati kapcsolaton keresztül küldi őket.
Ha biztosan tudja, hogy az összetevő csak a WebAssemblyen fut, választhat, hogy szinkron JS interop-hívásokat kezdeményez. Ez valamivel kisebb többletterheléssel jár, mint az aszinkron hívások végrehajtása, és kevesebb renderelési ciklust eredményezhet, mivel nincs köztes állapot az eredményekre várva.
Ha egy ügyféloldali összetevőben a JavaScriptből a .NET-be szeretne szinkron hívást kezdeményezni, használja DotNet.invokeMethod a DotNet.invokeMethodAsynchelyett.
A szinkron hívások akkor működnek, ha:
JavaScript-hely
A JavaScript kód (JS) betöltése a JavaScript-elhelyezkedésről szóló cikkben ismertetett módszerek bármelyikével:
A JS modulok betöltéséről JS ebben a cikkben olvashat a JavaScript-elkülönítés JavaScript-modulokban című szakaszában .
Warning
Csak akkor helyezzen el <script> címkét egy összetevőfájlba (.razor), ha az összetevő garantáltan képes a statikus kiszolgálóoldali renderelésre (statikus SSR), mivel a <script> címke nem frissíthető dinamikusan.
Warning
Ne helyezzen <script> címkét egy összetevőfájlba (.razor), mert a <script> címke nem frissíthető dinamikusan.
JavaScript-elkülönítés JavaScript-modulokban
Blazor engedélyezi a JavaScript (JS) elkülönítését a standard JavaScript-modulokban (ECMAScript specifikáció). A JavaScript-modul betöltése ugyanúgy működik Blazor, mint más típusú webalkalmazások esetében, és szabadon testre szabhatja a modulok definiálását az alkalmazásban. A JavaScript-modulok használatáról további információt MDN Web Docs: JavaScript-modulokcímű témakörben talál.
JS elkülönítés a következő előnyöket biztosítja:
- Az importált JS már nem szennyezi a globális névteret.
- A könyvtárak és összetevők felhasználóinak nem szükséges importálniuk a kapcsolódó JS-t.
További információ: JavaScript-függvények meghívása a .NET-metódusokból ASP.NET Core Blazor.
A dinamikus importálást az import() operátorral az ASP.NET Core és a Blazortámogatja.
if ({CONDITION}) import("/additionalModule.js");
Az előző példában a {CONDITION} helyőrző egy feltételes ellenőrzést jelöl annak megállapításához, hogy be kell-e tölteni a modult.
A böngésző kompatibilitását lásd: Használhatom: JavaScript-modulok: dinamikus importálási.
Körkörös objektumhivatkozások elkerülése
A körkörös hivatkozásokat tartalmazó objektumok nem szerializálhatók az ügyfélen:
- .NET-metódushívások.
- JavaScript-metódushívások C#-ból, ha a visszatérési típus körkörös hivatkozásokat tartalmaz.
Bájttömb támogatása
Blazor támogatja az optimalizált bájttömb JavaScript (JS) interop használatát, amely megakadályozza a bájttömbök Base64-be való kódolását/dekódolását. Az alábbi példa az JS interopot használja arra, hogy egy bájttömböt adjon át a .NET-nek.
Adjon meg egy sendByteArrayJS függvényt. A függvényt statikusan hívjuk meg, amely tartalmazza a invokeMethodAsync hívás szerelvénynév paraméterét az összetevő egyik gombja alapján, és nem ad vissza értéket:
CallDotnet8.razor.js:
export function sendByteArray() {
const data = new Uint8Array([0x45, 0x76, 0x65, 0x72, 0x79, 0x74, 0x68, 0x69,
0x6e, 0x67, 0x27, 0x73, 0x20, 0x73, 0x68, 0x69, 0x6e, 0x79, 0x2c,
0x20, 0x43, 0x61, 0x70, 0x74, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x4e,
0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x72, 0x65, 0x74, 0x2e]);
DotNet.invokeMethodAsync('BlazorSample', 'ReceiveByteArray', data)
.then(str => {
alert(str);
});
}
export function addHandlers() {
const btn = document.getElementById("btn");
btn.addEventListener("click", sendByteArray);
}
<script>
window.sendByteArray = () => {
const data = new Uint8Array([0x45,0x76,0x65,0x72,0x79,0x74,0x68,0x69,
0x6e,0x67,0x27,0x73,0x20,0x73,0x68,0x69,0x6e,0x79,0x2c,
0x20,0x43,0x61,0x70,0x74,0x61,0x69,0x6e,0x2e,0x20,0x4e,
0x6f,0x74,0x20,0x74,0x6f,0x20,0x66,0x72,0x65,0x74,0x2e]);
DotNet.invokeMethodAsync('BlazorSample', 'ReceiveByteArray', data)
.then(str => {
alert(str);
});
};
</script>
Note
A JS helyére és az éles alkalmazásokkal kapcsolatos ajánlásainkra vonatkozó általános útmutatásért nézze meg a JavaScript-helyet az ASP.NET Core Blazor alkalmazásokban.
CallDotnet8.razor:
@page "/call-dotnet-8"
@using System.Text
@implements IAsyncDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 8</PageTitle>
<h1>Call .NET Example 8</h1>
<p>
<button id="btn">Send Bytes</button>
</p>
<p>
Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>:
<a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
<a href="https://www.imdb.com/name/nm0821612/">Jewel Staite on IMDB</a>
</p>
@code {
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/Pages/CallDotnet8.razor.js");
await module.InvokeVoidAsync("addHandlers");
}
}
[JSInvokable]
public static Task<string> ReceiveByteArray(byte[] receivedBytes) =>
Task.FromResult(Encoding.UTF8.GetString(receivedBytes, 0,
receivedBytes.Length));
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
}
}
CallDotnet8.razor:
@page "/call-dotnet-8"
@using System.Text
@implements IAsyncDisposable
@inject IJSRuntime JS
<PageTitle>Call .NET 8</PageTitle>
<h1>Call .NET Example 8</h1>
<p>
<button id="btn">Send Bytes</button>
</p>
<p>
Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>:
<a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
<a href="https://www.imdb.com/name/nm0821612/">Jewel Staite on IMDB</a>
</p>
@code {
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/Pages/CallDotnet8.razor.js");
await module.InvokeVoidAsync("addHandlers");
}
}
[JSInvokable]
public static Task<string> ReceiveByteArray(byte[] receivedBytes) =>
Task.FromResult(Encoding.UTF8.GetString(receivedBytes, 0,
receivedBytes.Length));
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
}
}
CallDotNetExample8.razor:
@page "/call-dotnet-example-8"
@using System.Text
<PageTitle>Call .NET 8</PageTitle>
<h1>Call .NET Example 8</h1>
<p>
<button onclick="sendByteArray()">Send Bytes</button>
</p>
<p>
Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>:
<a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
<a href="https://www.imdb.com/name/nm0821612/">Jewel Staite on IMDB</a>
</p>
@code {
[JSInvokable]
public static Task<string> ReceiveByteArray(byte[] receivedBytes)
{
return Task.FromResult(
Encoding.UTF8.GetString(receivedBytes, 0, receivedBytes.Length));
}
}
CallDotNetExample8.razor:
@page "/call-dotnet-example-8"
@using System.Text
<h1>Call .NET Example 8</h1>
<p>
<button onclick="sendByteArray()">Send Bytes</button>
</p>
<p>
Quote ©2005 <a href="https://www.uphe.com">Universal Pictures</a>:
<a href="https://www.uphe.com/movies/serenity-2005">Serenity</a><br>
<a href="https://www.imdb.com/name/nm0821612/">Jewel Staite on IMDB</a>
</p>
@code {
[JSInvokable]
public static Task<string> ReceiveByteArray(byte[] receivedBytes)
{
return Task.FromResult(
Encoding.UTF8.GetString(receivedBytes, 0, receivedBytes.Length));
}
}
Ha a JavaScript .NET-ből való meghívása során bájttömböt használ, olvassa el a JavaScript-függvények .NET-metódusokból való meghívását a ASP.NET Core-ban Blazor.
Streamelés JavaScriptből .NET-be
Blazor közvetlenül JavaScriptből .NET-be streameli az adatokat. Az streameket a Microsoft.JSInterop.IJSStreamReference interfész használatával kérik.
Microsoft.JSInterop.IJSStreamReference.OpenReadStreamAsync visszaad egy értéket Stream , és a következő paramétereket használja:
-
maxAllowedSize: A JavaScript olvasási műveletéhez engedélyezett bájtok maximális száma, amely alapértelmezés szerint 512 000 bájt, ha nincs megadva. -
cancellationToken: A CancellationToken az olvasás megszakításához.
JavaScriptben:
function streamToDotNet() {
return new Uint8Array(10000000);
}
C#-kódban:
var dataReference =
await JS.InvokeAsync<IJSStreamReference>("streamToDotNet");
using var dataReferenceStream =
await dataReference.OpenReadStreamAsync(maxAllowedSize: 10_000_000);
var outputPath = Path.Combine(Path.GetTempPath(), "file.txt");
using var outputFileStream = File.OpenWrite(outputPath);
await dataReferenceStream.CopyToAsync(outputFileStream);
Az előző példában:
-
JSegy injektált IJSRuntime példány. A IJSRuntime-t a Blazor keretrendszer regisztrálja. - A
dataReferenceStreamaz aktuális felhasználó ideiglenes mappaútvonalán lévő lemezre íródik (file.txt).
JavaScript-függvények meghívása .NET-metódusokból az ASP.NET Core-ban Blazor bemutatja a fordított műveletet: a .NET-ről a JavaScriptre való streamelést egy DotNetStreamReference.
ASP.NET Alapszintű Blazor fájlfeltöltések bemutatja, hogyan tölthet fel fájlokat a fájlba Blazor. A kiszolgálóoldali összetevőkben adatokat streamelő <textarea> űrlapok esetében lásd: ASP.NET Core-űrlapok Blazor hibaelhárítása.
JavaScript [JSImport]/[JSExport] interop
Ez a szakasz az ügyféloldali összetevőkre vonatkozik.
A JavaScript (JS) ügyféloldali összetevőkben való használatának alternatívájaként BlazorJSIJSRuntimeJS[JSImport]/[JSExport] interfészen alapuló interop api-ja érhető el a .NET 7 vagy újabb verziót célzó alkalmazások számára.
További információért lásd: JavaScript JSImport/JSExport interop ASP.NET Core-val Blazor.
JavaScript interop objektumhivatkozások megsemmisítése
A JavaScript (JS) interop cikkekben példák mutatnak be tipikus objektumelhelyezési mintákat:
Amikor a JS hívja meg a .NET-et, ahogy a jelen cikkben leírtuk, a létrehozott DotNetObjectReference-et semmisítse meg akár a .NET-ből, akár JS-ből, hogy elkerülje a .NET memória kiszivárgását.
Ha a .NET-ből hívja meg a(z) JS-t, ahogy a -ben leírtuk A JavaScript-függvények meghívása a .NET-metódusokból ASP.NET Core Blazor-ban, semmisítse meg a létrehozott IJSObjectReference/IJSInProcessObjectReference/
JSObjectReference-t akár a .NET-ből, akár a JS-ból, a JS memória kiszivárgásának elkerülése érdekében.
JS interop objektumhivatkozások a hivatkozást létrehozó JS interop hívás oldalán található azonosító által kulcsolt térképként vannak implementálva. Ha az objektumelhelyezést a .NET vagy JS oldalról kezdeményezik, Blazor eltávolítja a bejegyzést a térképről, és az objektum szemétként gyűjthető, feltéve, hogy nincs más erős hivatkozás az objektumra.
Legalább a .NET oldalon létrehozott objektumokat mindig megsemmisítse, hogy elkerülje a .NET által felügyelt memória kiszivárgását.
DOM-tisztítási feladatok az összetevők ártalmatlanítása során
További információ: ASP.NET Core Blazor JavaScript-együttműködés (JS interop).
JavaScript interop hívások áramkör nélkül
További információ: ASP.NET Core Blazor JavaScript-együttműködés (JS interop).
További erőforrások
- JavaScript-függvények meghívása .NET-metódusokból a ASP.NET Core Blazor
-
InteropComponent.razorpélda (dotnet/AspNetCoreGitHub-adattármainág): Amainág a termékegység aktuális fejlesztését jelöli a ASP.NET Core következő kiadásához. Ha egy másik kiadás ágát szeretné kiválasztani (példáulrelease/{VERSION}, ahol a{VERSION}helyőrző a kiadás verziója), használja az Ágak vagy címkék váltása legördülő listából az ág kiválasztásához. A már nem létező ág esetén a Címkék lapon keresse meg az API-t (példáulv7.0.0). - Interakció a DOM-tal
-
Blazor GitHub-adattár mintái (
dotnet/blazor-samples) (hogyan lehet letölteni) - ASP.NET Core Blazor-alkalmazások hibáinak kezelése (JavaScript interop szakasz)
- Fenyegetéscsökkentés: A böngészőből meghívott .NET-metódusok