WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

Blazor Web App でファイルアプロード

by WebSurfer 5. November 2024 14:45

Visal Studio 2022 の Blazor プロジェクト作成用テンプレートで Blazor Web App を選んで作成した Blazor アプリからファイルをアップロードする方法を書きます。

テンプレートで Blazor Web App を選択

基本的には先の記事「Blazor WASM でファイルアップロード」とほぼ同じです。違いは、WASM ではなく Web App であること、ファイルを選択する画面とアップロードする画面を分けたこと、ファイルをアップロードするスクリプトは jQuery ajax に替えて fetch を使ったこと、複数のファイルを一度にアップロードできるようにしたことです。

ファイルを選択する画面とアップロードする画面を分ける必要はないのですが、訳あって、画面遷移しても <input type="file" /> から取得できる FileList オブジェクトを画面間で受け渡すことができるかを調べるため分けました。

正確に言うと「受け渡す」のではなくて、Blazor アプリは基本 SPA なので、画面が遷移しても書き変わらない共通部分に情報を保持しておいて、異なる画面で共通に使うということです。

作成したアプリを動かして、Select File 画面でファイルを選択し、

Select File 画面

その後 Upload File 画面に移って[Upload]ボタンをクリックすると、別プロジェクトとして作成した ASP.NET Core Web API にファイルをアップロードするようになっています。

Upload File 画面

下に載せたコードで、Select File 画面でファイルを選択して FileList オブジェクト作成し、それを共通部分にある JavaScript の変数に代入し、Upload File 画面に移ってその変数から FileList オブジェクトを取得して FormData オブジェクトを作成し、ファイルをアップロードすることはできました。

ただし、Select File 画面の <input type="file" /> の DOM は、Upload File 画面ではなくなってしまうので、時間が経つとブラウザのガベージコレクタで FileList オブジェクトもなくなってしまう可能性は否定できません。

検証に使ったブラウザは、Windows 10 64-bit の Chrome 130.0.6723.117、Microsoft Edge 130.0.2849.68、Firefox 132.0.1、Opera 114.0.5282.115 です。


以下にどのようにアプリを作成したかを書きます。

まず、一番上の画像に示したように Visual Studio 2022 のテンプレートを使って Blazor Web App のプロジェクトを作成します。この記事のサンプルでは Interactive render mode は Server に、Interactive location は Per Page/component に設定しました。(Interactive render mode は Auto でも WebAssembly でも OK です)

Razor Component の追加

Select File 画面と File Upload 画面の Razor Component を追加します。コードはそれぞれ以下の通りです。Blazor Web App はデフォルトでは static rendering になるので、下のコード例のように rendermode を指定しないと interactive にならず、スクリプトを Invoke できないことに注意してください。

Select File 画面用

@page "/selectfile"
@rendermode InteractiveServer
@inject IJSRuntime JSRuntime;

<h3>Select File</h3>

<input type="file" name="fileupload" id="fileupload" 
    multiple="multiple" @onchange="Select" />

<div id="result"></div>

@code {
    private async Task Select()
    {
        await JSRuntime.InvokeVoidAsync("select");
    }
}

Upload File 画面用

@page "/uploadfile"
@rendermode InteractiveServer
@inject IJSRuntime JSRuntime;

<h3>Upload File</h3>

<button type="button" class="btn btn-primary" @onclick="Upload">
    Upload
</button>

<div id="result"></div>

@code {
    private async Task Upload()
    {
        await JSRuntime.InvokeVoidAsync("upload");
    }
}

ファイル選択とアップロード用 JavaScript

上の Select File 画面と Upload File 画面でファイル選択とアップロードを行う JavaScript ファイルを作成し、wwwroot フォルダに配置します。名前は任意ですがこの記事では exampleJsInterop.js としています。

window.select = () => {
    let fileUpload = document.getElementById("fileupload");
    fileList = fileUpload.files;

    let str = "<ul>";
    for (let i = 0; i < fileList.length; i++) {
        str += `<li>${fileList[i].name}, ${fileList[i].type}, ${fileList[i].size}</li>`
    }
    str += "</ul>";

    let result = document.getElementById("result");
    result.innerHTML = str;
}

window.upload = async () => {   
    if (fileList) {
        let resultDiv = document.getElementById("result");

        let fd = new FormData();
        for (let i = 0; i < fileList.length; i++) {
            fd.append("postedfiles", fileList[i])
        }

        const param = {
            method: "POST",
            body: fd
        }
        const response = await fetch("送信先 Web API の url", param);
        if (response.ok) {
            const message = await response.text();
            resultDiv.innerText = message;
        } else {
            resultDiv.innerText = "アップロード失敗";
        }
    }
}

App.razor にコードを追加

上の Select File 画面の JavaScript で <input type="file" /> から取得した FileList オブジェクトへの参照を保持するスクリプト fileList = null; と、wwwroot に配置した外部スクリプトファイル exampleJsInterop.js をダウンロードできるよう、下の画像の赤枠で囲ったコードを追加します。

App.razor にコードを追加

Blazor は基本 Single Page Application なので、追加した部分は遷移で書き換えられることはなく、すべての画面で共有されます。

ファイル受信用 Web API

上の JavaScript により送信されたファイルファイルを受信するため、別プロジェクトとして CORS 対応した Web API を作成しています。そのアクションメソッドのコードを下に載せておきます。

using Microsoft.AspNetCore.Mvc;

namespace WebApi.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class FileUpDownloadController : ControllerBase
    {
        // 物理パスの取得用
        private readonly IWebHostEnvironment _hostingEnvironment;

        public FileUpDownloadController(IWebHostEnvironment hostingEnvironment)
        {
            this._hostingEnvironment = hostingEnvironment;
        }

        [HttpPost("multiple")]
        public async Task<IActionResult> MuilipleFiles(List<IFormFile>? postedFiles)
        {
            string result = "アップロードされたファイル: ";
            if (postedFiles != null)
            {
                // アプリケーションルートの物理パスを取得
                // wwwroot の物理パスは WebRootPath プロパティを使う
                string contentRootPath = _hostingEnvironment.ContentRootPath;

                foreach (var postedFile in postedFiles)
                {
                    if (postedFile != null && postedFile.Length > 0)
                    {
                        // アップロードされたファイル名を取得
                        string filename = Path.GetFileName(postedFile.FileName);

                        // アプリケーションルート直下の UploadedFiles フォルダに書き込み
                        string filePath = $"{contentRootPath}\\UploadedFiles\\{filename}";
                        using (var stream = new FileStream(filePath, FileMode.Create))
                        {
                            await postedFile.CopyToAsync(stream);
                        }

                        result += $"{filename} ";
                    }
                }
            }
            else
            {
                result = "ファイルアップロードに失敗しました";
            }

            return Content(result);
        }
    }
}

Tags: , , ,

Upload Download

Blazor WASM から ASP.NET Core Web API を呼び出し

by WebSurfer 29. June 2024 11:42

ASP.NET Core Blazor Web Assembly (WASM) からトークン (JWT) ベースの認証が必要な ASP.NET Core Web API にクロスドメインでアクセスしてデータを取得するサンプルを作ってみました。以下に作り方を備忘録として書いておきます。

結果の表示

Visual Studio 2022 のテンプレートを利用して ASP.NET Core Web API と Blazor WASM のソリューションを別々に作成します。完成後、Visual Studio 2022 から両方のプロジェクトを実行し ([デバッグ(D)]⇒[デバッグなしで開始(H)])、Blazor WASM から Web API に要求を出して応答を Blazor WASM の画面上に表示したのが上の画像です。

以下に、まず Web API アプリの作り方、次に Blazor WASM アプリの作り方を書きます。

(1) Web API アプリ

(1.1) プロジェクトの作成

元になる ASP.NET Core Web API アプリのプロジェクトは Visual Studio 2022 V17.10.3 のテンプレートで自動生成されたものを使いました。プロジェクトを作成する際「追加情報」のダイアログで「認証の種類(A)」は「なし」にします。この記事ではターゲットフレームワークは .NET 8.0 にしました。

自動生成されたプロジェクトにはサンプルのコントローラ WeatherForecastController が実装されていて、Visual Studio からプロジェクトを実行し、ブラウザから WeatherForecast を要求すると JSON 文字列が返ってきます。

これに JWT ベースの認証を実装し(即ち、トークンが無いとアクセス拒否するようにし)、さらに Blazor WASM からクロスドメインで呼び出せるようにするため CORS を実装します。

加えて、クライアントからの要求に応じてトークンを発行するための API も追加で実装します。この記事では、トークン要求の際クライアントから ID とパスワードを送信してもらい、それらが既存の ASP.NET Core Identity で有効であることを確認してからトークンを返すようにします。無効の場合は HTTP 401 Unauthorized 応答を返します。

(1.2) NuGet パッケージのインストール

下の画像の赤枠で囲んだ Microsoft.AspNetCore.Authentication.JwtBearer を NuGet からインストールします。

NuGet パッケージのインストール

青枠で囲んだものは、上に述べたトークン発行の際の既存の ASP.NET Core Identity によるユーザー認証を行うために必要です。ASP.NET Core Identity を使わない場合(例えば、ユーザー認証なしで無条件にトークンを返すようにする場合)は必要ありません。

(1.3) JWT 認証スキーマを登録

自動生成された Program.cs に、AddAuthentication メソッドを使って JWT 認証スキーマを登録するコードを追加します。加えて、認証を有効にするため app.UseAuthentication(); も追加します。

app.UseAuthentication(); は既存のコードの app.UseAuthorization(); の前にする必要があるので注意してください。

具体的には以下のコードで「JWT ベースの認証を行うため追加」とコメントしたコードを追加します。

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using WebApi.Data;
using Microsoft.EntityFrameworkCore;

namespace WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // JWT ベースの認証を行うため追加
            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = builder.Configuration["Jwt:Issuer"],
                        ValidAudience = builder.Configuration["Jwt:Issuer"],
                        IssuerSigningKey = new SymmetricSecurityKey(
                            Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
                    };
                });

            // ・・・中略・・・

            // JWT ベースの認証を行うため追加
            app.UseAuthentication();

            //・・・後略・・・

(1.4) Key と Issuer を appsettings.json に登録

上の (1.3) コードでは Key と Issuer を appsettings.json ファイルより取得するようにしていますので、以下のように "Jwt" 要素を追加します。

{

  ・・・中略・・・

  "AllowedHosts": "*",
  "Jwt": {
    "Key": "veryVerySecretKeyWhichMustBeLongerThan32",
    "Issuer": "https://localhost:44366"
  }
}

Key はパスワードのようなもので任意の文字列を設定できます。32 文字以上にしないとエラーになるので注意してください。.NET Core 3.1 時代は 16 文字以上で良かったのですが、いつからか 32 文字以上に変わったらしいです。Issuer はサービスを行う URL にします。

(1.5) [Authorize] 属性を付与

自動生成された WeatherForecastController コントローラの Get() メソッドに [Authorize] 属性を付与します。

ここまでの設定で JWT トークンベースのアクセス制限の実装は完了しており、トークンなしで WeatherForecastController コントローラの Get() メソッドを要求すると HTTP 401 Unauthorized 応答が返ってくるはずです。

(1.6) トークンを発行する API を実装

クライアントから送信されてきた ID とパスワードでユーザー認証を行った上でトークンを発行する API を実装します。以下のコードでは、UserManager<IdentityUser> オブジェクトへの参照を DI によって取得し、それを使って既存の ASP.NET Core Identity から情報を取得してユーザー認証に用いています。

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

namespace WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TokenController : ControllerBase
    {
        private readonly IConfiguration _config;
        private readonly UserManager<IdentityUser> _userManager;

        public TokenController(IConfiguration config,
                               UserManager<IdentityUser> userManager)
        {
            _config = config;
            _userManager = userManager;
        }

        [AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> CreateToken(LoginModel login)
        {
            string? id = login.Username;
            string? pw = login.Password;
            IActionResult response = Unauthorized();

            if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(pw))
            {
                var user = await _userManager.FindByNameAsync(id);
                if (user != null && 
                    await _userManager.CheckPasswordAsync(user, pw))
                {
                    var tokenString = BuildToken();
                    response = Ok(new { token = tokenString });
                }
            }

            return response;
        }


        private string BuildToken()
        {
            var key = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));

            var creds = new SigningCredentials(
                key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: _config["Jwt:Issuer"],
                audience: _config["Jwt:Issuer"],
                claims: null,
                notBefore: null,
                expires: DateTime.Now.AddMinutes(30),
                signingCredentials: creds);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }

    public class LoginModel
    {
        public string? Username { get; set; }
        public string? Password { get; set; }
    }
}

既存の ASP.NET Core Identity から情報を取得してユーザー認証を行うためには上記以外にも以下の (a) ~ (d) の追加が必要です。

ただし、ユーザー認証など面倒なことはしないで、CreateToken メソッドが呼ばれたら無条件にトークンを発行して返せばよいという場合は不要です。上のコードの UserManager<IdentityUser> オブジェクトの DI を行う部分も不要です。

(a) 上の (1.2) の画像で青枠で囲んだ NuGet パッケージのインストール。

(b) IdentityDbContext を継承した ApplicationDbContext クラスを追加。Data フォルダを作ってそれにクラスファイルとして実装します。

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace WebApi.Data
{
    public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext(
            DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
}

(c) appsettings.json に ASP.NET Core Identity が使う既存の SQL Server DB への接続文字列を追加。

(d) Program.cs に以下の「// 追加」とコメントしたコードを追加。これらは上の「(1.3) JWT 認証スキーマを登録」に書いたコード builder.Services.AddAuthentication(...); より前に追加する必要があるので注意してください。

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using WebApi.Data;
using Microsoft.EntityFrameworkCore;

namespace WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // 追加
            builder.Services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    builder.Configuration.GetConnectionString(
                        "MvcCoreIdentityContextConnection")));

            // 追加
            builder.Services.AddDefaultIdentity<IdentityUser>()
                            .AddEntityFrameworkStores<ApplicationDbContext>();

            //・・・後略・・・

(1.7) CORS 機能の実装

Blazor WASM からクロスドメインで Web API を呼び出すため、Web API アプリに CORS 機能を実装します。

具体的には、Program.cs に以下のコードを追加します。プリフライトリクエストが行われますので AllowAnyHeader() と AllowAnyMethod() が必要です。AllowCredentials() はトークンベースの認証の場合は不要のようです。

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using WebApi.Data;
using Microsoft.EntityFrameworkCore;

namespace WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // 追加
            var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
            builder.Services.AddCors(options =>
            {
                options.AddPolicy(name: MyAllowSpecificOrigins,
                                  policy =>
                                  {
                                      policy.AllowAnyOrigin()
                                            .AllowAnyHeader()
                                            .AllowAnyMethod();
                                  });
            });

            // ・・・中略・・・

            // 追加 
            app.UseCors(MyAllowSpecificOrigins);

            //・・・後略・・・

(2) Blazor WASM アプリ

(2.1) プロジェクトの作成

Visual Studio 2022 の新しいプロジェクトの作成で「Blazor WabAssembly アプリ」のテンプレート (Blazor Web App を選ばないよう注意)を使って自動生成されたものを使います。「追加情報」のダイアログで「認証の種類(A)」は「なし」にします。この記事ではターゲットフレームワークは .NET 8.0 にしました。

(2.2) Weather.razor の修正

自動生成されたプロジェクトの Weather.razor には、wwwroot 下の json ファイル weather.json を要求して、応答の JSON 文字列をデシリアライズして表示するコードが含まれています。

その部分のコードを、Web API からトークンを取得した後、トークンを要求ヘッダに含めて送信し、応答として返されたデータを表示するように変更します。

変更するのは @code ブロックのみで、以下の通りとなります。

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        // 以下はテンプレートで自動生成されたコードに含まれているもの
        // これを下のように書き換える
        // forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");

        var tokenUrl = "https://localhost:44366/api/token";
        var forecastUrl = "https://localhost:44366/WeatherForecast";

        // 送信する ID とパスワード。既存の ASP.NET Core Identity で有効なもの
        var credentials = new {
            Username = "oz@mail.example.com",
            Password = "myPassword"
        };

        // ID とパスワードを送信してトークンを取得
        // content-type: application/json; charset=utf-8 は自動的に
        // ヘッダに付与される
        using var tokenResponse = await Http.PostAsJsonAsync(tokenUrl, credentials);
        var jwt = await tokenResponse.Content.ReadFromJsonAsync<JWT>();

        if (jwt != null && !string.IsNullOrEmpty(jwt.Token))
        {
            // 取得したトークンを Authorization ヘッダに含めて GET 要求
            var request = new HttpRequestMessage(HttpMethod.Get, forecastUrl);
            request.Headers.Authorization = 
                new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", jwt.Token);
            using var forecastResponse = await Http.SendAsync(request);
            forecasts = await forecastResponse.Content.ReadFromJsonAsync<WeatherForecast[]>();
        }
    }

    // 追加
    public class JWT
    {
        public string? Token { get; set; }
    }

    public class WeatherForecast
    {
        public DateOnly Date { get; set; }

        public int TemperatureC { get; set; }

        public string? Summary { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
    }
}

デスクトップアプリで使う HttpClient の場合とほぼ同じコードになりました。。Blazor WASM のクライアント側はブラウザなので、HttpClient は動くはずはなく、XMLHttpRequest とか fetch などを使った JavaScript のコードに変換されてブラウザに送られたコードが動いているのではないかと思います。

ブラウザからのクロスドメインでの要求で、かつシンプルなリクエストとはならないので、CORS 対応のためのプリフライトリクエストが必要なヘッダ情報を含めて送信されます。Fiddler で要求・応答をキャプチャするとそのあたりのことが分かります。

Fiddler で要求・応答をキャプチャ

Tags: , , , ,

CORE

Blazor アプリで Bootstrap5 Modal の利用

by WebSurfer 11. March 2023 14:09

Blazor アプリで Bootstrap5 の Modal を使う方法を書きます。この記事では Visaul Studio 2022 のテンプレートで作った .NET 6.0 の Blazor Web Assembly を例に使います。(Blazor Server でもほぼ同じようにしてできます)

Blazor アプリで Bootstrap Modal

Bootstrap5 Modal の詳しい説明は Bootstrap のドキュメント「Modal (モーダル)」にあります。普通の html + css + javascript のページに Bootstrap5 Modal を組み込むなら、そのドキュメントから十分な情報が得られると思います。

JavaScript のメソッドを呼び出すのがいろいろややこしい Blazor アプリに、Bootstrap5 Modal を組み込むにはどうしたらいいかというのががこの記事のポイントで、それを以下に述べます。

Visaul Studio 2022 のテンプレートで作った .NET 6.0 の Blazor アプリには bootstrap.min.css v5.1.0 が組み込み済みです。ただし、それだけでは Modal は使えません。使うには bootstrap.js が必要なので同じバージョンのものを wwwroot 下に追加します。

加えて、JavaScript で Modal を表示するためのコードを含んだ外部スクリプトファイルを作成します。内容は以下の通りです。Bootstrap のドキュメント「Via JavaScript」を参考にしました。ファイル名は exampleJsInterop.js としています (名前は任意)。

window.showBootstrapModal = () => {
    // staticBackdrop は modal 表示する div 要素の id
    let divModal = document.getElementById('staticBackdrop');
    let myModal = new bootstrap.Modal(divModal);
    myModal.show();
}

Modal を表示するには、Bootstrap のドキュメント「Via data attributes」に書かれているように、表示に必要な属性を付与した button のような要素を使う方法もあります。その方法で良ければ、上のスクリプトファイル exampleJsInterop.js は不要です。ただし、その場合でも bootstrap.js は必要ですので注意してください。

bootstrap.js ファイルと exampleJsInterop.js ファイルを wwwroot 下に配置し、wwwroot/index.html にそのファイルへの参照を追加します。下の画像の赤枠を見てください。青枠は既存の bootstrap.min.css のものです。

外部スクリプトファイルの追加

Bootstrap5 は jQuery に依存していないそうですので jquery.js は不要です。(上の画像では jquery.js も追加されていますが、Bootstrap5 とは関係ない別の目的です)

Blazor Sever の場合、外部スクリプトファイル bootstrap.js と exampleJsInterop.js への参照を追加するのは Pages/_Layout.cshtml になります。そこだけが Blazor Web Assembly と Blazor Server の違いです。

Pages フォルダ下に Razor コンポーネントを追加し、それに Bootstrap のドキュメント「Live demo」のコードをコピーします。それだけで[Launch static backdrop modal]ボタンをクリックすると Modal が表示されるようになります。

Blazor アプリで Bootstrap Modal

JavaScript で Modal を表示するには、外部スクリプトファイル exampleJsInterop.js の showBootstrapModal メソッドを呼び出してやります。それを含めた Razor コンポーネント全体のコードは以下のようになります。

[Via JavaScript]ボタンに設定した @onclick="ShowBootstrapModal" で @code 内の ShowBootstrapModal メソッドを呼び出し、その中の InvokeVoidAsync メソッドで showBootstrapModal メソッドを呼び出しています。

@page "/modal"
@inject IJSRuntime JSRuntime;

<PageTitle>Bootstrap Modal</PageTitle>

<!-- Modal -->
<div class="modal fade" 
    id="staticBackdrop" 
    data-bs-backdrop="static" 
    data-bs-keyboard="false" tabindex="-1" 
    aria-labelledby="staticBackdropLabel" 
    aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" 
                    id="staticBackdropLabel">
                    Modal title
                </h5>
                <button type="button" 
                    class="btn-close" 
                    data-bs-dismiss="modal" 
                    aria-label="Close">
                </button>
            </div>
            <div class="modal-body">
                ...
            </div>
            <div class="modal-footer">
                <button type="button" 
                    class="btn btn-secondary" 
                    data-bs-dismiss="modal">
                    Close
                </button>
                <button type="button" 
                    class="btn btn-primary">
                    Understood
                </button>
            </div>
        </div>
    </div>
</div>

<h1>Bootstrap Modal</h1>

<!-- Via JavaScript -->
<button type="button" class="btn btn-primary" 
    @onclick="ShowBootstrapModal">
    Via JavaScript
</button>

<br />
<br />

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" 
    data-bs-toggle="modal" 
    data-bs-target="#staticBackdrop">
    Launch static backdrop modal
</button>

@code {
    private async Task ShowBootstrapModal()
    {
        await JSRuntime
            .InvokeVoidAsync("showBootstrapModal");
    }
}

JavaScript のメソッドを呼び出す方法の詳細は Microsoft のドキュメント「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」に書かれていますので興味がありましたら読んでください。

Tags: , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  November 2024  >>
MoTuWeThFrSaSu
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

View posts in large calendar