情報応用演習Ⅰ(2024)

【T9b】簡易ブログソフトウェアの作成 Part.Ⅱ ~ 記事関連機能の実装(8/11)

プロジェクトタイプ(注意: 本文参照)
プロジェクト名T9b
ソリューション名PIT9
注意
  • 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
    • 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
    • プロジェクトの作成作業については準備作業を参照せよ.

9b-8. 記事の個別表示のためのアクションの修正

次に記事の個別表示のためのアクションであるDetailsアクションとそのビューを見直そう. デフォルトでは誰であってもすべての記事の個別表示が可能になっているが, 「下書き」の記事はその記事の作成者であるか管理者ユーザーしか閲覧できないようにしなくてはならない. そのためArticlesコントローラーのDetailsアクションを_に示すように修正しよう.

Articlesコントローラーの修正内容(Details)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// GET: Articles/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var article = await _context.Articles
        .Include(a => a.BlogUser)
        .FirstOrDefaultAsync(m => m.ArticleId == id);
    if (article == null)
    {
        return NotFound();
    }

    // ログイン中のユーザー情報を取得して閲覧可能かどうかを調べる.
    BlogUser? currentUser = await _userManager.GetUserAsync(User);
    if (!await IsReadableAsync(currentUser, article)) return Forbid();

    // ログイン中の場合その記事を編集可能かどうかをViewDataに記憶しておく.
    ViewBag.IsModifiable = currentUser != null && await IsModifiableAsync(currentUser, article);

    return View(article);
}

17~19行目ではリスト9b-5-2で定義したIsReadableAsync()メソッドを使用して その記事がログイン中のユーザーにとって閲覧可能であるかを判定し,そうでなければForbid()メソッドを呼び出して アクセスを拒否している.

21~22行目では同じくリスト9b-5-2で定義したIsModifiableAsync()メソッドを使用して その記事がログイン中のユーザーにとって削除・編集可能であるかを判定し,その判定結果をViewBagに格納している.

このDetailsアクションのためのビューも変更しておこう. Views/Articles/Details.cshtml を_に示すように変更しよう.

Views/Articles/Details.cshtmlの内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@model T9b.Models.Article

@{
    if (Model is null) throw new ArgumentNullException(nameof(Model)); // ad-hoc! 非null保証のための回避策

    ViewData["Title"] = Model.Title; // 記事タイトルをページのタイトルに設定する.

    var isModifiable = (bool)ViewBag.IsModifiable; // この記事をログイン中のユーザーが
                                                   // 修正できるかどうかをViewBagから取り出す.
}

@* 記事の作成者の表示 *@
<p> @(Model.BlogUser?.Nickname ?? Model.BlogUser?.UserName) による投稿</p>

<dl>
  @* 記事の作成日時の表示 *@
  <dt>@Html.DisplayNameFor(m => m.Created)</dt>
  <dd>@Html.DisplayFor(m => m.Created)</dd>

  @* 記事の更新日時の表示 *@
  <dt>@Html.DisplayNameFor(m => m.Modified)</dt>
  <dd>@Html.DisplayFor(m => m.Modified)</dd>
</dl>

@* 記事の本文の表示 *@
<pre class="article">@Model.Body</pre>

<a asp-action="Index">一覧に戻る</a>

@if(isModifiable)
{
    <text>| </text><a asp-action="Edit" asp-route-id="@Model.ArticleId">編集</a>
    <text>| </text><a asp-action="Delete" asp-route-id="@Model.ArticleId">削除</a>
}

いままでのビューと異なり,ViewData["Title"]に直接記事のタイトルをセットしている(6行目). このViewData["Title"]は現状のレイアウトページ( Views/Shared/_Layout.cshtml )の5行目と23行目を見ると分かるが, ページの title 要素と本文( body 要素)内の最初の h2 要素に設定される文言であるため, このようにすることで当該の個所に記事のタイトルが設定されるようになる. 13行目ではリスト9b-6-2と同様に設定されていればニックネームを表示するようにしている.

また,アクションメソッド内で判定した編集・削除可能かどうかのフラグをViewBagから取り出し(8~9行目), 可能であれば「編集」と「削除」のリンクを表示するようにしている(30~34行目).

Last updated on 2024-06-19
Published on 2024-06-19

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.