BlazorアプリケーションでC#のコードからJavaScriptを呼び出す
BlazorアプリケーションでC#のコードからJavaScriptを呼び出すコードを紹介します。
概要
BlazorアプリケーションでJavaScriptの処理をC#のコードから呼び出したい場合のコードを紹介します。C#のコードからJavaScriptを呼び出す場合には、IJSRuntime クラスのInvokeAsync()メソッドを利用します。
プログラム1 : シンプルな実装
プロジェクトの作成
ASP.NET Core Webアプリケーションを作成します。手順は
こちらの記事を参照して下さい。
Blazorアプリケーションのファイル作成
Blazorアプリケーションで必要なファイルを作成します。
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
</Found>
<NotFound>
<LayoutView>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ExecJavaScript
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
フォールバックページの作成
Pagesフォルダ内にフォールバックページを作成します。
フォールバックページ内のheadタグ内にJavaScriptの関数を実装します。今回は myfunc という関数を作成します。関数が実行されるとalert関数を実行しダイアログを表示します。ダイアログのメッセージには「myfunc関数が呼び出されました」の文字列と、myfunc関数を呼び出した際の引数を表示します。
@page
@model ExecJavaScript.Pages._HostModel
@namespace ExecJavaScript.Pages
<!DOCTYPE html>
<html lang="ja">
<head>
<script>
function myfunc(text) {
alert('myfunc関数が呼び出されました:' + text);
}
</script>
</head>
<body>
<app>
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
</body>
</html>
@{
}
ページの作成
ページを作成します。Pagesフォルダ内に Index.razor ファイルを作成します。コードは下記になります。
@inject IJSRuntime JsRuntime;
を記述します。@inject ディレクティブによりIJSRuntimeのサービスを要求します。ページでは、buttonタグでボタンを配置します。@onclick属性に"ButtonClick"を指定しボタンがクリックされた際には@codeセクションのButtonClick()関数を呼び出します。
ButtonClick()関数では、IJSRuntimeのサービスインスタンスである JsRuntime オブジェクトの InvokeVoidAsync メソッドを呼び出します。InvokeVoidAsync の第一引数には呼び出すJavaScritptの関数名を与えます。第二引数以降に関数の引数を与えます。今回、myfunc関数は一つしか引数が無いため、InvokeVoidAsync に与える引数は呼び出す関数名とパラメーター一つの合計2つになります。
@page "/Index"
@inject IJSRuntime JsRuntime;
<h3>Index</h3>
<p></p>
<button type="button" @onclick="ButtonClick">Button1</button>
@code {
void ButtonClick()
{
string param = "penguin";
JsRuntime.InvokeVoidAsync("myfunc", param);
StateHasChanged();
}
}
実装完了後のソリューションエクスプローラーの状態です。
実行結果
プロジェクトを実行します。Webブラウザで
(アプリケーションルートURL)/Index
URLにアクセスします。下図のページが表示されます。
[Button1]をクリックします。アラートダイアログが表示され「myfunc関数が呼び出されました」のメッセージが表示されます。またメッセージの後にC#コードからmyfunc関数に与えた引数の"penguin" の値も表示されています。
C#のコードからJavaScriptの関数の呼び出しができました。
プログラム2 : ページのrazorコンポーネントの基底のC#コードからの呼び出し
先のプログラムはrazorファイル内の@codeセクションからJavaScriptの関数を呼び出しました。このセクションでは、razorファイルの基底クラスのC#のコードからJavaScript関数を呼び出すコードを紹介します。
先ほどのプログラムのPagesフォルダに Index_cb.razor ファイルとIndex_cb.razor.cs ファイルを追加します。コードは下記になります。
Index_cb.razorでは@inheritsディレクティブを記述しIndex_cb.razor.cs ファイルで実装されているIndex_cbModelクラスの派生クラスとします。また、ページ内にはbuttonタグを記述しボタンを配置します。@onclick属性には "ButtonClick" を指定します。ボタンのクリックにより、Index_cbModelクラスに実装した、ButtonClickメソッドを呼び出す処理になります。実装の詳細に関しては
こちらの記事を参照してください。
@page "/Index_cb"
@namespace ExecJavaScript.Pages
@inherits Index_cbModel
<h3>Index_cb</h3>
<button type="button" @onclick="ButtonClick">Button1</button>
C#のコードでは、[Inject]属性を利用し IJSRuntimeオブジェクトを参照します。IJSRuntimeオブジェクトのインスタンスオブジェクトが JsRuntime になります。また、ボタンがクリックされた際に呼び出される、ButtonClickメソッドを実装します。ボタンのクリックにより、IJSRuntimeオブジェクトのInvokeAsyncオブジェクトを呼び出します。第一引数に呼び出す関数名を与えます。第二引数にパラメーターを与えます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace ExecJavaScript.Pages
{
public class Index_cbModel : ComponentBase
{
[Inject]
private IJSRuntime JsRuntime { get; set; }
public void ButtonClick()
{
string param = "Duck";
JsRuntime.InvokeVoidAsync("myfunc", param);
StateHasChanged();
}
}
}
実装完了後のソリューションエクスプローラーの状態です。
実行結果
プロジェクトを実行します。Webブラウザで
(アプリケーションルートURL)/Index_cb
URLにアクセスします。下図のページが表示されます。
[Button1]をクリックします。アラートダイアログが表示され「myfunc関数が呼び出されました」のメッセージが表示されます。またメッセージの後にC#コードからmyfunc関数に与えた引数の"Duck" の値も表示されています。
プログラム3 : 戻り値がある場合の例
戻り値がある場合の実装コードを紹介します。
フォールバックページの_Host.cshtml ファイルにJavaScriptの関数を追加します。mycalc の名称で関数を実装します。2つの引数を受け取り数値に変換して2つの引数を足し、「計算結果は(合計値)です。」の文字列を巻子の戻り値として返します。
@page
@model ExecJavaScript.Pages._HostModel
@namespace ExecJavaScript.Pages
<!DOCTYPE html>
<html lang="ja">
<head>
<script>
function myfunc(text) {
alert('myfunc関数が呼び出されました:' + text);
}
function mycalc(a, b) {
var c = Number(a) + Number(b);
return "計算結果は" + String(c) + "です。";
}
</script>
</head>
<body>
<app>
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
</body>
</html>
ページを追加します。Index_return.razor ファイルと Index_return.razor.cs ファイルを追加します。コードは下記です。
Index_return.razor は@Inheritsディレクティブの記述により、Index_return.razor.csファイルのクラスIndex_returnModelの派生クラスとします。ページにはbuttonタグを記述しボタンを配置します。クリック時にはIndex_returnModelクラスのButtonClickメソッドを呼び出します。
また、ボタンの下部の段落で returnText変数の内容を表示します。reutnTextにはJavaScriptの関数の戻り値を代入するため、ボタンクリックでJavaScriptを実行したときの戻り値の値がページに表示される動作になります。
@page "/Index_return"
@namespace ExecJavaScript.Pages
@inherits Index_returnModel
<h3>Index_return</h3>
<button type="button" @onclick="ButtonClick">Button1</button>
<p>@retuenText</p>
C#のコードでは、IJSRuntime をInject属性を付けて呼び出しサービスが利用できる状態にします。今回は戻り値があるため、 InvokeVoidAsync メソッドではなくInvokeAsync メソッドを呼び出します。InvokeAsyncメソッドは非同期メソッドのため、await を付けてメソッドを呼び出し、メソッドの結果が戻るまで待機します。awaitを利用するため、ButtonClickメソッドも非同期にする必要があるため、メソッドの識別子にasyncを記述します。
InvokeAsyncメソッドのタイプ部分のTValueには戻り値の型を記述します。今回のJavaScriptの戻り値の型は文字列なので、stringを記述します。InvokeAsyncの第一引数には呼び出すJavaScriptの関数名を与えるため"mycalc"を与えます。mycalc関数は2つの引数があるため、第二引数と第三引数はmycalc関数の引数を記述します。
JavaScript関数の戻り値はreturnText変数に代入します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace ExecJavaScript.Pages
{
public class Index_returnModel:ComponentBase
{
[Inject]
private IJSRuntime JsRuntime { get; set; }
protected string retuenText;
public async void ButtonClick()
{
int param1 = 8;
int param2 = 4;
retuenText = await JsRuntime.InvokeAsync<string>("mycalc", param1, param2);
StateHasChanged();
}
}
}
実行結果
プロジェクトを実行します。Webブラウザで
(アプリケーションルートURL)/Index_return
URLにアクセスします。下図のページが表示されます。
[Button1]をクリックします。ページに「計算結果は12です。」の文字列が表示されます。JavaScriptの関数を呼び出し、計算結果と戻り値の取得ができていることが確認できます。
BlazorアプリケーションでC#のコードからJavaScriptの呼び出しができました。
このページのキーワード
- BlazorアプリケーションでC#のコードからJSを呼び出す
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用