Skip to content

MS_PartialRenderingAndJavaScript

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

部分描画とJavaScript

移行メモ(戻るリンクの補完): 原文には「戻る」の行が無かったため、
本文の参照関係から ASP.NET 配下として補った。

概要

クライアント・サイドの JavaScript フレームワークとシームレスに連動して
部分更新を実現する仕組み。

補足(本ページの主題): 「Ajax で画面の一部だけを更新する」ことを、
サーバ側のフレームワークが肩代わりするという発想の仕組みを扱う。

【本ページが扱う方式】サーバ主導の部分更新
   UpdatePanel(Web Forms)、Ajax.BeginForm(MVC)
     → 開発者は Ajax を書かない。フレームワークが隠蔽する

【現在の方式】クライアント主導
   fetch / axios で API を呼び、
   React / Vue / Blazor が DOM を更新する
     → 何が起きているかがコードに現れる

結論を先に言うと、本ページの 2 方式はいずれも現在は使われない
(Ajax.BeginForm は ASP.NET Core MVC で廃止、
UpdatePanel は Web Forms とともに .NET Framework 止まり)。
原文が末尾で挙げる問題点の分析が、そのまま廃止の理由になっている。

詳細

ASP.NET Web Formsの UpdatePanel

特徴

  • UpdatePanel を敷いた部分が部分更新となる。

  • ソレ以外の部分は、全体更新と成る。

  • 仕組みとしては、

    • 部分更新イベントで全情報がポストバックされ、
    • 対象となるイベント・ハンドラが実行され、
    • 部分更新される部分の HTML が返され、
    • 返された HTML がレンダリングされる。

補足(「全情報がポストバックされる」が要点): 原文の
この記述が、UpdatePanel の性質を最もよく表している。

【見た目】     画面の一部だけが書き換わる(Ajax っぽい)
【実際の通信】 フォーム全体 + ViewState を丸ごと POST している
                サーバ側ではページ ライフサイクルが「全部」走る
                ([ASP.NET Web Formsのイベント発生順](MS_ASPNETWebFormsEventOrder))

つまり 「通信量も処理量も、全体更新とほぼ変わらない」
減るのは描画のちらつきだけである。

通常のポストバック UpdatePanel 本来の Ajax
送信データ フォーム全体 + ViewState 同じ 必要な項目のみ
サーバ処理 全ライフサイクル 全ライフサイクル 必要な処理のみ
応答 ページ全体の HTML 更新部分の HTML JSON(数十バイト)
画面のちらつき あり 無い 無い

ViewState が肥大化していると、UpdatePanel は非常に重くなる
「Ajax にしたのに速くならない」という体感は、これが原因である。

参考

ASP.NET MVCの Ajax.BeginForm

特徴

  • Html.BeginForm

    • モジュール構造は大きく変わらない。
      (部分ビューは、共通化目的で Html.BeginForm にも存在する。)

    • ただし、以下のように動作は大きく異なる。

      • jQuery を使用してリクエストし、
      • 更新部位のレスポンスを受けて JavaScript で描画。
  • 部分更新のターゲットを意識する必要がある。

    • 送信時に設定したターゲット以外を更新しようとして、結果的に画面遷移する場合、
    • RedirectToAction・RedirectToRoute 等で ActionResult を返すことが出来ないので、
      JavaScriptResult 等で JavaScript を返し、画面遷移をする必要がある。

補足(この「ターゲット問題」が本質的な弱点): 原文が指摘する
**「リダイレクトを返せない」**という制約は、
サーバ主導の部分更新に共通する構造的な問題である。

Ajax.BeginForm は「更新先の DOM 要素(UpdateTargetId)」を
あらかじめ 1 つ決めておく方式

  → 正常時: 部分ビューの HTML を返し、その要素を差し替える
  → 異常時/画面遷移したい: 返す先が決まっているので、
     RedirectToAction を返しても「その要素の中に遷移先の HTML が
     埋め込まれる」という珍妙な結果になる
  → JavaScriptResult で location.href を書いて返す、という回避策
// 回避策:JavaScript を返して遷移させる
return JavaScript($"window.location='{Url.Action("Index")}';");

サーバが「HTML の断片」を返す方式は、
「どこに差し込むか」をサーバとクライアントの両方が知っている必要があり、
結合度が高くなる
これが、JSON を返して描画はクライアントに任せる方式へ
移行した理由の一つである。

discon へ。

以下の問題が大きかったのか、
ASP.NET Core MVC で、discon となっている

補足(正確な経緯): Ajax.BeginFormMicrosoft.jQuery.Unobtrusive.Ajax)は
ASP.NET Core MVC には移植されなかった

後継として用意されたもの:

機能 ASP.NET Core での代替
Ajax.BeginForm 無し(自分で fetch を書く)
部分ビューの返却 PartialView() は健在
部分更新 fetch + innerHTML、または htmx
サーバ主導の DOM 更新 Blazor Server(SignalR で差分を送る)
// 現在の素朴な部分更新
const res  = await fetch('/Items/List', { headers: { 'X-Requested-With': 'fetch' } });
document.getElementById('list').innerHTML = await res.text();

htmx は、まさに Ajax.BeginForm と同じ発想
(HTML 断片を返して差し替える)をライブラリとして実装したもので、
ASP.NET Core と組み合わせる例が近年増えている。

<form hx-post="/Items/Create" hx-target="#list" hx-swap="innerHTML">

Blazor Server は、
UpdatePanel の思想を現代的に再構築したものとも言える
(サーバ側に状態を持ち、差分だけを送って DOM を更新する)。
ただし ViewState ではなく SignalR の常時接続で実現している点、
差分が DOM レベルで最小化されている点が決定的に異なる。

参考

その性質上、Ajax 通信の結果をページの一部に
反映させるようなケースで利用することになるだろう。

部分描画の問題点

懸念

もともと、ASP.NET Web Formsの UpdatePanel では、

  • ScriptManager がブラックボックスで
  • 他の JavaScript に干渉する可能性があり。
  • 危なっかしくて触りたくない感があった。

実際

実際のトコロ、

  • JavaScript の挙動の分析が困難になり、
    特に、サーバー側で JavaScript を生成して UI を制御しているとき
    問題発生時のトラブルシュートが難しくなることがある。

  • 部分描画では、ブラウザがレスポンス待ちかどうかユーザが識別できず、
    レスポンスに時間が抱えるケースで、UX が低下するという問題を生んだ。

移行メモ(誤記): 原文の「レスポンスに時間が抱える」は
**「時間がかかる」**の誤記と判断されるが、
原文の表現を保ちつつここに注記する。

補足(この分析は的確で、そのまま廃止理由になっている): 原文が挙げる
2 点は、いずれもサーバ主導の部分更新に固有の弱点である。

① JavaScript の干渉

UpdatePanel が DOM を差し替えると、
  ・その領域に付けたイベント ハンドラが消える
  ・jQuery プラグインの初期化が失われる
  ・$(document).ready は再実行されない

→ Sys.WebForms.PageRequestManager の
  add_endRequest で再初期化する、という定型的な回避策が要る
Sys.WebForms.PageRequestManager.getInstance()
    .add_endRequest(function () { initPlugins(); });

「差し替えたら初期化し直す」という責務が暗黙になっていることが、
原文の言う「ブラックボックス」「危なっかしい」の実体である。

**現在のフレームワーク(React / Vue / Blazor)**は、
DOM の差し替えを仮想 DOM / 差分レンダリングで管理し、
ライフサイクル フック(useEffectOnAfterRender 等)を
明示的に提供する
ことでこの問題を解消している。

② 待ち状態が分からない(UX の低下)

通常のポストバック → ブラウザがローディング表示を出す
部分描画           → ブラウザは何も表示しない
                      → ユーザーは「押せていない」と思い、二重送信する

**対処は「自分でローディング表示を出す」**ことであり、
UpdatePanel には UpdateProgress コントロールが用意されていた。

現在もこの責務はクライアント側に残るが、
設計として明示されている点が異なる。

対処 現在の実装
ローディング表示 状態変数 + スピナー(isLoading
二重送信の防止 送信中はボタンを disabled
楽観的 UI 先に画面を更新し、失敗したら戻す
進捗の可視化 スケルトン表示

結論: 原文の懸念は正当で、
「部分更新をフレームワークが隠す」という設計自体が問題だった。
現在は隠さずに、明示的に扱う方向に収束している。

参考

Microsoft Learn


Tags: 移行, .NET開発, ASP.NET, ASP.NET Web Forms, ASP.NET MVC

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally