ASP.NET Core 2.0 Razor Pages での部分ビューの罠


結論から

Visual Studioでそれっぽく新規作成した部分ビューはそのままでは使えません!!(一部誇張)
部分ビュー側の@pageを削りましょう!

環境

  • Visual Studio Enterprizer 2017 version 15.4.5
  • .NET Framework 4.7.02556
  • .NET Core 2.0

再現(序):前準備

  1. Visual Studioから新しいプロジェクトを作成
  2. Visual C#.NET CoreASP.NET Core Webアプリケーションを選択
  3. .NET CoreASP.NET Core 2.0Web アプリケーション(Razorの方)を選択
  4. 適当な画面に適当に実装(例ではIndex)
Index.cshtml
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

Title:<input asp-for="Content.Title" />
Body:<input asp-for="Content.Body" />
Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WebApplication1.Pages
{
    public class IndexModel : PageModel
    {
        public class MyContent
        {
            public string Title { get; set; }
            public string Body { get; set; }
        }

        [BindProperty]
        public MyContent Content { get; set; }

        public void OnGet() { }

        public IActionResult OnPost()
        {
            if (ModelState.IsValid)
            {
                //登録処理とか
                return Redirect("Welcome");
            }
            return Page();
        }
    }
}

再現(破):部分ビュー作成

  1. バインドしたモデルごと別の画面でも使えるので部分ビューとして切り出しを思い立つ
  2. Pagesを右クリック>追加Razorページ
  3. 適当な命名で部分ビューを作成(例では_Common)

_Common.cshtml
@page
@*
    For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

再現(急):動かない!!

  1. Indexの実装を_Commonに移植して呼び出し
  2. エラー
Index.cshtml
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

@*Title:<input asp-for="Content.Title" />
Body:<input asp-for="Content.Body" />*@
@Html.Partial("_Common")
_Common.cshtml
@page
@*
    For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
*@
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

@*Indexで使っていたModelClassを_Commonで使うために@model定義*@
@model WebApplication1.Pages.IndexModel
Title:<input asp-for="Content.Title" />
Body:<input asp-for="Content.Body" />

解決

_Common.cshtmlの1行目の@pageを削りましょう。

さいごに

やりたいことをふつーに考えて実行したら動かなくなるってのは、困りますね。
自動生成されるキーワードが何を意味するかのドキュメントも、MSDNに完全に整備されているわけではないですし。
この小さなTipsで誰か救われますよーに!