Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Note
Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.
Warning
Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.
Important
Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.
Zie de .NET 9-versie van dit artikel voor de huidige release.
In dit artikel wordt uitgelegd hoe u .NET-methoden aanroept vanuit JavaScript (JS).
Zie Blazorvoor meer informatie over het aanroepen van functies vanuit .NET.
Een statische .NET-methode aanroepen
Als u een statische .NET-methode wilt aanroepen vanuit JavaScript (JS), gebruikt u de JS volgende functies:
-
DotNet.invokeMethodAsync
(aanbevolen): Asynchroon voor zowel server- als clientonderdelen. -
DotNet.invokeMethod
: Alleen synchroon voor onderdelen aan de clientzijde.
Geef de naam van de assembly door die de methode bevat, de id van de statische .NET-methode en eventuele argumenten.
In het volgende voorbeeld:
- De
{PACKAGE ID/ASSEMBLY NAME}
placeholder is de pakket-id van het project (<PackageId>
in het projectbestand) voor een library- of assemblynaam voor een app. - De
{.NET METHOD ID}
tijdelijke aanduiding is de .NET-methode-id. - De
{ARGUMENTS}
tijdelijke aanduidingen zijn optionele, door komma's gescheiden argumenten om door te geven aan de methode, die elk JSON-serializeerbaar moeten zijn.
DotNet.invokeMethodAsync('{PACKAGE ID/ASSEMBLY NAME}', '{.NET METHOD ID}', {ARGUMENTS});
DotNet.invokeMethodAsync
retourneert een JS Promise
weergave van het resultaat van de bewerking.
DotNet.invokeMethod
(onderdelen aan de clientzijde) retourneert het resultaat van de bewerking.
Important
Voor onderdelen aan de serverzijde raden we de asynchrone functie (invokeMethodAsync
) aan via de synchrone versie (invokeMethod
).
De .NET-methode moet openbaar, statisch zijn en het [JSInvokable]
kenmerk hebben.
In het volgende voorbeeld:
- De
{<T>}
tijdelijke aanduiding geeft het retourtype aan. Dit is alleen vereist voor methoden die een waarde retourneren. - De
{.NET METHOD ID}
tijdelijke aanduiding is de methode-id.
@code {
[JSInvokable]
public static Task{<T>} {.NET METHOD ID}()
{
...
}
}
Note
Het aanroepen van open algemene methoden wordt niet ondersteund met statische .NET-methoden, maar wordt ondersteund met exemplaarmethoden. Voor meer informatie, zie de sectie Aanroepen van generieke methoden van .NET-klassen.
In het volgende onderdeel retourneert de ReturnArrayAsync
C#-methode een int
matrix. Het [JSInvokable]
kenmerk wordt toegepast op de methode, waardoor de methode kan worden aangeroepen door JS.
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);
}
De addHandlers
JS functie voegt een click
gebeurtenis toe aan de knop. De returnArrayAsync
JS functie wordt toegewezen als handler.
De returnArrayAsync
JS functie roept de ReturnArrayAsync
.NET-methode van het onderdeel aan, waarmee het resultaat wordt opgeslagen in de console voor webontwikkelaars van de browser.
BlazorSample
is de assemblynaam van de app.
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);
}
De addHandlers
JS functie voegt een click
gebeurtenis toe aan de knop. De returnArrayAsync
JS functie wordt toegewezen als handler.
De returnArrayAsync
JS functie roept de ReturnArrayAsync
.NET-methode van het onderdeel aan, waarmee het resultaat wordt opgeslagen in de console voor webontwikkelaars van de browser.
BlazorSample
is de assemblynaam van de app.
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 });
}
}
Het HTML-attribuut van het <button>
-element is de JavaScript onclick
gebeurtenis-handler toewijzing voor het verwerken van onclick
-gebeurtenissen, niet het aanwijzingsattribuut van click
Blazor. De returnArrayAsync
JS functie wordt toegewezen als handler.
Met de volgende returnArrayAsync
JS functie wordt de ReturnArrayAsync
.NET-methode van het onderdeel aangeroepen, waarmee het resultaat wordt opgeslagen in de console voor webontwikkelaars van de browser.
BlazorSample
is de assemblynaam van de app.
<script>
window.returnArrayAsync = () => {
DotNet.invokeMethodAsync('BlazorSample', 'ReturnArrayAsync')
.then(data => {
console.log(data);
});
};
</script>
Note
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
Wanneer de Trigger .NET static method
knop is geselecteerd, worden de matrixgegevens weergegeven in de console voor ontwikkelaarshulpprogramma's van de browser. De indeling van de uitvoer verschilt enigszins tussen browsers. In de volgende uitvoer ziet u de indeling die wordt gebruikt door Microsoft Edge:
Array(3) [ 11, 12, 13 ]
Geef gegevens door aan een .NET-methode wanneer u de invokeMethodAsync
functie aanroept door de gegevens als argumenten door te geven.
Als u wilt demonstreren dat gegevens worden doorgegeven aan .NET, geeft u een beginpositie door aan de ReturnArrayAsync
methode waarin de methode wordt aangeroepen in JS:
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>
De aanroepbare ReturnArrayAsync
methode van het onderdeel ontvangt de beginpositie en bouwt de matrix ermee. De matrix wordt geretourneerd voor logboekregistratie naar de console:
[JSInvokable]
public static Task<int[]> ReturnArrayAsync(int startPosition) =>
Task.FromResult(Enumerable.Range(startPosition, 3).ToArray());
Nadat de app opnieuw is gecompileerd en de browser is vernieuwd, wordt de volgende uitvoer weergegeven in de console van de browser wanneer de knop is geselecteerd:
Array(3) [ 14, 15, 16 ]
De .NET-methode-id voor de aanroep is de naam van de JS .NET-methode, maar u kunt een andere id opgeven met behulp van de [JSInvokable]
kenmerkconstructor . In het volgende voorbeeld DifferentMethodName
is de toegewezen methode-id voor de ReturnArrayAsync
methode:
[JSInvokable("DifferentMethodName")]
In de aanroep naar DotNet.invokeMethodAsync
(server- of clientonderdelen) of DotNet.invokeMethod
(alleen clientonderdelen), roept u DifferentMethodName
aan om de ReturnArrayAsync
.NET-methode uit te voeren:
DotNet.invokeMethodAsync('BlazorSample', 'DifferentMethodName');
-
DotNet.invokeMethod('BlazorSample', 'DifferentMethodName');
(alleen onderdelen aan clientzijde)
Note
Het ReturnArrayAsync
voorbeeld van de methode in deze sectie retourneert het resultaat van een Task zonder expliciete C# async
en await
trefwoorden. Coderingsmethoden met async
en await
zijn typische methoden die het await
trefwoord gebruiken om de waarde van asynchrone bewerkingen te retourneren.
ReturnArrayAsync
methode samengesteld met async
en await
trefwoorden:
[JSInvokable]
public static async Task<int[]> ReturnArrayAsync() =>
await Task.FromResult(new int[] { 11, 12, 13 });
Zie Asynchrone programmering met asynchroon programmeren en wachten in de C#-handleiding voor meer informatie.
JavaScript-object- en gegevensverwijzingen maken om door te geven aan .NET
Aanroep DotNet.createJSObjectReference(jsObject)
om een JS objectverwijzing te maken, zodat deze kan worden doorgegeven aan .NET, waar jsObject
wordt gebruikt JS Object
om de JS objectverwijzing te maken. In het volgende voorbeeld wordt een verwijzing naar het niet-serialiseerbare window
object doorgegeven aan .NET, dat deze in de ReceiveWindowObject
C#-methode ontvangt als een IJSObjectReference.
DotNet.invokeMethodAsync('{PACKAGE ID/ASSEMBLY NAME}', 'ReceiveWindowObject',
DotNet.createJSObjectReference(window));
[JSInvokable]
public static void ReceiveWindowObject(IJSObjectReference objRef)
{
...
}
In het voorgaande voorbeeld is de {PACKAGE ID/ASSEMBLY NAME}
tijdelijke aanduiding de pakket-id van het project (<PackageId>
in het projectbestand) voor een bibliotheek- of assemblynaam voor een app.
Note
Het voorgaande voorbeeld vereist geen verwijdering van de JSObjectReference
, aangezien er geen verwijzing naar het window
object wordt bewaard in JS.
Het onderhouden van een verwijzing naar een JSObjectReference
verwijzing vereist het verwijderen ervan om te voorkomen dat geheugen op de client wordt gelekt JS . In het volgende voorbeeld wordt de voorgaande code hersteld om een verwijzing naar de JSObjectReference
vast te leggen, gevolgd door het aanroepen van DotNet.disposeJSObjectReference()
om de verwijzing te verwijderen.
var jsObjectReference = DotNet.createJSObjectReference(window);
DotNet.invokeMethodAsync('{PACKAGE ID/ASSEMBLY NAME}', 'ReceiveWindowObject', jsObjectReference);
DotNet.disposeJSObjectReference(jsObjectReference);
In het voorgaande voorbeeld is de {PACKAGE ID/ASSEMBLY NAME}
tijdelijke aanduiding de pakket-id van het project (<PackageId>
in het projectbestand) voor een bibliotheek- of assemblynaam voor een app.
Aanroep DotNet.createJSStreamReference(streamReference)
om een JS stroomreferentie te maken, zodat deze kan worden doorgegeven aan .NET, waarbij streamReference
een ArrayBuffer
, Blob
of een getypte matrix, zoals Uint8Array
of Float32Array
, wordt gebruikt om de JS stroomreferentie te maken.
Een .NET-instantiemethode aanroepen
Een .NET-instantiemethode aanroepen vanuit JavaScript (JS):
Geef het .NET-exemplaar door als referentie aan JS door het exemplaar in een DotNetObjectReference te verpakken en Create erop aan te roepen.
Roep een .NET-exemplaarmethode aan van JS met
invokeMethodAsync
(aanbevolen) ofinvokeMethod
(alleen client-side componenten) van de doorgegeven DotNetObjectReference. Geef de id van de .NET-instantiemethode en eventuele argumenten door. Het .NET-exemplaar kan ook worden doorgegeven als argument bij het aanroepen van andere .NET-methoden vanuit JS.In het volgende voorbeeld:
-
dotNetHelper
is een DotNetObjectReference. - De
{.NET METHOD ID}
tijdelijke aanduiding is de .NET-methode-id. - De
{ARGUMENTS}
tijdelijke aanduidingen zijn optionele, door komma's gescheiden argumenten om door te geven aan de methode, die elk JSON-serializeerbaar moeten zijn.
dotNetHelper.invokeMethodAsync('{.NET METHOD ID}', {ARGUMENTS});
Note
invokeMethodAsync
eninvokeMethod
accepteer geen assemblynaamparameter bij het aanroepen van een exemplaarmethode.invokeMethodAsync
retourneert een JSPromise
weergave van het resultaat van de bewerking.invokeMethod
(alleen onderdelen aan de clientzijde) retourneert het resultaat van de bewerking.Important
Voor onderdelen aan de serverzijde raden we de asynchrone functie (
invokeMethodAsync
) aan via de synchrone versie (invokeMethod
).-
Verwijder de DotNetObjectReference.
De volgende secties van dit artikel laten verschillende benaderingen zien voor het aanroepen van een .NET-instantiemethode:
Vermijd het inkorten van .NET-methoden die door JavaScript kunnen worden opgeroepen.
Deze sectie is van toepassing op apps aan de clientzijde waarvoor vooraf compilatie (AOT) en runtime-relinking is ingeschakeld.
Verschillende voorbeelden in de volgende secties zijn gebaseerd op een benadering van een klasse-exemplaar, waarbij de JavaScript-invokable .NET-methode die is gemarkeerd met het [JSInvokable]
kenmerk lid is van een klasse die geen Razor onderdeel is. Wanneer dergelijke .NET-methoden zich in een Razor onderdeel bevinden, worden ze beschermd tegen het opnieuw koppelen/bijsnijden van runtime. Als u de .NET-methoden wilt beveiligen tegen bijsnijden buiten Razor onderdelen, implementeert u de methoden met het DynamicDependency
kenmerk op de constructor van de klasse, zoals in het volgende voorbeeld wordt gedemonstreerd:
using System.Diagnostics.CodeAnalysis;
using Microsoft.JSInterop;
public class ExampleClass {
[DynamicDependency(nameof(ExampleJSInvokableMethod))]
public ExampleClass()
{
}
[JSInvokable]
public string ExampleJSInvokableMethod()
{
...
}
}
Zie .NET-bibliotheken voorbereiden voor bijsnijden: DynamicDependency voor meer informatie.
Geef een DotNetObjectReference
door aan een afzonderlijke JavaScript-functie
In het voorbeeld in deze sectie ziet u hoe u een DotNetObjectReference afzonderlijke JavaScript-functie (JS) doorgeeft.
De volgende sayHello1
JS functie ontvangt een DotNetObjectReference en roept aan invokeMethodAsync
om de GetHelloMessage
.NET-methode van een onderdeel aan te roepen:
<script>
window.sayHello1 = (dotNetHelper) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage');
};
</script>
Note
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
Voor het volgende onderdeel:
- Het onderdeel heeft een .NET-methode genaamd JS, die
GetHelloMessage
-invokable is. - Wanneer de
Trigger .NET instance method
knop is geselecteerd, wordt de JS functiesayHello1
aangeroepen met de DotNetObjectReference. -
sayHello1
:- Roept
GetHelloMessage
aan en ontvangt het berichtresultaat. - Retourneert het berichtresultaat naar de aanroepmethode
TriggerDotNetInstanceMethod
.
- Roept
- Het geretourneerde bericht van
sayHello1
inresult
wordt weergegeven aan de gebruiker. - Om een geheugenlek te voorkomen en garbagecollection toe te staan, wordt de door DotNetObjectReference gemaakte .NET-objectverwijzing vrijgegeven in de
Dispose
-methode.
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();
}
}
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
Gebruik de volgende richtlijnen om argumenten door te geven aan een exemplaarmethode:
Voeg parameters toe aan de aanroep van de .NET-methode. In het volgende voorbeeld wordt een naam doorgegeven aan de methode. Voeg indien nodig extra parameters toe aan de lijst.
<script>
window.sayHello2 = (dotNetHelper, name) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage', name);
};
</script>
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
Geef de lijst met parameters op voor de .NET-methode.
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();
}
}
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
Een DotNetObjectReference
aan een klasse doorgeven met meerdere JavaScript-functies
In het voorbeeld in deze sectie ziet u hoe u een DotNetObjectReference JavaScript-klasse (JS) met meerdere functies doorgeeft.
Maak en geef een DotNetObjectReference van de OnAfterRenderAsync
levenscyclusmethode door aan een JS klasse die meerdere functies kan gebruiken. Zorg ervoor dat de .NET-code de DotNetObjectReference vrijgeeft, zoals in het volgende voorbeeld wordt getoond.
In het volgende onderdeel roepen de Trigger JS function
knoppen JS functies aan door de JSonclick
eigenschap in te stellen, en niet het Blazor@onclick
instructiekenmerk.
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();
}
}
In het voorgaande voorbeeld:
-
JS
is een geïnjecteerd IJSRuntime exemplaar. IJSRuntime wordt geregistreerd door het Blazor framework. - De naam
dotNetHelper
van de variabele is willekeurig en kan worden gewijzigd in elke voorkeursnaam. - Het onderdeel moet DotNetObjectReference expliciet verwijderen om de vuilnisverzameling toe te staan en een geheugenlek te voorkomen.
-
JSDisconnectedException komt vast te zitten bij het verwijderen van de module wanneer het BlazorSignalR circuit verloren gaat. Als de voorgaande code wordt gebruikt in een Blazor WebAssembly-app, is er geen SignalR verbinding verloren gegaan, zodat u het
try
-catch
blok kunt verwijderen en de regel kunt verlaten waarmee de module (await module.DisposeAsync();
) wordt verwijderd. Zie ASP.NET Core Blazor JavaScript-interoperabiliteit (JS interop)voor meer informatie.
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);
}
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
@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();
}
}
In het voorgaande voorbeeld:
-
JS
is een geïnjecteerd IJSRuntime exemplaar. IJSRuntime wordt geregistreerd door het Blazor framework. - De naam
dotNetHelper
van de variabele is willekeurig en kan worden gewijzigd in elke voorkeursnaam. - Het onderdeel moet DotNetObjectReference expliciet verwijderen om de vuilnisverzameling toe te staan en een geheugenlek te voorkomen.
<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>
In het voorgaande voorbeeld:
- De
GreetingHelpers
klasse wordt toegevoegd aan hetwindow
object om de klasse globaal te definiëren, zodat Blazor de klasse kan lokaliseren voor JS-interop. - De naam
dotNetHelper
van de variabele is willekeurig en kan worden gewijzigd in elke voorkeursnaam.
Note
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
Algemene .NET-klassemethoden aanroepen
JavaScript-functies (JS) kunnen .NET-algemene klassemethoden aanroepen, waarbij een JS functie een .NET-methode van een algemene klasse aanroept.
In de volgende algemene typeklasse (GenericType<TValue>
):
- De klasse heeft één typeparameter (
TValue
) met één algemeneValue
eigenschap. - De klasse heeft twee niet-algemene methoden die zijn gemarkeerd met het
[JSInvokable]
kenmerk, elk met een algemene typeparameter met de naamnewValue
:-
Update
werkt de waarde vanValue
synchroon bij vanuitnewValue
. -
UpdateAsync
werkt asynchroon de waarde vanValue
bij vannewValue
na het creëren van een awaitable taak met Task.Yield, die asynchroon terugkeert naar de huidige context wanneer deze wordt afgewacht.
-
- Elk van de klassemethoden schrijft het type
TValue
en de waarde vanValue
naar de console. Schrijven naar de console is alleen voor demonstratiedoeleinden. Productie-apps vermijden meestal naar de console schrijven ten gunste van app-logboeken. Zie ASP.NET Core-logboekregistratie Blazor en -logboekregistratie in .NET en ASP.NET Core voor meer informatie.
Note
Open generieke types en methoden geven geen typen op voor typeplaatsaanduiders. Omgekeerd leveren gesloten generieken typen voor alle type tijdelijke aanduidingen. In de voorbeelden in deze sectie worden gesloten generics gedemonstreert, maar het aanroepen van JSinteroperabiliteitsexemplaren met open generics wordt ondersteund. Het gebruik van open generics wordt niet ondersteund voor aanroepen van statische .NET-methoden, die eerder in dit artikel zijn beschreven.
Zie de volgende artikelen voor meer informatie:
- Algemene klassen en methoden (C#-documentatie)
- Algemene klassen (C#-programmeerhandleiding)
- Generics in .NET (.NET-documentatie)
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}");
}
}
In de volgende invokeMethodsAsync
functie:
- De algemene typeklasse
Update
enUpdateAsync
methoden worden aangeroepen met argumenten die tekenreeksen en getallen vertegenwoordigen. - Onderdelen aan de clientzijde ondersteunen het aanroepen van .NET-methoden synchroon met
invokeMethod
.syncInterop
ontvangt een Booleaanse waarde die aangeeft of de JS interoperabiliteit plaatsvindt op de client. WanneersyncInterop
true
is, kaninvokeMethod
veilig worden aangeroepen. Als de waarde vansyncInterop
false
is, wordt alleen de asynchrone functieinvokeMethodAsync
aangeroepen omdat de interoperabiliteit wordt uitgevoerd in een server-side component JS. - Voor demonstratiedoeleinden wordt de DotNetObjectReference functie-aanroep (
invokeMethod
ofinvokeMethodAsync
), de .NET-methode aangeroepen (Update
ofUpdateAsync
) en het argument naar de console geschreven. De argumenten gebruiken een willekeurig getal om het koppelen van de JS functieaanroep aan de aanroep van de .NET-methode toe te staan (ook naar de console aan de .NET-zijde geschreven). Productiecode schrijft meestal niet naar de console, op de client of op de server. Productie-apps zijn meestal afhankelijk van app-logboekregistratie. Zie ASP.NET Core-logboekregistratie Blazor en -logboekregistratie in .NET en ASP.NET Core voor meer informatie.
<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
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
In de volgende GenericsExample
component:
- De JS functie
invokeMethodsAsync
wordt aangeroepen wanneer deInvoke Interop
knop is geselecteerd. - Er worden twee DotNetObjectReference typen gemaakt en doorgegeven aan de JS functie voor instanties van de
GenericType
als eenstring
en eenint
.
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();
}
}
In het voorgaande voorbeeld JS
is een geïnjecteerd IJSRuntime exemplaar.
IJSRuntime wordt geregistreerd door het Blazor framework.
Hieronder ziet u de typische uitvoer van het voorgaande voorbeeld wanneer de Invoke Interop
knop is geselecteerd in een onderdeel aan de clientzijde:
JS: invokeMethodAsync:Update('string 37802')
.NET: Update: GenericType<System.String>: tekenreeks 37802
JS: invokeMethodAsync:UpdateAsync('string 53051')
JS: invokeMethod:Update('string 26784')
.NET: Update: GenericType<System.String>: tekenreeks 26784
JS: invokeMethodAsync:Update(14107)
.NET: Bijwerken: GenericType<System.Int32>: 14107
JS: invokeMethodAsync:UpdateAsync(48995)
JS: invokeMethod:Update(12872)
.NET: Update: GenericType<System.Int32>: 12872
.NET: UpdateAsync: GenericType<System.String>: tekenreeks 53051
.NET: UpdateAsync: GenericType<System.Int32>: 48995
Als het voorgaande voorbeeld wordt geïmplementeerd in een server-side onderdeel, worden de synchrone aanroepen met invokeMethod
vermeden. Voor onderdelen aan de serverzijde raden we de asynchrone functie (invokeMethodAsync
) aan via de synchrone versie (invokeMethod
).
Typische uitvoer van een onderdeel aan de serverzijde:
JS: invokeMethodAsync:Update('string 34809')
.NET: Update: GenericType<System.String>: tekenreeks 34809
JS: invokeMethodAsync:UpdateAsync('string 93059')
JS: invokeMethodAsync:Update(41997)
.NET: Bijwerken: GenericType<System.Int32>: 41997
JS: invokeMethodAsync:UpdateAsync(24652)
.NET: UpdateAsync: GenericType<System.String>: tekenreeks 93059
.NET: UpdateAsync: GenericType<System.Int32>: 24652
In de voorgaande uitvoervoorbeelden ziet u dat asynchrone methoden in een willekeurige volgorde worden uitgevoerd en voltooid, afhankelijk van verschillende factoren, waaronder threadplanning en de snelheid van de uitvoering van de methode. Het is niet mogelijk om de volgorde van voltooiing voor asynchrone methodeaanroepen betrouwbaar te voorspellen.
Voorbeelden van klasse-instanties
De volgende sayHello1
JS functie:
- Roept de
GetHelloMessage
.NET-methode aan op de doorgegeven DotNetObjectReference. - Retourneert het bericht van
GetHelloMessage
naar desayHello1
aanroeper.
<script>
window.sayHello1 = (dotNetHelper) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage');
};
</script>
Note
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
De volgende HelloHelper
klasse heeft een aanroepbare .NET-methode met de naam JS. Wanneer HelloHelper
wordt gemaakt, wordt de naam in de Name
eigenschap gebruikt om een bericht terug te geven van GetHelloMessage
.
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}!";
}
De CallHelloHelperGetHelloMessage
methode in de volgende JsInteropClasses3
klasse roept de JS functie sayHello1
aan met een nieuw exemplaar van HelloHelper
.
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);
}
}
Om een geheugenlek te voorkomen en garbagecollection toe te staan, wordt de .NET-objectverwijzing die is gemaakt door DotNetObjectReference verwijderd wanneer de objectverwijzing uit scope raakt via de using var
-syntaxis.
Wanneer de Trigger .NET instance method
knop is geselecteerd in het volgende onderdeel, JsInteropClasses3.CallHelloHelperGetHelloMessage
wordt aangeroepen met de waarde van 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);
}
}
}
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);
}
}
In de volgende afbeelding ziet u het weergegeven onderdeel met de naam Amy Pond
in het Name
veld. Nadat de knop is geselecteerd, Hello, Amy Pond!
wordt deze weergegeven in de gebruikersinterface:
Het voorgaande patroon dat in de JsInteropClasses3
klasse wordt weergegeven, kan ook volledig in een onderdeel worden geïmplementeerd.
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);
}
}
Om een geheugenlek te voorkomen en garbagecollection toe te staan, wordt de .NET-objectverwijzing die is gemaakt door DotNetObjectReference verwijderd wanneer de objectverwijzing uit scope raakt via de using var
-syntaxis.
De uitvoer die door het onderdeel wordt weergegeven, is Hello, Amy Pond!
wanneer de naam Amy Pond
wordt opgegeven in het name
veld.
In het voorgaande onderdeel wordt de .NET-objectverwijzing verwijderd. Als een klasse of component de DotNetObjectReference niet verwijdert, verwijder het dan van de client door de methode dispose
aan te roepen op het doorgegeven DotNetObjectReference:
window.{JS FUNCTION NAME} = (dotNetHelper) => {
dotNetHelper.invokeMethodAsync('{.NET METHOD ID}');
dotNetHelper.dispose();
}
In het voorgaande voorbeeld:
- De
{JS FUNCTION NAME}
tijdelijke aanduiding is de naam van de JS functie. - De naam
dotNetHelper
van de variabele is willekeurig en kan worden gewijzigd in elke voorkeursnaam. - De
{.NET METHOD ID}
tijdelijke aanduiding is de .NET-methode-id.
Helperklasse voor .NET-methoden voor componentinstanties
Een helperklasse kan een .NET-exemplaarmethode aanroepen als een Action. Helperklassen zijn handig in scenario's waarin het gebruik van statische .NET-methoden niet van toepassing is:
- Wanneer verschillende onderdelen van hetzelfde type worden weergegeven op dezelfde pagina.
- In serverside applicaties waarin meerdere gebruikers gelijktijdig hetzelfde onderdeel gebruiken.
In het volgende voorbeeld:
- Het onderdeel bevat verschillende
ListItem1
onderdelen. - Elk
ListItem1
onderdeel bestaat uit een bericht en een knop. - Wanneer een
ListItem1
componentknop is geselecteerd, wijzigt deListItem1
-methode van deUpdateMessage
de tekst van het lijstitem en wordt de knop verborgen.
De volgende MessageUpdateInvokeHelper
klasse onderhoudt een JS.NET-methode UpdateMessageCaller
die kan worden aangeroepen om de Action opgegeven methode aan te roepen wanneer de klasse wordt geïnstantieerd.
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();
}
}
Met de volgende updateMessageCaller
JS functie wordt de UpdateMessageCaller
.NET-methode aangeroepen.
<script>
window.updateMessageCaller = (dotNetHelper) => {
dotNetHelper.invokeMethodAsync('UpdateMessageCaller');
dotNetHelper.dispose();
}
</script>
Note
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
Het volgende ListItem1
-onderdeel is een gedeeld onderdeel dat elk gewenst aantal keren in een oudercomponent kan worden gebruikt en lijstitems (<li>...</li>
) voor een HTML-lijst (<ul>...</ul>
of <ol>...</ol>
) kan maken. Met elke ListItem1
componentinstantie maakt een exemplaar van MessageUpdateInvokeHelper
, waarbij Action is ingesteld op de UpdateMessage
methode.
Wanneer de knop van een ListItem1
onderdeel is geselecteerd, InteropCall
wordt aangeroepen met een gemaakt updateMessageCaller
voor het DotNetObjectReferenceMessageUpdateInvokeHelper
exemplaar. Hierdoor kan het framework UpdateMessageCaller
aanroepen op de ListItem1
-instantie van die MessageUpdateInvokeHelper
. Het doorgegeven DotNetObjectReference wordt afgehandeld in JS (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
wordt aangeroepen om de gebruikersinterface bij te werken wanneer message
is ingesteld in UpdateMessage
. Als StateHasChanged
niet wordt aangeroepen, heeft Blazor geen manier om te weten dat de gebruikersinterface moet worden bijgewerkt wanneer de Action wordt aangeroepen.
Het volgende bovenliggende onderdeel bevat vier lijstitems, elk een exemplaar van het ListItem1
onderdeel.
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>
In de volgende afbeelding ziet u het weergegeven oudercomponent nadat de tweede InteropCall
knop is geselecteerd.
- Het tweede
ListItem1
onderdeel heeft hetUpdateMessage Called!
bericht weergegeven. - De
InteropCall
knop voor het tweedeListItem1
onderdeel is niet zichtbaar omdat de CSS-eigenschapdisplay
van de knop is ingesteld opnone
.
.NET-methode van componentinstantie aangeroepen vanuit DotNetObjectReference
en toegewezen aan een elementeigenschap
De toewijzing van een DotNetObjectReference aan een eigenschap van een HTML-element maakt het mogelijk om .NET-methoden op een onderdeelexemplaar aan te roepen.
- Er wordt een elementreferentie vastgelegd (ElementReference).
- In de
OnAfterRender{Async}
-methode van het onderdeel wordt een JavaScript-functie (JS) aangeroepen met de elementverwijzing en het onderdeelexemplaar als een DotNetObjectReference. De JS functie koppelt het DotNetObjectReference aan het element in een eigenschap. - Wanneer een elementgebeurtenis wordt aangeroepen in JS (bijvoorbeeld
onclick
), wordt het gekoppelde DotNetObjectReference element gebruikt om een .NET-methode aan te roepen.
Deze benadering is vergelijkbaar met de benadering beschreven in het gedeelte Component Instance .NET-methode helperklasse. Deze benadering is nuttig in scenario's waarin het gebruik van statische .NET-methoden niet toepasbaar is:
- Wanneer verschillende onderdelen van hetzelfde type worden weergegeven op dezelfde pagina.
- In serverside applicaties waarin meerdere gebruikers gelijktijdig hetzelfde onderdeel gebruiken.
- De .NET-methode wordt aangeroepen vanuit een JS gebeurtenis (bijvoorbeeld
onclick
), niet van een Blazor gebeurtenis (bijvoorbeeld@onclick
).
In het volgende voorbeeld:
- Het onderdeel bevat verschillende
ListItem2
onderdelen, een gedeeld onderdeel. - Elk
ListItem2
component bestaat uit een lijstitembericht<span>
en een tweede<span>
waarop eendisplay
CSS-eigenschap is ingesteldinline-block
voor weergave. - Wanneer een
ListItem2
lijstitem is geselecteerd, verandert deListItem2
-methode vanUpdateMessage
de tekst van het lijstitem in de eerste<span>
en verbergt de tweede<span>
door de eigenschap van de tweede<span>
in te stellen opnone
.
De volgende assignDotNetHelper
JS functie wijst de DotNetObjectReference toe aan een element in een eigenschap genaamd dotNetHelper
. De volgende interopCall
JS functie gebruikt het DotNetObjectReference voor het doorgegeven element om een .NET-methode aan te roepen met de naam UpdateMessage
.
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
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
In het voorgaande voorbeeld is de naam dotNetHelper
van de variabele willekeurig en kan deze worden gewijzigd in elke voorkeursnaam.
Het volgende ListItem2
-onderdeel is een gedeeld onderdeel dat elk gewenst aantal keren in een oudercomponent kan worden gebruikt en lijstitems (<li>...</li>
) voor een HTML-lijst (<ul>...</ul>
of <ol>...</ol>
) kan maken.
Elke ListItem2
onderdeelexemplaar roept de assignDotNetHelper
JS functie aan in OnAfterRenderAsync
met een referentie naar een element (het eerste <span>
element van het lijstitem) en het onderdeelexemplaar als een DotNetObjectReference.
Wanneer een bericht van een ListItem2
component is geselecteerd, wordt <span>
aangeroepen met het interopCall
element als parameter (<span>
), waarmee de this
.NET-methode wordt aangeroepen.UpdateMessage
In UpdateMessage
wordt StateHasChanged
aangeroepen om de gebruikersinterface bij te werken wanneer message
deze is ingesteld en de display
eigenschap van de tweede <span>
wordt bijgewerkt. Als StateHasChanged
niet wordt aangeroepen, heeft Blazor geen manier om te weten dat de gebruikersinterface moet worden bijgewerkt wanneer de methode wordt aangeroepen.
Het DotNetObjectReference wordt weggegooid wanneer het onderdeel wordt verwijderd.
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();
}
Het volgende bovenliggende onderdeel bevat vier lijstitems, elk een exemplaar van het ListItem2
onderdeel.
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>
Synchrone JS interoperabiliteit in clientonderdelen
Deze sectie is alleen van toepassing op onderdelen aan de clientzijde.
JS interop-aanroepen zijn altijd asynchroon, ongeacht of de aangeroepen code synchroon of asynchroon is. Aanroepen zijn asynchroon om ervoor te zorgen dat onderdelen compatibel zijn met de rendermodi aan de serverzijde en clientzijde. Op de server moeten alle JS interop-aanroepen asynchroon zijn omdat ze via een netwerkverbinding worden verzonden.
Als u zeker weet dat uw onderdeel alleen wordt uitgevoerd op WebAssembly, kunt u ervoor kiezen om synchrone JS interop-aanroepen uit te voeren. Dit heeft iets minder overhead dan het maken van asynchrone aanroepen en kan leiden tot minder rendercycli, omdat er geen tussenliggende status is tijdens het wachten op resultaten.
Gebruik DotNet.invokeMethod
in plaats van DotNet.invokeMethodAsync
om een synchrone aanroep van JavaScript naar .NET te maken in een onderdeel aan de clientzijde.
Synchrone aanroepen werken als:
JavaScript location
JavaScript-code (JS) laden met behulp van een van de methoden die worden beschreven in het artikel over javaScript-locatie:
-
een script laden in
<head>
opmaak (over het algemeen niet aanbevolen) -
Een script laden in
<body>
-opmaak -
een script laden vanuit een extern JavaScript-bestand (
.js
) dat is gekoppeld aan een onderdeel -
een script laden vanuit een extern JavaScript-bestand (
.js
) - Een script injecteren voordat of nadat Blazor begint
Het gebruik van JS-modules om JS te laden, wordt beschreven in dit artikel in de paragraaf JavaScript-isolatie in JavaScript-modules.
Warning
Plaats geen <script>
tag in een onderdeelbestand (.razor
) omdat de tag <script>
niet dynamisch kan worden bijgewerkt.
JavaScript-isolatie in JavaScript-modules
Blazor maakt isolatie van JavaScript (JS) mogelijk in standaard JavaScript-modules (ECMAScript-specificatie). Laden van JavaScript-modules werkt op dezelfde manier in Blazor als voor andere typen web-apps en u kunt aanpassen hoe modules in uw app worden gedefinieerd. Zie MDN-webdocumenten: JavaScript-modulesvoor een handleiding over het gebruik van JavaScript-modules.
JS isolatie biedt de volgende voordelen:
- Geïmporteerde JS vervuilt de globale naamruimte niet meer.
- Gebruikers van een bibliotheek en componenten hoeven de gerelateerde JSniet te importeren.
Zie JavaScript-functies aanroepen vanuit .NET-methoden in ASP.NET Core Blazorvoor meer informatie.
Dynamisch importeren met de import()
-operator wordt ondersteund met ASP.NET Core en Blazor:
if ({CONDITION}) import("/additionalModule.js");
In het voorgaande voorbeeld vertegenwoordigt de tijdelijke aanduiding {CONDITION}
een voorwaardelijke controle om te bepalen of de module moet worden geladen.
Zie Kan ik gebruiken: JavaScript-modules: dynamische importvoor browsercompatibiliteit.
Vermijd kringverwijzingen naar objecten
Objecten die kringverwijzingen bevatten, kunnen niet op de client worden geserialiseerd voor:
- Aanroepen van .NET-methoden.
- Aanroepen van JavaScript-methoden vanuit C# wanneer het retourtype circulaire referenties bevat.
Ondersteuning voor bytematrix
Blazor ondersteunt geoptimaliseerde byte-array JavaScript-interoperabiliteit (JS) die het encoderen/decoderen van byte-arrays naar Base64 vermijdt. In het volgende voorbeeld wordt interop gebruikt JS om een bytematrix door te geven aan .NET.
Geef een sendByteArray
JS-functie op. De functie wordt statisch aangeroepen door een knop in de component, waarbij de parameter assemblynaam in de invokeMethodAsync
aanroep is opgenomen, en retourneert geen waarde.
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
Zie JSvoor algemene richtlijnen voor Blazor locatie en onze aanbevelingen voor productie-apps.
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));
}
}
Zie JavaScript-functies aanroepen vanuit .NET-methoden in ASP.NET Core Blazorvoor meer informatie over het gebruik van een bytematrix bij het aanroepen van JavaScript vanuit .NET.
Streamen van JavaScript naar .NET
Blazor ondersteunt het rechtstreeks streamen van gegevens van JavaScript naar .NET. Streams worden aangevraagd met behulp van de Microsoft.JSInterop.IJSStreamReference
interface.
Microsoft.JSInterop.IJSStreamReference.OpenReadStreamAsync
retourneert een Stream en gebruikt de volgende parameters:
-
maxAllowedSize
: Maximum aantal bytes dat is toegestaan voor de leesbewerking van JavaScript, wat standaard 512.000 bytes is als deze niet is opgegeven. -
cancellationToken
: A CancellationToken voor het annuleren van de leesbewerking.
In JavaScript:
function streamToDotNet() {
return new Uint8Array(10000000);
}
In C#-code:
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);
In het voorgaande voorbeeld:
-
JS
is een geïnjecteerd IJSRuntime exemplaar. IJSRuntime wordt geregistreerd door het Blazor framework. - De
dataReferenceStream
wordt naar schijf (file.txt
) geschreven op het tijdelijke mappad van de huidige gebruiker (GetTempPath).
JavaScript-functies aanroepen vanuit .NET-methoden in ASP.NET Core Blazor behandelt de omgekeerde bewerking, streaming van .NET naar JavaScript met behulp van een DotNetStreamReference.
ASP.NET Core Blazor bestandsuploads behandelt hoe u een bestand uploadt in Blazor. Zie voor een voorbeeld van formulieren dat <textarea>
gegevens in een server-side component streamt, Problemen met ASP.NET Core Blazor formulieren oplossen.
JavaScript-interoperabiliteit [JSImport]
/[JSExport]
Deze sectie is van toepassing op onderdelen aan de clientzijde.
Als alternatief voor interactie met JavaScript (JS) in clientonderdelen met behulp van BlazorJS interop-mechanisme op basis van de IJSRuntime interface, is een JS[JSImport]
/[JSExport]
interop-API beschikbaar voor apps die gericht zijn op .NET 7 of hoger.
Zie JavaScript JSImport/JSExport-interop met ASP.NET Core Blazorvoor meer informatie.
Verwijdering van JavaScript-interoperabiliteitsobjectverwijzingen
Voorbeelden in de Interop-artikelen van JavaScript (JS) laten typische patronen voor objectverwijdering zien:
Wanneer u .NET aanroept van JS, zoals beschreven in dit artikel, verwijdert u een gemaakt DotNetObjectReference van .NET of van JS om te voorkomen dat .NET-geheugen wordt gelekt.
Wanneer u JS aanroept vanuit .NET, zoals beschreven in JavaScript-functies aanroepen vanuit .NET-methoden in ASP.NET Core Blazor, verwijdert u alle gemaakte IJSObjectReference/IJSInProcessObjectReference/
JSObjectReference
van .NET of van JS om te voorkomen dat JS geheugen wordt gelekt.
JS interop-objectverwijzingen worden geïmplementeerd als een kaart die is gekoppeld aan een id aan de zijkant van de JS interop-aanroep waarmee de verwijzing wordt gemaakt. Wanneer de verwijdering van een object wordt geïnitieerd vanuit de .NET- of JS-kant, verwijdert Blazor de vermelding uit de kaart en kan het object worden afval verzameld, zolang er geen andere sterke verwijzing naar het object aanwezig is.
Verwijder minimaal objecten die aan de .NET-zijde zijn gemaakt om te voorkomen dat .NET beheerd geheugen wordt gelekt.
DOM-opschoontaken tijdens het verwijderen van onderdelen
Zie ASP.NET Core Blazor JavaScript-interoperabiliteit (JS interop)voor meer informatie.
JavaScript-interopaanroepen zonder circuit
Zie ASP.NET Core Blazor JavaScript-interoperabiliteit (JS interop)voor meer informatie.
Additional resources
- JavaScript-functies aanroepen vanuit .NET-methoden in ASP.NET Core Blazor
-
InteropComponent.razor
voorbeeld (dotnet/AspNetCore
GitHub-opslagplaatsmain
branch): demain
vertakking vertegenwoordigt de huidige ontwikkeling van de producteenheid voor de volgende release van ASP.NET Core. Als u de vertakking wilt selecteren voor een andere release (bijvoorbeeldrelease/{VERSION}
, waarbij de tijdelijke aanduiding{VERSION}
de releaseversie is), gebruikt u de Switch-vertakkingen of -tags vervolgkeuzelijst om de vertakking te selecteren. Voor een tak die niet meer bestaat, gebruikt u de tab Tags om de API te vinden (bijvoorbeeldv7.0.0
). - Interactie met de DOM
-
Blazor voorbeelden GitHub-opslagplaats (
dotnet/blazor-samples
) (hoe te downloaden) - fouten afhandelen in ASP.NET Core Blazor-apps (sectie vanJavaScript interop)
- Bedreigingsbeperking: .NET-methoden die vanuit de browser worden aangeroepen