Interop JavaScript [JSImport]
/[JSExport]
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Artikel ini menjelaskan cara menjalankan .NET dari JavaScript (JS) menggunakan/JS[JSImport]
[JSExport]
interop.
Untuk panduan tambahan, lihat panduan Mengonfigurasi dan menghosting aplikasi .NET WebAssembly di repositori GitHub .NET Runtime (dotnet/runtime
).
Aplikasi yang JS ada dapat menggunakan dukungan WebAssembly sisi klien yang diperluas untuk menggunakan kembali pustaka .NET dari JS atau untuk membangun novel . Aplikasi dan kerangka kerja berbasis NET.
Catatan
Artikel ini berfokus pada menjalankan .NET dari JS aplikasi tanpa dependensi apa pun pada Blazor. Untuk panduan tentang menggunakan [JSImport]
/[JSExport]
interop dalam Blazor WebAssembly aplikasi, lihat interop JavaScript JSImport/JSExport dengan ASP.NET Core Blazor.
Pendekatan ini sesuai ketika Anda hanya berharap untuk berjalan di WebAssembly (WASM). Pustaka dapat melakukan pemeriksaan runtime untuk menentukan apakah aplikasi sedang berjalan WASM dengan memanggil OperatingSystem.IsBrowser.
Prasyarat
wasm-tools
Instal beban kerja dalam shell perintah administratif, yang membawa target MSBuild terkait:
dotnet workload install wasm-tools
Alat ini juga dapat diinstal melalui alat penginstal Visual Studio di bawah ASP.NET dan beban kerja pengembangan web di alat penginstal Visual Studio. Pilih opsi alat build .NET WebAssembly dari daftar komponen opsional.
Secara opsional, instal wasm-experimental
beban kerja, yang berisi templat proyek eksperimental untuk mulai menggunakan .NET di WebAssembly di aplikasi browser (Aplikasi Browser WebAssembly) atau di Simpul.jsaplikasi konsol berbasis -(Aplikasi Konsol WebAssembly). Beban kerja ini tidak diperlukan jika Anda berencana untuk mengintegrasikan JS[JSExport]
/[JSImport]
interop ke dalam aplikasi yang adaJS.
dotnet workload install wasm-experimental
Templat juga dapat diinstal dari Microsoft.NET.Runtime.WebAssembly.Templates
paket NuGet dengan perintah berikut:
dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
Untuk informasi selengkapnya, lihat bagian Beban kerja eksperimental dan templat proyek.
Ruang nama
JS API interop yang dijelaskan dalam artikel ini dikontrol oleh atribut di System.Runtime.InteropServices.JavaScript namespace layanan.
Konfigurasi proyek
Untuk mengonfigurasi proyek (.csproj
) untuk mengaktifkan JS interop:
Atur moniker kerangka kerja target (
{TARGET FRAMEWORK}
tempat penampung):<TargetFramework>{TARGET FRAMEWORK}</TargetFramework>
.NET 7 (
net7.0
) atau yang lebih baru didukung.Aktifkan AllowUnsafeBlocks properti , yang mengizinkan generator kode di kompilator Roslyn untuk menggunakan pointer untuk JS interop:
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Peringatan
JS API interop memerlukan pengaktifan AllowUnsafeBlocks. Berhati-hatilah saat menerapkan kode Anda sendiri yang tidak aman di aplikasi .NET, yang dapat menimbulkan risiko keamanan dan stabilitas. Untuk informasi selengkapnya, lihat Kode tidak aman, jenis penunjuk, dan penunjuk fungsi.
Berikut ini adalah contoh file proyek (.csproj
) setelah konfigurasi. Tempat {TARGET FRAMEWORK}
penampung adalah kerangka kerja target:
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
<PropertyGroup>
<TargetFramework>{TARGET FRAMEWORK}</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
Atur moniker kerangka kerja target:
<TargetFramework>net7.0</TargetFramework>
.NET 7 (
net7.0
) atau yang lebih baru didukung.Tentukan
browser-wasm
untuk pengidentifikasi runtime:<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
Tentukan jenis output yang dapat dieksekusi:
<OutputType>Exe</OutputType>
Aktifkan AllowUnsafeBlocks properti , yang mengizinkan generator kode di kompilator Roslyn untuk menggunakan pointer untuk JS interop:
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Peringatan
JS API interop memerlukan pengaktifan AllowUnsafeBlocks. Berhati-hatilah saat menerapkan kode Anda sendiri yang tidak aman di aplikasi .NET, yang dapat menimbulkan risiko keamanan dan stabilitas. Untuk informasi selengkapnya, lihat Kode tidak aman, jenis penunjuk, dan penunjuk fungsi.
Tentukan
WasmMainJSPath
untuk menunjuk ke file pada disk. File ini diterbitkan dengan aplikasi, tetapi penggunaan file tidak diperlukan jika Anda mengintegrasikan .NET ke dalam aplikasi yang ada JS .Dalam contoh berikut, JS file pada disk adalah
main.js
, tetapi nama file apa pun JS diizinkan:<WasmMainJSPath>main.js</WasmMainJSPath>
Contoh file proyek (.csproj
) setelah konfigurasi:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<WasmMainJSPath>main.js</WasmMainJSPath>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Interop JavaScript aktif WASM
API dalam contoh berikut diimpor dari dotnet.js
. API ini memungkinkan Anda menyiapkan modul bernama yang dapat diimpor ke dalam kode C# Anda dan memanggil metode yang diekspos oleh kode .NET Anda, termasuk Program.Main
.
Penting
"Impor" dan "ekspor" di seluruh artikel ini ditentukan dari perspektif .NET:
- Aplikasi mengimpor JS metode sehingga dapat dipanggil dari .NET.
- Aplikasi ini mengekspor metode .NET sehingga dapat dipanggil dari JS.
Dalam contoh berikut:
File
dotnet.js
digunakan untuk membuat dan memulai runtime .NET WebAssembly.dotnet.js
dihasilkan sebagai bagian dari output build aplikasi.Penting
Untuk berintegrasi dengan aplikasi yang ada, salin konten folder output penerbitan†ke aset penyebaran aplikasi yang ada sehingga dapat dilayani bersama dengan rest aplikasi. Untuk penyebaran produksi, terbitkan aplikasi dengan
dotnet publish -c Release
perintah di shell perintah dan sebarkan konten folder output dengan aplikasi.†Folder output penerbitan adalah lokasi target profil publikasi Anda. Default untuk Release profil di .NET 8 atau yang lebih baru adalah
bin/Release/{TARGET FRAMEWORK}/publish
, di mana{TARGET FRAMEWORK}
tempat penampung adalah kerangka kerja target (misalnya,net8.0
).dotnet.create()
menyiapkan runtime .NET WebAssembly.
setModuleImports
mengaitkan nama dengan modul JS fungsi untuk diimpor ke .NET. Modul JS berisidom.setInnerText
fungsi, yang menerima dan memilih elemen dan waktu untuk menampilkan waktu stopwatch saat ini di UI. Nama modul dapat berupa string apa pun (tidak perlu menjadi nama file), tetapi harus cocok dengan nama yangJSImportAttribute
digunakan dengan (dijelaskan nanti dalam artikel ini). Fungsi inidom.setInnerText
diimpor ke C# dan dipanggil dengan metodeSetInnerText
C# . MetodeSetInnerText
ini ditampilkan nanti di bagian ini.exports.StopwatchSample.Reset()
panggilan ke .NET (StopwatchSample.Reset
) dari JS. MetodeReset
C# memulai ulang stopwatch jika sedang berjalan atau mengatur ulang jika tidak berjalan. MetodeReset
ini ditampilkan nanti di bagian ini.exports.StopwatchSample.Toggle()
panggilan ke .NET (StopwatchSample.Toggle
) dari JS. MetodeToggle
C# memulai atau menghentikan stopwatch tergantung pada apakah saat ini berjalan atau tidak. MetodeToggle
ini ditampilkan nanti di bagian ini.runMain()
Program.Main
menjalankan .
setModuleImports
mengaitkan nama dengan modul JS fungsi untuk diimpor ke .NET. Modul JS berisiwindow.location.href
fungsi, yang mengembalikan alamat halaman (URL) saat ini. Nama modul dapat berupa string apa pun (tidak perlu menjadi nama file), tetapi harus cocok dengan nama yangJSImportAttribute
digunakan dengan (dijelaskan nanti dalam artikel ini). Fungsi iniwindow.location.href
diimpor ke C# dan dipanggil dengan metodeGetHRef
C# . MetodeGetHRef
ini ditampilkan nanti di bagian ini.exports.MyClass.Greeting()
panggilan ke .NET (MyClass.Greeting
) dari JS. MetodeGreeting
C# mengembalikan string yang menyertakan hasil pemanggilanwindow.location.href
fungsi. MetodeGreeting
ini ditampilkan nanti di bagian ini.dotnet.run()
Program.Main
menjalankan .
JS modul:
import { dotnet } from './_framework/dotnet.js'
const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet
.withApplicationArguments("start")
.create();
setModuleImports('main.js', {
dom: {
setInnerText: (selector, time) =>
document.querySelector(selector).innerText = time
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
document.getElementById('reset').addEventListener('click', e => {
exports.StopwatchSample.Reset();
e.preventDefault();
});
const pauseButton = document.getElementById('pause');
pauseButton.addEventListener('click', e => {
const isRunning = exports.StopwatchSample.Toggle();
pauseButton.innerText = isRunning ? 'Pause' : 'Start';
e.preventDefault();
});
await runMain();
import { dotnet } from './_framework/dotnet.js'
const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
.withDiagnosticTracing(false)
.withApplicationArgumentsFromQuery()
.create();
setModuleImports('main.js', {
window: {
location: {
href: () => globalThis.window.location.href
}
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
console.log(text);
document.getElementById('out').innerHTML = text;
await dotnet.run();
import { dotnet } from './dotnet.js'
const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);
const { setModuleImports, getAssemblyExports, getConfig } =
await dotnet.create();
setModuleImports("main.js", {
window: {
location: {
href: () => globalThis.window.location.href
}
}
});
const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
console.log(text);
document.getElementById("out").innerHTML = text;
await dotnet.run();
Untuk mengimpor JS fungsi sehingga dapat dipanggil dari C#, gunakan yang baru JSImportAttribute pada tanda tangan metode yang cocok. Parameter pertama untuk JSImportAttribute adalah nama fungsi yang akan diimpor JS dan parameter kedua adalah nama modul.
Dalam contoh berikut, fungsi dipanggil dom.setInnerText
dari main.js
modul ketika SetInnerText
metode dipanggil:
[JSImport("dom.setInnerText", "main.js")]
internal static partial void SetInnerText(string selector, string content);
Dalam contoh berikut, fungsi dipanggil window.location.href
dari main.js
modul ketika GetHRef
metode dipanggil:
[JSImport("window.location.href", "main.js")]
internal static partial string GetHRef();
Dalam tanda tangan metode yang diimpor, Anda dapat menggunakan jenis .NET untuk parameter dan mengembalikan nilai, yang dinamai secara otomatis oleh runtime. Gunakan JSMarshalAsAttribute<T> untuk mengontrol bagaimana parameter metode yang diimpor di-marshalled. Misalnya, Anda dapat memilih untuk marshal a long
sebagai System.Runtime.InteropServices.JavaScript.JSType.Number atau System.Runtime.InteropServices.JavaScript.JSType.BigInt. Anda dapat meneruskan Action/Func<TResult> panggilan balik sebagai parameter, yang dinamai sebagai fungsi yang dapat JS dipanggil. Anda dapat meneruskan JS referensi objek dan terkelola, dan dinamai sebagai objek proksi, menjaga objek tetap hidup di seluruh batas sampai proksi dikumpulkan sampah. Anda juga dapat mengimpor dan mengekspor metode asinkron dengan Task hasil, yang dinamai sebagai JS janji. Sebagian besar jenis marshalled bekerja di kedua arah, sebagai parameter dan sebagai nilai pengembalian, pada metode yang diimpor dan diekspor.
Fungsi yang dapat diakses pada namespace global dapat diimpor dengan menggunakan globalThis
awalan dalam nama fungsi dan dengan menggunakan [JSImport]
atribut tanpa memberikan nama modul. Dalam contoh berikut, console.log
diawali dengan globalThis
. Fungsi yang diimpor dipanggil oleh metode C# Log
, yang menerima pesan string C# (message
) dan marshalls string C# ke JSString
untuk console.log
:
[JSImport("globalThis.console.log")]
internal static partial void Log([JSMarshalAs<JSType.String>] string message);
Untuk mengekspor metode .NET sehingga dapat dipanggil dari JS, gunakan JSExportAttribute.
Dalam contoh berikut, setiap metode diekspor ke JS dan dapat dipanggil dari JS fungsi:
- Metode
Toggle
ini memulai atau menghentikan stopwatch tergantung pada status berjalannya. - Metode
Reset
memulai ulang stopwatch jika sedang berjalan atau mengatur ulang jika tidak berjalan. - Metode ini
IsRunning
menunjukkan apakah stopwatch berjalan.
[JSExport]
internal static bool Toggle()
{
if (stopwatch.IsRunning)
{
stopwatch.Stop();
return false;
}
else
{
stopwatch.Start();
return true;
}
}
[JSExport]
internal static void Reset()
{
if (stopwatch.IsRunning)
stopwatch.Restart();
else
stopwatch.Reset();
Render();
}
[JSExport]
internal static bool IsRunning() => stopwatch.IsRunning;
Dalam contoh berikut, Greeting
metode mengembalikan string yang menyertakan hasil pemanggilan GetHRef
metode. Seperti yang ditunjukkan GetHref
sebelumnya, metode C# memanggil fungsi JS window.location.href
dari main.js
modul. window.location.href
mengembalikan alamat halaman (URL) saat ini:
[JSExport]
internal static string Greeting()
{
var text = $"Hello, World! Greetings from {GetHRef()}";
Console.WriteLine(text);
return text;
}
Beban kerja eksperimental dan templat proyek
Untuk menunjukkan JS fungsionalitas interop dan mendapatkan JS templat proyek interop, instal wasm-experimental
beban kerja:
dotnet workload install wasm-experimental
Beban wasm-experimental
kerja berisi dua templat proyek: wasmbrowser
dan wasmconsole
. Templat ini bersifat eksperimental saat ini, yang berarti alur kerja pengembang untuk templat berkembang. Namun, .NET dan JS API yang digunakan dalam templat didukung di .NET 8 dan menyediakan fondasi untuk menggunakan .NET aktif WASM dari JS.
Templat juga dapat diinstal dari Microsoft.NET.Runtime.WebAssembly.Templates
paket NuGet dengan perintah berikut:
dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates
Aplikasi browser
Anda dapat membuat aplikasi browser dengan wasmbrowser
templat dari baris perintah, yang membuat aplikasi web yang menunjukkan menggunakan .NET dan JS bersama-sama di browser:
dotnet new wasmbrowser
Atau di Visual Studio, Anda dapat membuat aplikasi menggunakan WebAssembly Browser App templat proyek.
Buat aplikasi dari Visual Studio atau dengan menggunakan .NET CLI:
dotnet build
Buat dan jalankan aplikasi dari Visual Studio atau dengan menggunakan .NET CLI:
dotnet run
Atau, instal dan gunakan dotnet serve
perintah :
dotnet serve -d:bin/$(Configuration)/{TARGET FRAMEWORK}/publish
Dalam contoh sebelumnya, {TARGET FRAMEWORK}
tempat penampung adalah moniker kerangka kerja target.
Simpul.js aplikasi konsol
Anda dapat membuat aplikasi konsol dengan wasmconsole
templat, yang membuat aplikasi yang berjalan di bawah WASM sebagai aplikasi konsol Node.js atau V8 :
dotnet new wasmconsole
Atau di Visual Studio, Anda dapat membuat aplikasi menggunakan WebAssembly Console App templat proyek.
Buat aplikasi dari Visual Studio atau dengan menggunakan .NET CLI:
dotnet build
Buat dan jalankan aplikasi dari Visual Studio atau dengan menggunakan .NET CLI:
dotnet run
Atau, mulai server file statis apa pun dari direktori output penerbitan yang berisi main.mjs
file:
node bin/$(Configuration)/{TARGET FRAMEWORK}/{PATH}/main.mjs
Dalam contoh sebelumnya, {TARGET FRAMEWORK}
tempat penampung adalah moniker kerangka kerja target, dan {PATH}
tempat penampung adalah jalur ke main.mjs
file.
Sumber Daya Tambahan:
- Mengonfigurasi dan menghosting aplikasi .NET WebAssembly
- Dokumentasi API
- Interop JavaScript JSImport/JSExport dengan ASP.NET Core Blazor
dotnet/runtime
Di repositori GitHub:- Gunakan .NET dari aplikasi JavaScript apa pun di .NET 7
ASP.NET Core