プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2019/07/10

[ASP.NET Core] Flags 属性を持った Enum をバインディングする

event_note2019/07/10 9:55

Flags 属性を持った Enum をチェックボックスにバインディングしたいなと思ったのですが、現時点の ASP.NET Core には そのような機能はありません。

しかし、以下のライブラリを使うことで簡単にできたので、紹介します。

インストール

ライブラリの種類はいろいろありますが、Flags 属性の Enum をバインディングするのに必要なのは Sakura.AspNetCore.Mvc.TagHelpers です。
これを NuGet でインストールします。

準備

ミドルウェアの追加

Flags 属性の Enum をバインディングするには、ミドルウェアに FlagsEnumModelBinderProvider を追加する必要があるようです。

上記で説明されている通り、Startup.cs を以下のように変更します。

// In startup.cs

public void ConfigurationServices(IServiceCollection services)
{
  // Other configuration code
  services.AddMvc(options => 
  {
    // Using the followint code to add the new binder
    options.AddFlagsEnumModelBinderProvider();
  });
}

タグヘルパーの有効化

タグヘルパーを有効にするために、_ViewImports.cs に以下を追加します。

@addTagHelper *, Sakura.AspNetCore.Mvc.TagHelpers

これについては以下で解説されています。

View

タグヘルパーについては以下で解説されています。

上記のコードをそのまま転用しますが、以下のようなモデルが定義されていた場合、

// backend code
[Flags]
public enum Features
{
  None = 0x0,
  CanRead = 0x1,
  CanWrite = 0x2,
  CanSeek = 0x4
}

public class Stream
{
  public Features Features { get; set; }
}

View で以下のように記述するだけでバインディングできます。

<!-- In MVC view page -->
@model Stream
<label>
  <input type="checkbox" asp-enum-flag-for="Features" asp-enum-flag-value="Features.CanSeek"> CanSeek
</label>

しかし、私の場合は Razor がエラーを吐いていたので、input の最後に終了を示すスラッシュ / を追加しました。

尚、上記のコードは Razor によって以下のように展開されるようです。

<label>
  <input type="checkbox" name="Features" value="CanSeek" checked="checked"> CanSeek
</label>