WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

連動ドロップダウンリスト (ASP.NET Core MVC)

by WebSurfer 2024年2月8日 15:12

ASP.NET Core MVC での連動ドロップダウンリストの実装方法を備忘録として書いておきます。先の記事「連動ドロップダウンリスト (MVC5 版)」をターゲットフレームワーク .NET 8.0 の ASP.NET Core MVC ベースで書き直したものです。

ASP.NET Core MVC の連動 DropDownList

上の画像がそれで、先の記事と同様に、Microsoft の SQL Server サンプルデータベース Northwind の Categories テーブルと Products テーブルを使って、1 つめのドロップダウンリストで分類 (Categories) を選択すると、2 つめのドロップダウンリストにはその分類に属する製品 (Products) が絞り込まれて表示されるようにしています。

Categories テーブルと Products テーブルは以下の通りとなっています。(EDM のダイアグラムを表示したものです)

Categories  テーブルと Products テーブル

分類ドロップダウンリストの選択に応じて jQuery ajax を利用してアクションメソッドに要求を出し、選択された分類に該当するProducts テーブルの ProductID と ProductName を JSON 形式の応答として取得し、製品ドロップダウンリストの内容を書き換えるようにしています。

アプリの作り方の概要を以下に書きます。

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

Visual Studio 2022 のテンプレートの中から「ASP.NET Core Web アプリ (Model-View-Controller)」を選び ASP.NET Core MVC アプリのプロジェクトを作成します。

テンプレート

この記事の例ではターゲットフレームワークを .NET 8.0 にしています。その他のバージョンではこの記事の内容と多少違いがあるかもしれません。

(2) コンテキストクラスとエンティティクラスの作成

Entity Framework を利用するので、リバースエンジニアリングという手法を使って、SQL Server データベース Northwind からコンテキストクラスとエンティティクラスを生成します。

作成方法は Microsoft のドキュメント「スキャフォールディング (リバース エンジニアリング)」を見てください。各パラメータについては、こちらの記事 Scaffold-DbContext がまとまっていて分かりやすいと思います。

参考に、EF Core パッケージマネージャーコンソール (PMC) ツールを使った場合の Scaffold-DbContext コマンドの例を下に載せておきます。

Scaffold-DbContext -Connection "Data Source=(localdb)\MSSQLLocalDb;Initial Catalog=Northwind;Integrated Security=True" -Provider Microsoft.EntityFrameworkCore.SqlServer -ContextDir Data -OutputDir Models -Tables Products, Categories, Suppliers, Customers, Orders, Employees, Shippers, "Order Details" -DataAnnotations

(3) コンテキストクラスを DI コンテナに追加

上のステップ (2) で作成したコンテキストクラス NorthwindContext を DI コンテナに追加します。Program.cs に以下のコードを追加してください。"NorthwindConnection" は接続文字列名で任意です。

builder.Services.AddDbContext<NorthwindContext>(options =>
    options.UseSqlServer(builder.Configuration
           .GetConnectionString("NorthwindConnection")));

appsettings.json に接続文字列を追加します。名前は上のコードで設定したもの(この例では "NorthwindConnection")とし、接続文字列本体はリバースエンジニアリングの Scaffold-DbContext コマンドで使ったものと同じにします。ただし、文字列中の \ は \\ にエスケープする必要があるので注意してください。

(4) PruductsController と View の作成

Visual Studio のスキャフォールディング機能を使って、Products テーブルの CRUD (Create / Read / Upadate / Delete) を行う Controller と View 一式を生成します。

アプリを実行してみて CRUD 機能が期待通り動くことを確認します。

(5) アクションメソッドの追加

この記事の一番上の画像の連動ドロップダウンリスト用のアクションメソッドを作成し、上のステップ (4) で作った PruductsController に追加します。

まずベースとなるビューモデルを作成します。コードは以下の通りです。クラス名は任意ですがここでは Sales としています。

using System.ComponentModel.DataAnnotations;

namespace MvcNet8App.Models
{
    public class Sales
    {
        public int Id { get; set; }

        [Display(Name = "分類")]
        [Required(ErrorMessage = "{0} の選択は必須")]
        public int CategoryId { get; set; }

        [Display(Name = "製品")]
        [Required(ErrorMessage = "{0} の選択は必須")]
        public int ProductId { get; set; }

        [Display(Name = "コメント")]
        [Required(ErrorMessage = "{0} は必須")]
        public string? Comment { get; set; }
    }
}

連動ドロップダウンリスト用のアクションメソッド CascadingDropDown と、分類ドロップダウンリストの選択に応じて Products テーブルから選択された分類に該当する ProductID と ProductName を取得して JSON 形式で返すアクションメソッド GetProducts を作成し、PruductsController に追加します。

コードは以下の通りです。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using MvcNet8App.Data;
using MvcNet8App.Models;

namespace MvcNet8App.Controllers
{
    public class ProductsController : Controller
    {
        private readonly NorthwindContext _context;

        public ProductsController(NorthwindContext context)
        {
            _context = context;
        }

        // 中略(スキャフォールディングで自動生成されたコード)

        public IActionResult CascadingDropDown()
        {
            ViewData["CategoryId"] = 
                new SelectList(_context.Categories, "CategoryId", "CategoryName");
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult CascadingDropDown(
            [Bind("ProductId,CategoryId,Comment")] Sales sales)
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }

            // 検証結果 NG で再描画する際は以下のように再度 ViewBag
            // に SelectList を設定しないと分類ドロップダウンの中身
            // が表示されないので注意
            ViewData["CategoryId"] = 
                new SelectList(_context.Categories, "CategoryId", "CategoryName");
            return View(sales);
        }

        // 製品ドロップダウンに表示する ProductID と ProductName を
        // JSON 形式で取得するアクションメソッド。引数 id が分類ドロ
        // ップダウンで選択された CategoryID
        public async Task<IActionResult> GetProducts(int id)
        {
            var products = _context.Products
                           .Where(p => p.CategoryId == id)
                           .Select(p => new
                           {
                               ProductId = p.ProductId,
                               ProductName = p.ProductName
                           });

            return Json(await products.ToListAsync());
        }
    }
}

上のアクションメソッド GetProducts が返す JSON 文字列は、デフォルトでは Camel Casing される ( {"name":"value"} の "name" の先頭の文字が小文字になる) ので注意してください。(詳しくは先の記事「JsonSerializer の Camel Casing (CORE)」を見てください)

Camel Casing されないようにするには、Program.cs のコードの中に AddControllersWithViews() メソッドが含まれているはずなので、それに以下のように .AddJsonOptions(opttions => ... 以下のコードを追加します。

builder.Services.AddControllersWithViews().AddJsonOptions(options =>
{
    options.JsonSerializerOptions.PropertyNamingPolicy = null;
});

これをし���いで、クライアントスクリプトで対応しても OK です。いずれにしても、対応しないと製品ドロップダウンリストの内容が undefined となってしまいますので注意してください。

(6) View の追加

上のステップ (5) で作成したアクションメソッド CascadingDropDown に対応する View をスキャフォールディング機能を利用して作成します。レイアウトページ _Layout.cshtml を利用しています。コードは以下の通りです。説明はコメントに書きましたので、それを見てください

@model MvcNet8App.Models.Sales

@{
    var data = ViewBag.CategoryID;
    
    ViewData["Title"] = "CascadingDropDown";    
}

<h1>CascadingDropDown</h1>

<div class="row">
    <div class="col-md-4">
        <form asp-action="CascadingDropDown">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <input type="hidden" asp-for="Id" />
            <div class="form-group">
                <label asp-for="CategoryId" class="control-label"></label>

                @* 
                スキャフォールディングで生成される input を select に書き換え
                *@
                <select asp-for="CategoryId" class="form-control" 
                    asp-items="ViewBag.CategoryId">
                    <option value="">▼分類を選択してください▼</option>
                </select>

                <span asp-validation-for="CategoryId" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="ProductId" class="control-label"></label>

                @*
                スキャフォールディングで生成される input を select に書き換え
                asp-for="ProductId" が無いと検証が動かないので注意 
                *@
                <select asp-for="ProductId" class="form-control"></select>

                <span asp-validation-for="ProductId" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Comment" class="control-label"></label>
                <input asp-for="Comment" class="form-control" />
                <span asp-validation-for="Comment" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

    <script type="text/javascript">
        //<![CDATA[

        $(function () {
            // 分類ドロップダウンの jQuery オブジェクトを取得。
            // html コードの id は html ヘルパの Id メソッドで取得
            var categoryDDL = $('#@Html.Id("CategoryId")');
            var productDDL = $('#@Html.Id("ProductId")');

            // 以下は初期画面および検証結果 NG での再描画の際必要。
            // 初期画面では categoryDDL.val() は上の option 要素の
            // value="" を取得するので if 文の条件は false となる。
            // 検証結果 NG で再描画される際は分類ドロップダウンの
            // 選択に応じて製品ドロップダウンの内容を書き換える
            if (categoryDDL.val() != "") {
                productDDL.children().remove();
                productDDL.append(
                    '<option value="">▼製品を選択してください▼</option>');
                productDDL.removeAttr('disabled');

                // 分類ドロップダウンの選択結果 (CategoryId) を
                // jQuery ajax でサーバー側の GetProducts アクション
                // メソッドに送信。アクションメソッドは Products テ
                // ーブルに SELECT クエリを発行し、CategoryId に属す
                // 製品の ProductId, ProductName を取得して JSON 文
                // 字列として返す。その JSON 文字列から option 要素
                // の文字列を組み立てて製品ドロップダウンに追加する
                $.ajax({
                    url: '/Products/GetProducts/' + categoryDDL.val(),
                    method: 'get',
                }).done(function (data) {
                    $.each(data, function (key, val) {
                        productDDL.append('<option value=' +
                            val.ProductId + '>' + val.ProductName +
                            '</option>');
                    });
                }).fail(function (jqXHR, textStatus, errorThrown) {
                    alert('Error getting products!');
                });
            } else {
                productDDL.children().remove();
                productDDL.attr('disabled', 'disabled');
            }

            // 分類ドロップダウンの選択が変更されると change イベント
            // が発生 するのでそのリスナで製品ドロップダウンの内容を
            // 分類に応じて書き換え。リスナの中身は上と同じコード
            categoryDDL.on("change", function () {
                if (categoryDDL.val() != "") {
                    productDDL.children().remove();
                    productDDL.append(
                        '<option value="">▼製品を選択してください▼</option>');
                    productDDL.removeAttr('disabled');

                    $.ajax({
                        url: '/Products/GetProducts/' + categoryDDL.val(),
                        method: 'get',
                    }).done(function (data) {
                        $.each(data, function (key, val) {
                            productDDL.append('<option value=' +
                                val.ProductId + '>' + val.ProductName +
                                '</option>');
                        });
                    }).fail(function (jqXHR, textStatus, errorThrown) {
                        alert('Error getting products!');
                    });
                } else {
                    productDDL.children().remove();
                    productDDL.attr('disabled', 'disabled');
                }
            });
        });

        //]]>
    </script>
}

Tags:

CORE

ASP.NET Core MVC で Bootstrap5 Modal の利用

by WebSurfer 2023年11月11日 10:46

Visual Studio 2022 を使って作成する ASP.NET Core MVC アプリで、データベースのテーブル一覧を表示し、その中の項目を選択すると、その詳細を Bootstrap5 の Modal を利用して表示する方法を書きます。

Bootstrap Modal に詳細を表示

この記事ではターゲットフレームワークを .NET 7.0 としています。.NET 5.0 以前をターゲットフレームワークとして作成したプロジェクトでは Bootstrap のバージョンが異なるので注意してください。

この記事のベースとしたアプリは、Microsoft のチュートリアル「CRUD 機能を実装する」です。そのアプリの Student テーブルのレコード一覧を表示する Index ページと各レコードの詳細を表示する Details ページを使います。

チュートリアルでは、Index ページに一覧表示されている各項目の右横のアクションリンク Details をクリックすると、別ページ Details に遷移し、遷移した Details ページ上で選択した項目の詳細を表示するようになっています。チュートリアルの「Details ビューに登録を追加する」セクションの下の方の画像を見てください。

それを、別ページ Details に遷移しないで、この記事の上の画像のように Index ページ上で Bootstrap Modal 内に詳細を表示するようにしてみます。

Bootstrap については、Visual Studio 2022 のテンプレートで、ターゲットフレームワーク .NET 7.0 として作成した ASP.NET Core MVC アプリのプロジェクトに Bootstrap.js, Boorstrap.css v5.1.0 が含まれています。Bootstrap Modal を使うために必要なものもそれらの中に含まれているので何も追加する必要はありません。

レイアウトページ _Layout.cshtml にはプロジェクトの Bootstrap.js, Boorstrap.css を参照する link タグ、script タグが含まれていますので、スキャフォールディングの際 _Layout.cshtml を使用するように設定すれば、それらが参照されるようになります。

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

ASP.NET Core MVC アプリに、Bootstrap5 Modal を組み込んで、Index ページにのアクションリンクをクリックして詳細データを取得し、Index ページ上で Modal に表示するにはどうしたらいいかというのががこの記事のポイントで、それを以下に述べます。

まずコントローラーのアクションメソッドですが、Index はチュートリアルのものと全く同じ、Details も最後の一行で部分ビューを返すように変更する以外はチュートリアルのものと同じです。

コードは以下の通りとなります。この記事ではアクションメソッドの名前を Index3, Details3 としています。

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MvcNet7App.Data;
using MvcNet7App.Models;

namespace MvcNet7App.Controllers
{
    public class StudentsController : Controller
    {
        private readonly SchoolContext _context;

        public StudentsController(SchoolContext context)
        {
            _context = context;
        }

        // Student のレコード一覧を取得しビューに渡す
        public async Task<IActionResult> Index3()
        {
            return _context.Students != null ?
                   View(await _context.Students.ToListAsync()) :
                   Problem("Entity set 'SchoolContext.Students'  is null.");
        }

        // 詳細を表示する部分ビュー用のアクションメソッド
        public async Task<IActionResult> Details3(int? id)
        {
            if (id == null || _context.Students == null)
            {
                return NotFound();
            }

            //var student = await _context.Students
            //    .FirstOrDefaultAsync(m => m.ID == id);
            var student = await _context.Students
                                        .Include(s => s.Enrollments)
                                            .ThenInclude(e => e.Course)
                                        .AsNoTracking()
                                        .FirstOrDefaultAsync(m => m.ID == id);

            if (student == null)
            {
                return NotFound();
            }

            // 部分ビューを返すように変更
            return PartialView(student);
        }
    }
}

次に、上の Index アクションメソッドに対応するビューですが、スキャフォールディングで自動生成されたコードに (1) Modal 部分を実装、(2) Details アクションリンクを JavaScript のメソッドを呼び出すよう変更、(3) fetch API でサーバーに要求を出し、応答として返される部分ビューを Modal 内の div 要素に書き込んだ後 Modal を表示する JavaScript のメソッドを追加します。

コードは以下の通りです。Modal 部分は Bootstrap 5 のドキュメント「Modal (モーダル)」の「Static backdrop」セクションのサンプルコードをコピペし、若干修正をして利用しています。詳細を書き込む div 要素に id="details" を追加したこと、デフォルトの "medium" サイズでは幅が足らないので CSS に modal-lg を追加したこと、Understood ボタンは削除したことが主な違いです。

@model IEnumerable<MvcNet7App.Models.Student>

@{
    ViewData["Title"] = "Index3";
}

<h1>Index3</h1>

<!-- (1) 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 modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"
                    id="staticBackdropLabel">
                    Student Details
                </h5>
                <button type="button"
                        class="btn-close"
                        data-bs-dismiss="modal"
                        aria-label="Close">
                </button>
            </div>
            <div class="modal-body" id="details">
                ...
            </div>
            <div class="modal-footer">
                <button type="button"
                        class="btn btn-primary"
                        data-bs-dismiss="modal">
                    Close
                </button>
            </div>
        </div>
    </div>
</div>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.LastName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstMidName)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.LastName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.FirstMidName)
                </td>
                <td>
                    @* (2) クリックで JavaScript の showDetails
                    を呼び出す。引数には Student の ID を渡す *@ 
                    <a href="javascript:showDetails(@item.ID)">
                        Details
                    </a>
                </td>
            </tr>
        }
    </tbody>
</table>

@section Scripts {
    <script type="text/javascript">

        // (3) fetch API でサーバーに要求を出し、応答として返される
        // 部分ビューを Modal 内の div 要素に書き込んだ、後 Modal を
        // 表示する

        // Modal を表示するためのヘルパーメソッド
        const showBootstrapModal = () => {
            // staticBackdrop は Modal の div 要素の id
            let divModal = document.getElementById('staticBackdrop');
            let myModal = new bootstrap.Modal(divModal);
            myModal.show();
        }

        const showDetails = async (id) => {
            // 部分ビュー用アクションメソッドの url
            // id は Student テーブルのレコードの ID
            const url = "/Students/Details3/" + id;

            // Student 詳細を表示する Modal 内の div 要素
            const resultDiv = document.getElementById('details');

            const response = await fetch(url);
            if (response.ok) {
                // 部分ビューのテキストを取得
                const text = await response.text();

                // テキストを Modal 内の div 要素に書き込み
                resultDiv.innerHTML = text;

                // Modal を表示
                showBootstrapModal();
            }            
        }

    </script>
}

最後に、Details アクションメソッドに対応する部分ビューですが、以下の通りとなっています。チュートリアルで自動生成されたコードから部分ビューに不要な部分を削除しただけです。

@model MvcNet7App.Models.Student

<div>
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.LastName)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.LastName)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.FirstMidName)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.FirstMidName)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.EnrollmentDate)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.EnrollmentDate)
        </dd>

        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Enrollments)
        </dt>
        <dd class="col-sm-10">
            <table class="table">
                <tr>
                    <th>Course Title</th>
                    <th>Grade</th>
                </tr>
                @foreach (var item in Model.Enrollments)
                {
                    <tr>
                        <td>
                            @Html.DisplayFor(modelItem => item.Course.Title)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.Grade)
                        </td>
                    </tr>
                }
            </table>
        </dd>
    </dl>
</div>

Tags: , , ,

CORE

ASP.NET Core のカスタムクラスから HttpContext にアクセス

by WebSurfer 2023年9月19日 14:59

ASP.NET Core Web アプリ内のカスタムクラスから HttpContext にアクセスする方法を備忘録として書いておきます。下の画像は、カスタムクラスから HttpContext にアクセスし、ログイン中のユーザー名を取得して表示したものです。赤枠の部分がそれです。

ログイン中のユーザー名を取得

その方法は Microsoft のドキュメント「ASP.NET Core で HttpContext にアクセスする」の中の「カスタム コンポーネントから HttpContext を使用する」を見ればすぐ分かるのですが、どこに書いてあったか忘れて探し回ることがないように自分のブログに書いておくことにしました。

基本的にどうするかというと、Visual Studio のテンプレートを使って作成する ASP.NET Core アプリには Dependency Injection (DI) 機能が組み込まれていますのでそれを利用します。

まず、DI コンテナに IHttpContextAccessor サービスと、それを利用するカスタムクラスを登録します。具体的には、Program.cs に以下のようにコードを追加します。

using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.EntityFrameworkCore;
using MvcNet7App.Data;
using MvcNet7App.Libraries;

var builder = WebApplication.CreateBuilder(args);

// ・・・中略・・・

// DI コンテナに IHttpContextAccessor サービスを登録
builder.Services.AddHttpContextAccessor();

// それを利用するカスタムクラスを登録
builder.Services.AddTransient<IUserRepository, UserRepository>();

// ・・・後略・・・

カスタムクラス UserRepository の例は以下の通りです。DI 機能によって、コンストラクタ経由で IHttpContextAccessor サービスを inject できるようにしています。LogCurrentUser メソッドは、inject された IHttpContextAccessor サービスから HttpContext にアクセスし、ログイン中のユーザー名を取得して戻り値として返します。

namespace MvcNet7App.Libraries
{
    public class UserRepository : IUserRepository
    {
        // DI でコンストラクタの引数経由 IHttpContextAccessor 
        // サービスを inject できるよう設定
        private readonly IHttpContextAccessor _httpContextAccessor;

        public UserRepository(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public string? LogCurrentUser()
        {
            // ログイン中のユーザー名を取得
            var username = _httpContextAccessor.HttpContext?
                           .User.Identity?.Name;
            return username;
        }
    }

    public interface IUserRepository
    {
        public string? LogCurrentUser();
    }
}

上のカスタムクラスを利用する場合は、組み込みの DI 機能を使ってカスタムクラスのインスタンスが渡されるようにします。例えば、MVC の Controller の場合、以下のようにコンストラクタの引数を経由してカスタムクラスのインスタンスを渡しています。

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using MvcNet7App.Libraries;
using MvcNet7App.Models;
using System.Diagnostics;

namespace MvcNet7App.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        // 組み込みの DI 機能によりコンストラクタの引数経由で
        // カスタムクラスのインスタンスが渡される
        private readonly Libraries.IUserRepository _user;

        public HomeController(ILogger<HomeController> logger, 
                              IUserRepository user)
        {
            _logger = logger;
            _user = user;
        }

        public IActionResult Index()
        {
            ViewBag.Username = _user.LogCurrentUser();

            return View();
        }

        // ・・・中略・・・
    }
}

ユーザーが上の Home/Index を要求すると、ASP.NET は HomeController のインスタンスを生成して要求を処理しますが、その際 DI コンテナに登録された UserRepository クラスと IHttpContextAccessor サービスのインスタンスは自動的・連鎖的に生成され、コンストラクタの引数経由で inject されます。

なので、Index アクションメソッドで、inject された UserRepository クラスの LogCurrentUser メソッドを使ってログイン中のユーザー名を取得できます。

取得したユーザー名を ViewBag を使って View に渡し、ブラウザ上に表示したのがこの記事の一番上の画像です。赤枠の中の surfer@mail.example.com がそれです。


なお、Controller や View から HttpContext にアクセスする場合は、DI 機能などは使う必要はなく、もっと簡単にできます。詳しくは「ASP.NET Core の HttpContext にアクセスする」を見てください。

Tags: , ,

CORE

About this blog

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

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar