📖

.NET Core Blazor + MicroCMSでブログサイト作成⑦

2021/09/05に公開

今回の内容は

  • ブログ記事をタグで絞り込む
  • ブログ記事ページ作成

です。

ラッキーセブンとよく言いますが、由来はアメリカの野球にあるそうです。

タグ絞り込み

ただのイベント処理です。

Blog.razor
//抜粋
@page "/blog"
@using BlazorBlog.Shared.MicroCMS
@inject HttpClient Http

@if (sitedata == null || tag == null || blog == null)
{
...
}
else
{
    <h1>@sitedata.BlogTitle</h1>

    <div class="mb-3">
        @foreach (TagContents contents in tag.TagList)
        {
	    <!-- @onclickを追加 -->
            <button type="button" class="btn btn-dark btn-sm rounded-pill mx-2" @onclick="@(e => TagSelected(contents.Id))">@contents.Name</button>
        }
    </div>
    ...
}

@code {
    private SiteDataModel sitedata;
    private TagModel tag;
    private BlogModel blog;

    protected override async Task OnInitializedAsync()
    {
    // ...
    }

    // 追加
    private async Task TagSelected(string tagId)
    {
        try
        {
            blog = await Http.GetFromJsonAsync<BlogModel>($"MicroCMS/BlogList/{tagId}");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
}
appsettings.json
// 抜粋
  "MicroCMS": {
    // ...
    "QueryParam": {
      "SiteData": "?fields=title",
      "TagList": "?fields=id,name",
      "BlogList": "?fields=title,publishedAt,tag.id,tag.name",
      // 追加
      "BlogListByTag": "?filters=tag[equals]#id"
    }
  }
MicroCMSController.cs
// 抜粋
namespace BlazorBlog.Server.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class MicroCMSController : ControllerBase
    {
    // ...
        // 追加
        [Route("BlogList/{tagId}")]
        public async Task<BlogModel> GetBlogListByTag(string tagId)
        {
            string url = apiSettings.BaseUrl + apiSettings.Endpoints.BlogList
                + "?" + apiSettings.QueryParam.BlogList
                + "&" + apiSettings.QueryParam.BlogListByTag.Replace("#id", tagId);
            string apikey = apiSettings.ApiKey;

            BlogModel result = await Fetch<BlogModel>(url, apikey);

            return result;
        }
    // ...
    }
}

実行してみます。MicroCMSには3つのタグが登録してあり、

  • 「数学」⇒使用していない
  • 「ブログ」⇒テスト1,テスト2,テスト5
  • 「Minecraft」⇒テスト3、テスト4

となっています。上記のとおりにフィルタリングされることを確認します。

「数学」を押すと

「Minecraft」を押すと

「ブログ」を押すと

と、正しくフィルタリングできました。
なんだかブログらしくなってきました。

取得データもちゃんと必要な項目だけになってます。(「ブログ」クリック時)

ブログ記事ページ作成

ブログ一覧の各タイトルをクリックするとコンテンツページに飛ぶようにつくります。

タイトルをリンク化

Shared/BlogCard.razor
<div class="row my-2 d-flex justify-content-center">
    <div class="col-12 col-md-8 text-truncate cardbox">
        <div class="m-3">
	    <!-- pタグからaタグに変更 -->
            <a href="blog/@blogId">@title</a>
            <div>Tag:@tag</div>
            <div>Publish:@publishedAt.ToLocalTime().ToString("yyyy/MM/dd")</div>
        </div>
    </div>
</div>

@code {
    // 追加
    [Parameter]
    public string blogId { get; set; }

    [Parameter]
    public string title { get; set; }

    [Parameter]
    public string tag { get; set; }

    [Parameter]
    public DateTime publishedAt { get; set; }
}

設定値、アクションの追加

コンテンツIDがあれば本文データを取得可能です。
MicroCMS APIにはblog/コンテンツIDにリクエストを送ると、指定したコンテンツIDを持つコンテンツのみを返す機能があります。(もちろんクエリパラメータで項目を絞ることは可能です)

appsettings.json
// 抜粋
    "QueryParam": {
      "SiteData": "?fields=title",
      "TagList": "?fields=id,name",
      "BlogList": "?fields=id,title,publishedAt,tag.id,tag.name",
      "BlogListByTag": "?filters=tag[equals]#id",
      // 追加
      "BlogContents": "?fields=title,tag.name,publishedAt,body"
    }
MicroCMSSettingModel
// 抜粋
namespace BlazorBlog.Server
{
// ...
    public class MicroCMSQueryParamSettingModel
    {
        public string SiteData { get; set; }

        public string TagList { get; set; }

        public string BlogList { get; set; }

        public string BlogListByTag { get; set; }

        // 追加
        public string BlogContents { get; set; }
    }
}
MicroCMSController.cs
// 抜粋
namespace BlazorBlog.Server.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class MicroCMSController : ControllerBase
    {
    // ...
        // 追加
        [Route("BlogContents/{blogId}")]
        public async Task<BlogContents> GetBlogContents(string blogId)
        {
            string url = apiSettings.BaseUrl + apiSettings.Endpoints.BlogContents.Replace("#id", blogId)
                + "?" + apiSettings.QueryParam.BlogContents;
            string apikey = apiSettings.ApiKey;

            BlogContents result = await Fetch<BlogContents>(url, apikey);

            return result;
        }
    }

ブログ記事ページ

スタイリングは後回しで。

BlogPage.razor
@page "/blog/{blogId}"
@using BlazorBlog.Shared.MicroCMS
@inject HttpClient Http

@if (contents == null)
{
    <div class="d-flex justify-content-center">
        <div class="spinner-border" style="width: 3rem; height: 3rem;" role="status">
            <span class="visually-hidden">Loading...</span>
        </div>
    </div>
}
else
{
    <h3>@contents.Title</h3>
    <p>Tag:@contents.Tag.Name</p>
    <p>Publish:@contents.PublishedAt.ToLocalTime().ToString("yyyy/MM/dd")</p>
    <div>
        @((MarkupString)contents.Body)
    </div>
}

@code {
    [Parameter]
    public string blogId { get; set; }

    private BlogContents contents;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            contents = await Http.GetFromJsonAsync<BlogContents>($"MicroCMS/BlogContents/{blogId}");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
}

HTMLをそのまま、文字列としてHTMLが表示されてしまします。
正しく表示させるには、MarkupStringにキャストする必要があります👇

@((MarkupString)contents.Body)

実行


   👇

めでたく表示できました。

次回

  • ブログ記事ページに機能追加、スタイリング
    • 一覧に戻るリンク
    • 次の記事/前の記事リンク
    • シンタックスハイライト(Highlight.js)

Discussion