【失敗談】コマンドからスキャフォールディングしたら、思ってたのと違った話

1. きっかけ

MacOS で文献管理システムを作ろうと奮闘しているとき、スキャフォールドの仕方が分からず色々調べながらやってました。できたにはできたのですが、思ってたのと違ったので失敗談として記録。

2. 環境

  • MacOS Mojave 10.14.1
  • .Net Core 2.1.400

3. 文献管理用データベースモデルの作成

コードはこんな感じです。Models > Book.cs

    public class Book
    {
        public int Id { get; set; } //データベースのキーID
        public string タイトル { get; set; } //文献タイトル
        public string 著者 { get; set; } //文献の著者
        public string 出版社 { get; set; } //文献の出版社

        [DataType(DataType.Date)]
        public DateTime 発行日 { get; set; } //文献の発行日

        public string 分野 { get; set; } //文献の分類
        public string リンク { get; set; } //文献のリンク先
    }

データベースコンテキストは Model > RazorPagesBooksContext.cs で作成。

    public class RazorPagesBooksContext : DbContext
    {
        public RazorPagesBooksContext(DbContextOptions<RazorPagesBooksContext> options)
            : base(options)
        {
        }

        public DbSet<BooksDatabase.Models.Book> Book { get; set; }
    }

MySQL データベース用に接続文字列を指定。(appsettings.json)

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;User Id=root;Password=pass;Database=ApplicationDbContext",
    "BooksDbContext": "Server=localhost;User Id=root;Password=pass;Database=BooksDbContext"
        },
//略

NuGet にてパッケージを追加

  • Microsoft.VisualStudio.Web.CodeGeneration.Design
  • Microsoft.EntityFrameworkCore.Design
  • Pomelo.EntityFrameworkCore.MySql

Startup.cs の UseSqlServer メソッドを UseMysql メソッドに変更

//略
 public void ConfigureServices(IServiceCollection services)
{
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseMySql(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>()
                .AddEntityFrameworkStores<ApplicationDbContext>();
            services.AddDbContext<RazorPagesBooksContext>(options =>
                    options.UseMySql(Configuration.GetConnectionString("BooksDbContext")));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//略

4. スキャフォールディング

この時点で3回ほどやり直していています。Model のデータベース要素 (Books.cs) をもとにして、View にて Pages/Books を作ろうとすると、なぜか "Books" が競合してしまうようでビルドできませんでした。なので Book.cs として作成し、Pages/Books に View を作るようにします。その前にリストアとビルドをする必要があります。

sudo dotnet aspnet-codegenerator razorpage -m book -dc RazorPagesBooksContext -udl -outDir Pages/Books --referenceScriptLibraries

これで VIew が生成されます。

5. データベースの移行と更新

先にビルドしてスキャフォールドされたデータを適用します。データベースを移行し、更新します。

sudo dotnet ef migrations add --context RazorPagesBooksContext BooksDbContext

ここで一旦ビルド。そして更新します。

sudo dotnet ef database update --context RazorPagesBooksContext

問題なく生成されました。

6. 実行結果

データベースが動いているか実行して確認してみます。まだリンクを作成していないので、直接 URL からアクセスします。 localhost:port/Books f:id:takunology:20190627012215p:plain

ファーッ! 思ってたの違うぅ
何が違うかというと、

  • なぜかデザインが適用されていない
  • Create New ボタンが押せず、ただのテキストになっている
  • なんかダサい
  • なんかダサい
  • なんかダサい

とかです。もうこの時点で嫌な気がするんですが、念のため直接 URL を指定して文献作成ページに飛びます。 f:id:takunology:20190627012557p:plain

(゚∀゚)アヒャ(゚∀゚)アヒャ(゚∀゚)アヒャ
もうだめです。なぜか "Create" だけボタンとして押せるのですが、押してみると空白のページに飛びます。これじゃどこに何を入力していいかさっぱりですね。

7. 考察

スキャフォールドするときに View しか生成されていないことに気が付きました。Model をもとに View を作成されているんですが、肝心の Controller が生成されていません。なのでボタンをクリックしても処理されないのですね。しかし、View が分かりません。なぜこんなしょぼいページになっているのか...。これは自分で修正するしかないのか、それともスキャフォールドで修正できるのか...。これはやってみないと分かりませんね。

8. 結論

スキャフォールディングする方法が分かっただけでもかなりの収穫なのですが、それにしても悔しいです。
近いうちにリベンジします。