かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ASP.NET WebForm に Vue.js を入れてみよう

Vue.js は Progressive なので出来るでしょう。

プロジェクトの作成

ASP.NET WebForm のプロジェクトを作ります。凄く久しぶりなのですが、普通に ASP.NET Web Application のプロジェクトテンプレートの中の選択肢にありました。

Scripts フォルダーに vue.js をコピーして下準備完了です。

Default.aspx の変更

このページは Vue.js で作る!という意気込みで行くなら簡単です。Scripts フォルダーに default.js を追加して、以下のような感じで Default.aspx を編集します。

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="VueWebForm._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">

    <div id="app">
        <h1>Vue.js app</h1>
        <input type="text" v-model="input" />
        <p>{{ output }}</p>
    </div>

    <script type="text/javascript" src="Scripts/vue.js"></script>
    <script type="text/javascript" src="Scripts/default.js"></script>
</asp:Content>

そして default.js に好きなように Vue.js 書いていきます。

const vm = new Vue({
    el: '#app',
    data: function () {
        return {
            input: ''
        };
    },
    computed: {
        output: function () {
            return this.input.toUpperCase();
        }
    }
});

動いた。

f:id:okazuki:20190726151158p:plain

注意点

ASP.NET WebForm はページ自身に POST メソッドを投げるというポストバックを通じてページの状態の差分などからイベントを発火したり色々します。 ASP.NET WebForm のコントロールを使ってると、このときに TextBox の入力値とかは保持されるのですが Vue.js の世界からすると単純な再表示できれいさっぱりリセットされます。

なので以下のように WebForm のコントロールのあるページの一部が Vue.js だとすると…

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="VueWebForm._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">

    <asp:TextBox runat="server" ID="Input" />
    <asp:Button runat="server" ID="Button" Text="Click" OnClick="Button_Click" />

    <div id="app">
        <h1>Vue.js app</h1>
        <input type="text" v-model="input" />
        <p>{{ output }}</p>
    </div>

    <script type="text/javascript" src="Scripts/vue.js"></script>
    <script type="text/javascript" src="Scripts/default.js"></script>
</asp:Content>

実行して適当に入力して…

f:id:okazuki:20190726152057p:plain

ASP.NET WebForms のボタンコントロールのボタンを押すと…

f:id:okazuki:20190726152144p:plain

こんな感じで消えてしまいます。注意すべきなのは TextBox のテキスト変更イベントとかを使ってたら、それでもポストバックが走って Vue.js の画面がリフレッシュされてしまうということです。

ただ、input タグに name を付けてれば、ASP.NET WebForm のポストバックイベントの中で値を参照することは出来ます。 例えば以下のように vueinput という名前を input タグにつけておいて

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="VueWebForm._Default" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">

    <asp:TextBox runat="server" ID="Input" />
    <asp:Button runat="server" ID="Button" Text="Click" OnClick="Button_Click" />

    <div id="app">
        <h1>Vue.js app</h1>
        <input type="text" v-model="input" />
        <p>{{ output }}</p>
        <input name="vueinput" type="hidden" :value="output" />
    </div>

    <script type="text/javascript" src="Scripts/vue.js"></script>
    <script type="text/javascript" src="Scripts/default.js"></script>
</asp:Content>

ボタンのクリックイベントで値をとることができます。

protected void Button_Click(object sender, EventArgs e)
{
    var input = Request.Form["vueinput"];
    Input.Text = $"Hello from {input}";
}

実行して適当に入力して…

f:id:okazuki:20190726153215p:plain

ボタンを押すと Vue.js で大文字変換した結果がちゃんと ASP.NET WebForm のほうの TextBox に出てることが確認できます。

f:id:okazuki:20190726153305p:plain

まとめ

ASP.NET WebForms アプリでも単一ページ全体を Vue.js 化することは割と簡単に出来そう。 でも、ほかのページとステートを共有してとかなんだかんだしてるとめんどくさそうな気がします。

1 ページ内に Vue.js と WebForm が混ざってるとかなりめんどくさそうなので混ぜないのが吉な気がする…。

ということで、WebForms に完全新規ページで、割と独立性の高い機能を追加するのであれば Vue.js を入れることは出来なくはないと思いますが、継続的同じチームで見ていくようなシステムでみんなの合意が取れてる状態じゃないと、メンテナンスで引き取った人がかわいそうな雰囲気を感じました。