こんにちは、システム開発部のながたにです。
今、ASP.NET core を使用した開発をしておりまして、Entity Framework Core 3 を使用しているのですが、その Entity Framework Core で DB から取得したデータを ボタンをクリックすることで CSV ファイルとしてダウンロードできる機能を実装しました。

今回はその実装の方法について、紹介させていただきます。

プロジェクトを作成する

まずは ASP.NET Core 3 MVC のプロジェクトを作成します。

1. Visual Studio 2019 を開きます
2.「新しいプロジェクトの作成」を選択します

3.「ASP.NET Core Web アプリケーション」を選択します

4. プロジェクト名を任意で入力して作成します(今回は CsvDownload としました)

これでプロジェクトが作成されました。

ASP.NET Core 3 で Entity Framework Core 3 を使用できるようにする

公式のドキュメントにチュートリアルがありますので、こちらを参考にしながら、Entity Framework Core 3 を使用できるように設定してください。
あくまで CSV ファイルのダウンロードの実装方法を紹介することが目的ですので、今回は割愛させていただきます。

データを用意する

まずは、CSVファイル をダウンロードするデータを用意する必要があるので、Entity Framework Core 3 を使用してテーブルを作成し、データを挿入していきましょう。

■ テーブルを用意する
今回は Users テーブルを用意します。
カラムは

Id :プライマリーキー
Name:名前
Age:年齢
Height:身長
Weight:体重

にしましょう。

■ User モデルを作成する
次に上記テーブルを作成するため、 User モデルを用意します。
Models フォルダ以下に User.cs を作成します。

作成した User.cs を開いて、下記コードのようにカラムのプロパティを定義しましょう。

namespace CsvDownload.Models
{
    /// <summary>
    /// Users テーブルのモデルクラス
    /// </summary>
    public class User
    {
        public int Id { get; set; } // ID プライマリーキー
        public string Name { get; set; } // 名前
        public int Age { get; set; } // 年齢
        public float Height { get; set; } // 身長
        public float Weight { get; set; } // 体重
    }
}

■ コンテキストファイルを作成する
次に、DB と Model の接続を行うためのコンテキストファイルを用意します。
今回は プロジェクト下にContext.cs を作成しました。

作成した Context.cs に以下のようにコードを記述します。

using CsvDownload.Models;
using Microsoft.EntityFrameworkCore;

namespace CsvDownload
{
    /// <summary>
    /// DB との接続を行うためのコンテキストクラス
    /// </summary>
    public class Context : DbContext
    {
        public Context(DbContextOptions<Context> options) : base(options)
        {
            
        }

        // モデルをセットする
        public DbSet<User> Users { get; set; } // プロパティ名がテーブル名になる(この場合だと Users テーブルが作成される)
    }
}

■ 作成したコンテキストファイルをDI コンテナーに追加してEntity Framework Core として使用できるようにする
次に、Startup.cs の ConfigureServices メソッドに 先ほど作成したコンテキストを追加します

services.AddDbContext<Context>(options =>
        options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=CsvDownload;Trusted_Connection=True;MultipleActiveResultSets=true"));services.AddDbContext&amp;lt;Context&amp;gt;(options =&amp;gt; options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=CsvDownload;Trusted_Connection=True;MultipleActiveResultSets=true"));

※DBの接続文字列(UseSqlServerの部分)は任意で入力してください。特にこだわりがなければ、上記の記述でLocal環境にCsvDownload DBが作成されます。

■ マイグレーションファイルを作成する
これで、準備が整いましたので、次に Users テーブルを作成するためのマイグレーションファイルを作成します。
こちらはコンソールからコマンドを実行するだけで簡単に作成ができます。

[ツール] から [パッケージマネージャーコンソール] を開く

コンソールを開いたら以下のコマンドを実行する

PM> Add-Migration CreateTableUsers

※Add-Migration の後ろはマイグレーション名です。任意で設定してください。

これでMigration フォルダが作成されその中にマイグレーションファイルとマイグレーションのスナップショットファイルが作成されます。

■ マイグレーションを実行する
マイグレーションファイルを作成したときと同様、コンソールでコマンドを実行します。
マイグレーションを実行するコマンドは以下となります。

PM> Update-Database

成功すると DB が作成され Users テーブルが作成されます。
※[表示] ⇒ [SQL Server オブジェクト エクスプローラー] から確認ができます。

■ データを挿入する
これでテーブルが作成されましたので、あとは適当にデータを挿入してください。
※ [SQL Server オブジェクト エクスプローラー]からテーブルを選択して、[データを表示] をクリックすると テーブル内のデータが表示されるので、そこから直接挿入することが可能です。


CSV ダウンロード機能を実装する

お待たせしました… ここからがやっと本題になります。
先ほど挿入したUsers テーブルのデータをCSVダウンロードできるようにしましょう。

■ CsvHelper パッケージをインストールする
まず、CSV形式でダウンロードするために必要な、CsvHelper というパッケージをインストールします
[ツール] ⇒ [NuGet パッケージマネージャー] ⇒ [ソリューションの NuGet パッケージの管理] の順に選択します

CsvHelper と 入力すると [CsvHelper] が出てくるので、選択してインストールします

■ CSVダウンロードボタンを設置する
今回はデフォルトで用意されている Home 画面にボタンを設置しましょう。
[View] フォルダ ⇒ [Home] ⇒ [index.cshtml] を開く

以下のように View ファイルに CSV ダウンロードボタンを a タグで追加しましょう

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>

    @*CSV ダウンロードボタンを追加する*@
    <a asp-action="CsvDownload" class="btn btn-primary">ユーザー CSVダウンロード</a>

</div>

※a タグに asp-action で Controller のアクションを指定することで、自動的に href 属性を補完してくれます。

■ CSV ダウンロード 処理を実装する
ボタンを設置しましたので、最後にCSV ダウンロード処理を実装します。
上記で Action を CsvDownload としましたので、HomeController に CsvDownload アクション を追加して、その中でCSVダウンロード処理を実装していきましょう。

[Controllers] フォルダ ⇒ [HomeController.cs] を開く
以下のように CsvDownload アクションを追加します。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using CsvDownload.Models;
// Usingを追加する
using System.IO;
using CsvHelper;
using System.Globalization;

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

        public HomeController(ILogger<HomeController> logger, Context context)
        {
            _logger = logger;

            // コンテキストをコンストラクタで定義する
            _context = context;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }

        /// <summary>
        /// CSVダウンロード
        /// </summary>
        /// <returns>CSVファイル</returns>
        public FileContentResult CsvDownload()
        {
            // CSV ファイル名
            string csvFileName = "ユーザーデータ.csv";

            // メモリを確保する
            using (var memory = new MemoryStream())
            using (var writer = new StreamWriter(memory))
            using (var csv = new CsvWriter(writer, new CultureInfo(0x0411, false)))
            {
                // コンテキストを使用してUsers テーブルのデータを取得する
                List<User> users = _context.Users.ToList();

                // 取得したデータを記録する
                csv.WriteRecords(users);
                writer.Flush(); 

                // CSVファイルとして出力する
                return File(memory.ToArray(), "text/csv", csvFileName);
            }
        }
    }
}

■ 動作確認
これで、一通り実装ができましたので、最後に動作確認をしましょう。
ビルドしてホーム画面を開きます。
[ユーザー CSVダウンロード] ボタンが表示されているので、これをクリックするとCSVファイルがダウンロードされます。

ファイルを開くと以下のようにUsers テーブルのデータが登録されていることが確認できます。

これでCSVファイルのダウンロードができるようになりました。
以上が大まかな処理の流れとなります。

備考

■ 一部カラムを取得しないようにしたい
ID のようにCSVダウンロードで必要ないカラムを出力したくない場合があると思います。
そんな時は Model クラスの 出力したくないカラム(プロパティ)に [ignore] 属性(using CsvHelper.Configuration.Attributes; を追加する必要あり)を付与することで対応が可能です。

using CsvHelper.Configuration.Attributes;

namespace CsvDownload.Models
{
    /// <summary>
    /// Users テーブルのモデルクラス
    /// </summary>
    public class User
    {
        [Ignore]
        public int Id { get; set; } // ID プライマリーキー

        public string Name { get; set; } // 名前

        public int Age { get; set; } // 年齢

        public float Height { get; set; } // 身長

        public float Weight { get; set; } // 体重
    }
}

これでファイルをダウンロードするとIDカラムが出力されないようになります。

■ ヘッダー名を変更したい
現状ヘッダーは Model のプロパティ名がそのまま出力されていますが、こちらも変更することが可能です。
方法は、変更したいプロパティに[Name] 属性を付与するだけです。

using CsvHelper.Configuration.Attributes;

namespace CsvDownload.Models
{
    /// <summary>
    /// Users テーブルのモデルクラス
    /// </summary>
    public class User
    {
        [Ignore]
        public int Id { get; set; } // ID プライマリーキー

        [Name("名前")]
        public string Name { get; set; } // 名前

        [Name("年齢")]
        public int Age { get; set; } // 年齢

        [Name("身長")]
        public float Height { get; set; } // 身長

        [Name("体重")]
        public float Weight { get; set; } // 体重
    }
}

これでファイルをダウンロードするとヘッダーが変更されていることが確認できます。

まとめ

いかがでしたでしょうか。
このようにCSVダウンロード機能は、管理システム等ではよく必要とされる機能だと思いますので、少しでも参考になれば幸いでございます。

では、以上となります。
ありがとうございました!