WebSurfer's Home

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

ASP.NET MVC5 で boorstrap datepicker 利用

by WebSurfer 2021年8月16日 14:14

ASP.NET MVC5 で Controller で Model に日付を設定して View に渡し、Html ヘルパーの EditorFor を使ってテキストボックスにその日付を表示したとします。そのテキストボックスに bootstrap datepicker を適用してカレンダーを表示した際、 Model に設定した日付がカレンダー上で選択されるようにする方法を備忘録として残しておきます。

boorstrap datepicker

自動的に Model に設定した日付が bootstrap datepicker のカレンダー上で選択されて表示されると思っていたのですが、何もしないと Model に設定した日付ではなくてブラウザに表示された当日の日付になってしまいます。

その原因は、例えば new DateTime(2021, 3, 23) としてそれを Model に設定すると、テキストボックスに 2021/03/23 0:00:00 と表示される(当該 html input 要素で value="2021/06/24 0:00:00" となる)、即ち 0:00:00 部分が bootstrap datepicker にとって余計で日付を判定できなかったからのようです。

なので、当該 html input 要素で value="2021/03/23" となるようにすれば bootstrap datepicker のカレンダー上もその日付を選択して表示するようになります。

そのためには、Model の当該プロパティに DisplayFormatAttribute 属性を付与してやります。具体的には以下のようにします。その結果が上の画像です。

(1) Model

using System;
using System.ComponentModel.DataAnnotations;

namespace Mvc5App.Models
{
    public class BootstrapDatepickerModel
    {
        [Display(Name = "日付")]
        [DisplayFormat(ApplyFormatInEditMode = true,
            DataFormatString = "{0:yyyy/MM/dd}")]
        public DateTime? OrderDate { get; set; }
    }
}

Visual Studio 2019 のテンプレートを使って ASP.NET Web アプリを作ると、Bootstrap.js と Bootstrap.css が自動的にプロジェクトに含まれますが、bootstrap datepicker はその中には含まれていませんので注意してください。別途 github のサイト uxsolutions/bootstrap-datepicker 等からダウンロードする必要があります。この記事では、この記事を書いている時点での最新版 1.9.0 を使用しました。

また、bootstrap datepicker は Boorstrap 本体のバージョン 4 以上には対応してないそうです (Bootstrap 4 および 5 でも使う方法があるそうですが未検証・未確認です)。この記事で使った Bootstrap のバージョンは、MVC5 アプリのテンプレートに含まれている v3.4.1 です。

ご参考に View と Controller / Action Metod のコードも以下に載せておきます。

(2) View

@section Scripts { ... } 内の link 要素、script 要素による外部 bootstrap datepicker の js ファイル、css ファイルへの参照に注目してください。

@model Mvc5App.Models.BootstrapDatepickerModel

@{
    ViewBag.Title = "Datepicker";
}

<h2>Datepicker</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>BootstrapDatepickerModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.OrderDate,
                htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.OrderDate,
                    new { htmlAttributes = new { @class = "form-control datepicker" } })
                @Html.ValidationMessageFor(model => model.OrderDate, "",
                    new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    <link href="~/Content/bootstrap-datepicker.css" rel="stylesheet" />
    <script src="~/Scripts/bootstrap-datepicker.js"></script>
    <script src="~/Scripts/locales/bootstrap-datepicker.ja.min.js"></script>

    @Scripts.Render("~/bundles/jqueryval")

    <script type="text/javascript">
        //<![CDATA[
        $(function () {
            $('.datepicker').datepicker({
                format: 'yyyy/mm/dd',
                language: 'ja'
            });
        })
        //]]>
    </script>
}

(3) Controller / Action Method

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Mvc5App.DAL;
using System.Data.Entity;
using System.Web;
using System.Threading;
using System.Threading.Tasks;
using Mvc5App.Models;
using System;

namespace Mvc5App.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Datepicker()
        {
            var model = new BootstrapDatepickerModel();
            model.OrderDate = new DateTime(2021, 3, 23);

            // model.OrderDate が null なら今日の日付を表示する
            if (model.OrderDate == null)
            {
                model.OrderDate = DateTime.Now;
            }

            return View(model);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Datepicker(BootstrapDatepickerModel model)
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");

            }

            return View(model);
        }
    }
}

Tags: , , ,

MVC

カスタム Html ヘルパーで IUrlHelper を利用 (CORE)

by WebSurfer 2021年4月17日 12:27

先の記事「カスタム Tag ヘルパーで IUrlHelper を利用 (CORE)」のカスタム html ヘルパー版です。加えて、比較のために、同等な機能を部分ビューで実装する方法も書いてみました。

カスタム Html ヘルパー

カスタム html ヘルパーは ASP.NET Core MVC では推奨されてないのか、Microsoft のドキュメントには作成方法の記事が見当たりませんでした。でも、使うことは可能なようですので、先の記事と同じく内部で IUrlHelper を利用する html ヘルパーを書いてみました。

.NET Framework 版の MVC5 アプリでは、カスタム html ヘルパーの中で以下のコードのようにして UrlHelper オブジェクトを取得できます。

using System.Web;
using System.Web.Mvc;

namespace Mvc5App.HtmlHelpers
{
    public static class Mvc5AppHelpers
    {
        public static IHtmlString AchorTag(this HtmlHelper helper,
                                           string contoller, 
                                           string action, 
                                           string text)
        {
            var urlHepler = new UrlHelper(helper.ViewContext.RequestContext);
            var path = urlHepler.Action(action, contoller);

            return MvcHtmlString.Create(
                $"<a href=\"{path}\">{HttpUtility.HtmlEncode(text)}</a>");
        }
    }
}

Core 3.1 / 5.0 版の MVC アプリでは、先の記事「カスタム Tag ヘルパーで IUrlHelper を利用 (CORE)」に書きましたように、ASP.NET Core 組み込み��� DI 機能を利用してコンストラクタ経由で IUrlHelperFactory と IActionContextAccessor を DI し、IUrlHelperFactory の GetUrlHelper(ActionContext) メソッドを使って IUrlHelper オブジェクトを取得しました。・・・よく調べてみると、LinkGenerator API を取得して利用する方が良さそうです。LinkGenerator を使ったカスタム html ヘルパーは下の「2021/4/18 追記」に書きます。

しかし、カスタム html ヘルパーで上のコード例のように拡張メソッドを使う場合は、静的クラス内に静的メソッドを配置することになりますので、コンストラクタ経由での DI ができません。

そこをどうするかですが、HttpContextRequestServices プロパティ から IServiceProvider(サービスコンテナーへのアクセスを提供)を取得できますので、それを使って IUrlHelperFactory と IActionContextAccessor のインスタンスを取得できるようです。

HttpContent は IHtmlHelper.ViewContext プロパティから取得できる ViewContext の HttpContext プロパティで取得できます。

それらを利用したカスタム html ヘルパーを書いてみました。以下をコードを見てください。IServiceProvider から IUrlHelperFactory と IActionContextAccessor のインスタンスを取得し、それらを使って IUrlHelper オブジェクトを取得してその Action メソッドにより url パスの文字列を取得しています。(引数の AnchorTagData クラスの定義は先の記事を見てください)

using System;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using MvcCoreApp.Models;

namespace MvcCoreApp.HtmlHelpers
{
    public static class MvcCoreAppHtmlHelpers
    {
        // 静的クラスなのでコンストラクタ経由での DI はできない。
        // IServiceProvider を取得してそれから IServiceCollection に登録されている
        // IUrlHelperFactory と IActionContextAccessor のインスタンスを取得
        public static IHtmlContent AchorTag(this IHtmlHelper helper,
                                            IEnumerable<AnchorTagData> Info)
        {
            IServiceProvider provider = helper.ViewContext.HttpContext.RequestServices;

            var urlFactory = provider.GetRequiredService<IUrlHelperFactory>();

            var actionAccessor = provider.GetRequiredService<IActionContextAccessor>();

            var urlHelper = urlFactory.GetUrlHelper(actionAccessor.ActionContext);

            var content = "";
            foreach (var data in Info)
            {
                var path = urlHelper.Action(
                    action: data.Action,
                    controller: data.Controller);
                content += "<li class=\"nav-item\">" +
                    $"<a class=\"nav-link text-dark\" href=\"{path}\">" +
                    $"{HttpUtility.HtmlEncode(data.Text)}</a>" +
                    "</li>\r\n";
            }

            var output = $"<ul class=\"navbar-nav flex-grow-1\">{content}</ul>";

            return new HtmlString(output);
        }
    }
}

先のカスタム tag ヘルパーの記事と同様に、startup.cs での IActionContextAccessor のサービスへの登録は必要ですので忘れないようにしてください。具体的なコードは先の記事を見てください。

_Layout.cshtml に、上に定義した html ヘルパーが使えるように using 句を記述し、html ヘルパーに渡すモデルを初期化します。さらに、html ヘルパーを表示する場所に @Html.AchorTag(model) というコードを書きます。以下のような感じ。

@using MvcCoreApp.HtmlHelpers;

@{
    IEnumerable<AnchorTagData> model =
        new List<AnchorTagData> {
            new AnchorTagData { Controller="Home", Action="Index", Text="Home" },
            new AnchorTagData { Controller="Home", Action="Privacy", Text="Privacy" },
            new AnchorTagData { Controller="People", Action="Index", Text="People" },
            new AnchorTagData { Controller="Messages", Action="Index", Text="Messages" },
            new AnchorTagData { Controller="Validation", Action="Create", Text="Validation" },
            new AnchorTagData { Controller="Upload", Action="Index", Text="FileUpload" },
            new AnchorTagData { Controller="Products", Action="Index", Text="Products" },
            new AnchorTagData { Controller="Ajax", Action="Index", Text="Ajax" },
            new AnchorTagData { Controller="IHttpClientFactory", Action="Index", Text="HttpClient" }};
}

// ・・・中略・・・

@Html.AchorTag(model)

// ・・・中略・・・

以上により、_Layout.cshtml に書いた @Html.AchorTag(model) というコードの部分に上の画像の赤枠で示したリンクが表示されます。

部分ビューで実装

次に、先の記事のカスタム tag ヘルパー、この記事のカスタム html ヘルパーと同等の機能を部分ビューを使って実装してみます。

ASP.NET Core の組み込みタグヘルパーのアンカータグヘルパーを以下のように部分ビュー _Navi.cshtml(名前は任意)に組み込みます。

@using MvcCoreApp.Models
@using System.Web;
@model IEnumerable<AnchorTagData>

<ul class="navbar-nav flex-grow-1">
    @foreach (var data in Model)
    {
        <li class="nav-item">
            <a class="nav-link text-dark"
               asp-controller=@data.Controller
               asp-action=@data.Action>
                @HttpUtility.HtmlEncode(data.Text)
            </a>
        </li>
    }
</ul>

上記部分ビューを、部分タグヘルパーを使って、以下のように _Layout.cshtml に配置します。

@{
    IEnumerable<AnchorTagData> model = // 省略 (上と同じ)
}

// ・・・中略・・・

<partial name="_Navi.cshtml" model="model" />

// ・・・中略・・・

これだけで、先の記事のカスタム tag ヘルパー、この記事のカスタム html ヘルパーと同様に、上の画像の赤枠で示したリンクが表示されます。この記事で書いた程度のことを実装するなら部分ビューを使うのが一番シンプルでよさそうだと思いました


-------- 2021/4/18 追記 (LinkGenerator 利用) --------

上のカスタム html ヘルパーのコードは、IUrlHelperFactory と IActionContextAccessor をサービスコンテナーから取得し、 IUrlHelperFactory.GetUrlHelper(ActionContext) メソッドを使って IUrlHelper オブジェクトを取得して利用しています。

しかし、後でよく調べたら、Microsoft のドキュメント「URL 生成の概念」に書いてあるように LinkGenerator API を取得して利用する方が良さそうと思いました。

というわけで、LinkGenerator を使ったカスタム html ヘルパーのコードを以下に書きます。IActionContextAccessor のサービスへの登録は不要ですしコードも簡単になります。LinkGenerator はサービスコンテナに登録済みのようで、以下のようにするだけで取得できます。

using System;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Web;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using MvcCoreApp.Models;

// LinkGenarator の利用
using Microsoft.AspNetCore.Routing;

namespace MvcCoreApp.HtmlHelpers
{
    public static class MvcCoreAppHtmlHelpers
    {
        // 静的クラスなのでコンストラクタ経由での DI はできない。
        // IServiceProvider を取得してそれから IServiceCollection に登録されている
        // LinkGenarator のインスタンスを取得して利用する
        public static IHtmlContent AchorTag(this IHtmlHelper helper,
                                            IEnumerable<AnchorTagData> Info)
        {
            IServiceProvider provider = helper.ViewContext.HttpContext.RequestServices;

            var linkGenerator = provider.GetRequiredService<LinkGenerator>();

            var content = "";
            foreach (var data in Info)
            {
                var path = linkGenerator.GetPathByAction(
                    action: data.Action,
                    controller: data.Controller);
                content += "<li class=\"nav-item\">" +
                    $"<a class=\"nav-link text-dark\" href=\"{path}\">" +
                    $"{HttpUtility.HtmlEncode(data.Text)}</a>" +
                    "</li>\r\n";
            }

            var output = $"<ul class=\"navbar-nav flex-grow-1\">{content}</ul>";

            return new HtmlString(output);
        }
    }
}

Tags: , , ,

CORE

カスタム Tag ヘルパーで IUrlHelper を利用 (CORE)

by WebSurfer 2021年4月16日 15:18

ASP.NET Core 3.1 / 5.0 MVC アプリのカスタム Tag ヘルパーで url の文字列を生成したいということがあると思います。そのために IUrlHelper インターフェイスを利用する方法を書きます。(IUrlHelper インターフェイスは .NET Framework 版の MVC5 で使われる UrlHelper クラスに相当します)

カスタム Tag ヘルパー

上の画像の赤枠の部分は、Visual Studio のテンプレートで生成する ASP.NET Core MVC プロジェクトで自動生成される _Layout.cshtml では組み込みのアンカータグヘルパーを並べてリンクを作成していますが、これをカスタム tag ヘルパーを使って表示してみます。

ASP.NET Core MVC でもカスタム html ヘルパーは使えます。ただし、静的クラス / 静的メソッドになるので ASP.NET Core 組み込みのコンストラクタ経由での DI 機能が使えません。そのためか、カスタム html ヘルパーは Core では推奨されてないような感じで、Mocrosoft のドキュメントにも見当たりません。というわけで、この記事ではカスタム html ヘルパーではなくてカスタム tag ヘルパーで実装してみました。

(カスタム html ヘルパーまたは部分ビュー + 組み込み tag ヘルパー使ってもこの記事と同様な機能は実装できます。それらについては別の記事「カスタム Html ヘルパーで IUrlHelper を利用 (CORE)」に書きました。やってみた結果、この記事で書いた機能程度のことを実装するなら部分ビュー + 組み込み tag ヘルパーを使うのが一番シンプルでよさそうだと思いました)

カスタム tag ヘルパーの作成方法の概要は Microsoft のドキュメント「ASP.NET Core のタグ ヘルパー作成」の記事が参考になると思います。

その記事でほとんど用は足りると思いますが、もし、カスタム tag ヘルパー内でコントローラーとアクションメソッドの名前から url パスを作成する必要があると問題です。例えば、以下のようにアクションメソッドに [HttpPost("/fileupload")] というような属性が付与されているような場合、単純に名前から文字列連結で /upload/index というパスを組み立てて a タグに href="/upload/index" と設定したりすると HTTP 404 Not Found となってしまいま��。

namespace MvcCoreApp.Controllers
{
    public class UploadController : Controller
    {
        [HttpGet("/fileupload")]
        public IActionResult Index()
        {
            return View();
        }

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

ちなみに、組み込みのアンカータグヘルパーを使って asp-controller="Upload" asp-action="Index" とすると、それから生成される a タグには href="/fileupload" と設定されます。

そのようにならないと困るので、tag ヘルパー内で Url.Action("index", "upload"); というように url ヘルパーを使ってパスを取得したいということになると思います。そのために IUrlHelper オブジェクトを tag ヘルパーのコードの中でどのように取得するかがこの記事の課題です。

.NET Framework 版の MVC5 アプリでは、カスタム html ヘルパーの中で以下のコードのようにして url ヘルパーのオブジェクトを取得できます。

using System.Web;
using System.Web.Mvc;

namespace Mvc5App.HtmlHelpers
{
    public static class Mvc5AppHelpers
    {
        public static IHtmlString AchorTag(this HtmlHelper helper,
                                           string contoller, 
                                           string action, 
                                           string text)
        {
            var urlHepler = new UrlHelper(helper.ViewContext.RequestContext);
            var path = urlHepler.Action(action, contoller);

            return MvcHtmlString.Create(
                $"<a href=\"{path}\">{HttpUtility.HtmlEncode(text)}</a>");
        }
    }
}

Core 版の MVC アプリではもうちょっと頑張ってコードを書かないと url ヘルパーのオブジェクトを取得できません。前置きが長きなってしまいましたが、以下にその方法を書きます。

基本的には、IUrlHelperFactory インターフェイスIUrlHelperFactory.GetUrlHelper(ActionContext) メソッドを使って IUrlHelper オブジェクトを取得することになります。・・・と思いましたが、LinkGenerator API を取得して利用する方が良さそうです。LinkGenerator を使ったカスタム tag ヘルパーは下の「2021/4/18 追記」に書きます。

IUrlHelperFactory は、Visual Studio のテンプレートで作る ASP.NET Core 3.1 / 5.0 MVC アプリのプロジェクトにはデフォルトで IServiceCollection(DI コンテナ)に登録されているようで、tag ヘルパーのコンストラクタ経由で DI できます。

IUrlHelper オブジェクトを生成するためにIUrlHelperFactory.GetUrlHelper(ActionContext) メソッドを使いますが、その引数の「現在の要求に関連付けられている ActionContext」をどのように取得するかが問題でした。調べてみると、IActionContextAccessor を IServiceCollection に登録してコンストラクタ経由で DI できるようにし、その ActionContext プロパティを使うということのようです。

まず、IActionContextAccessor をサービスに登録します。具体的には、startup.cs の ConfigureServices メソッドで以下のようにします。

// 追加
using Microsoft.AspNetCore.Mvc.Infrastructure;

namespace MvcCoreApp
{
    public class Startup
    {

        // ・・・中略・・・

        public void ConfigureServices(IServiceCollection services)
        {
            // 追加
            services.AddSingleton<IActionContextAccessor, 
                                  ActionContextAccessor>();

        // ・・・中略・・・
}

カスタム tag ヘルパーは、Visual Studio のテンプレートで作った ASP.NET Core MVC アプリのプロジェクトのルートに TagHelpers という名前のフォルダを作って実装しました。コードは以下の通りで、コンストラクタ経由で IUrlHelperFactory と IActionContextAccessor が DI されるようにしています。

using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.TagHelpers;
using MvcCoreApp.Models;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using System.Web;

namespace MvcCoreApp.TagHelpers
{
    public class NaviTagHelper : TagHelper
    {
        private readonly IUrlHelperFactory _urlHelperFactory;
        private readonly IActionContextAccessor _actionContextAccessor;

        public NaviTagHelper(IUrlHelperFactory urlHelperFactory,
                             IActionContextAccessor actionContextAccessor)
        {
            _urlHelperFactory = urlHelperFactory;
            _actionContextAccessor = actionContextAccessor;
        }

        public IEnumerable<AnchorTagData> Info { get; set; }

        public override void Process(TagHelperContext context, 
                                     TagHelperOutput output)
        {
            var urlHelper = _urlHelperFactory.GetUrlHelper(
                                _actionContextAccessor.ActionContext);

            output.TagName = "ul";
            var @class = "navbar-nav flex-grow-1";
            output.Attributes.SetAttribute("class", @class);
            var content = "";
            foreach (var data in Info)
            {
                var path = urlHelper.Action(
                    action: data.Action,
                    controller: data.Controller);
                content += "<li class=\"nav-item\">" +
                    $"<a class=\"nav-link text-dark\" href=\"{path}\">" +
                    $"{HttpUtility.HtmlEncode(data.Text)}</a>" +
                    "</li>\r\n";
            }
            output.Content.SetHtmlContent(content);
        }
    }
}

上のカスタム tag ヘルパーで使っているモデル AnchorTagData クラスの定義は以下の通りです。

namespace MvcCoreApp.Models
{
    public class AnchorTagData
    {
        public string Controller { get; set; }
        public string Action { get; set; }
        public string Text { get; set; }
    }

_Layout.cshtml に、上に定義した tag ヘルパーが使えるように addTagHelper ディレクティブを記述し、tag に渡すモデルを初期化します。さらに、tag ヘルパーを表示する場所に <navi info="model"></navi> というタグを配置します。以下のような感じ。

@addTagHelper MvcCoreApp.TagHelpers.NaviTagHelper, MvcCoreApp

@{
    IEnumerable<AnchorTagData> model =
        new List<AnchorTagData> {
            new AnchorTagData { Controller="Home", Action="Index", Text="Home" },
            new AnchorTagData { Controller="Home", Action="Privacy", Text="Privacy" },
            new AnchorTagData { Controller="People", Action="Index", Text="People" },
            new AnchorTagData { Controller="Messages", Action="Index", Text="Messages" },
            new AnchorTagData { Controller="Validation", Action="Create", Text="Validation" },
            new AnchorTagData { Controller="Upload", Action="Index", Text="FileUpload" },
            new AnchorTagData { Controller="Products", Action="Index", Text="Products" },
            new AnchorTagData { Controller="Ajax", Action="Index", Text="Ajax" },
            new AnchorTagData { Controller="IHttpClientFactory", Action="Index", Text="HttpClient" }};
}

// ・・・中略・・・

<navi info="model"></navi>

// ・・・中略・・・

以上により、_Layout.cshtml に配置した <navi info="model"></navi> の部分に、上の画像の赤枠で示したリンクが表示されます。FileUpload へのリンク先も正しく href="/fileupload" となります。


-------- 2021/4/18 追記 (LinkGenerator 利用) --------

上のカスタム tag ヘルパーのコードは、IUrlHelperFactory と IActionContextAccessor を DI により取得し、 IUrlHelperFactory.GetUrlHelper(ActionContext) メソッドを使って IUrlHelper オブジェクトを取得して利用しています。

しかし、後でよく調べたら、Microsoft のドキュメント「URL 生成の概念」に書いてあるように LinkGenerator API を取得して利用する方が良さそうと思いました。

というわけで、LinkGenerator 使ったカスタム tag ヘルパーのコードを以下に書きます。IActionContextAccessor のサービスへの登録は不要ですしコードも簡単になります。LinkGenerator はサービスコンテナに登録済みのようで、以下のように引数に含めるだけで DI できます。

using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.TagHelpers;
using MvcCoreApp.Models;
using System.Web;

// LinkGenarator の利用
using Microsoft.AspNetCore.Routing;

namespace MvcCoreApp.TagHelpers
{
    public class NaviTagHelper : TagHelper
    {
        private readonly LinkGenerator _linkGenerator;

        public NaviTagHelper(LinkGenerator linkGenerator)
        {
            _linkGenerator = linkGenerator;
        }

        public IEnumerable<AnchorTagData> Info { get; set; }

        public override void Process(TagHelperContext context, 
                                     TagHelperOutput output)
        {
            output.TagName = "ul";
            var @class = "navbar-nav flex-grow-1";
            output.Attributes.SetAttribute("class", @class);
            var content = "";
            foreach (var data in Info)
            {
                var path = _linkGenerator.GetPathByAction(
                     action: data.Action,
                     controller: data.Controller);
                content += "<li class=\"nav-item\">" +
                    $"<a class=\"nav-link text-dark\" href=\"{path}\">" +
                    $"{HttpUtility.HtmlEncode(data.Text)}</a>" +
                    "</li>\r\n";
            }
            output.Content.SetHtmlContent(content);
        }
    }
}

Tags: , , ,

CORE

About this blog

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

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar