
Ajax.BeginFormを利用して、部分ビューを更新したいです。
詳細は以下です。
やりたいこと
- ボタンクリックで部分ビュー更新
- 更新後再描画された部分ビューで連続してボタンクリックによる部分ビュー更新ができる
起きている問題
- 想定通りに部分ビューが置き換わらない(UpdateTargetの中だけでなくフォーム全体が描画される…詳細は下部コード『html(画面で見た更新後のhtml)』参照)
- 更新後の部分ビューでは連続してボタンクリックによる部分ビューの更新ができない
コード
html(_comment.cshtml)
1<!-- // 厳密には cshtml --> 2@using(Ajax.BeginForm 3( 4 "Save", 5 "Common", 6 null, 7 new AjaxOptions 8 { 9 InsertionMode = InsertionMode.Replace, 10 HttpMethod = "POST", 11 UpdateTarget = "target-area" 12 } 13) 14{ 15 <div id="target-area"> 16 @Html.AntiForgeryToken() 17 <button name="save">保存</button> 18 @Html.TextArea("text-area", Model.textData) 19 </div> 20 <!-- /#target-area --> 21}
c#(CommonController.cs)
1[HttpPost] 2[ValidateAntiForgeryToken] 3public ActionResult Save() 4{ 5 // ここで非同期通信できているか確認 6 // 初回はif内へは入らず後続処理が正常動作していることから、 7 // 非同期通信になっていることを確認 8 if(!Request.IsAjaxRequest()) 9 { 10 return new EmptyResult(); 11 } 12 13 var textdata = Request.Form["text-area"]; 14 var model = new TestModel(); 15 model.textData = textdata; 16 return PartialView ("_textarea", model); 17}
生成されたHtmlのコード(開発者ツールで確認)
html(画面で見た更新前のhtml)
1<form action="/Common/Save" data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace"> 2 <div id="target-area"> 3 <button name="save">保存</button> 4 <textarea name="text-area"></textarea> 5 </div> 6 <!-- #target-area --> 7</form>
html(画面で見た更新後のhtml)
1<form action="/Common/Save" data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace"> 2 <div id="target-area"> 3 <form action="/Common/Save" data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace"> 4 <div id="target-area"> 5 <button name="save">保存</button> 6 <textarea name="text-area"></textarea> 7 </div> 8 <!-- #target-area --> 9 </form> 10 </div> 11 <!-- #target-area --> 12</form>
その他情報
- 初期表示時にボタンクリックしたときに、1回は非同期通信ができています。(Request.IsAjaxRequest()で確認)
- 連続して(画面全体を再読み込みせずに)ボタンクリックすると非同期通信にならず、EmptyResult() が返されます。(新規でHtmlが生成されるのでイベントを追加しなければならないんだとは思いますが、Ajax.BeginFormを使った場合にどのように書けばいいかが分かりません。)
- Microsoft.jQuery.Unobtrusive.Ajax はNugetでインストール済みです。
- jquery.unobtrusive-ajax.js の参照は記述済みです。(ブラウザ開発者ツールでデバッグもできるので正しく読み込めていることを確認)
- BundleConfig.cs の利用を禁止されており、以下を追記できていません。これが気がかりです。もしこれが原因の場合、対策はありますか?
c#(BundleConfig.cs)
1 bundles.Add(new ScriptBundle("~/bundles/jqueryajax").Include("~/Scripts/jquery.unobtrusive-ajax*"));
- UpdateTargetId に該当するidを設定する要素の位置がformの外が良いのかとも思いましたが、以下リンク先の質問の回答でformの中に定義していたので真似ています。
<参考にした質問ページ>
https://teratail.com/questions/137630
環境
- OS: Windows 10
- IDE: Microsoft Visual Studio Professional 2019
- 対象フレームワーク: .Net Framework 4.8
- 使用対象ブラウザ: Chrome, Chromium Edge, FireFox
以上の問題を解消し、やりたいことの実現をするためにご助言いただきたく、よろしくお願い致します。
[追記]
問題発生中のプロジェクトと同じ構成のコード
※以下のコードは問題発生中のものと同じ構成ですが、Web操作的には正常に動作します。
そのため、問題の原因がなおさら分からない状況にあります。
html(_Layout.cshtml)
1<!DOCTYPE html> 2<html> 3<head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <meta charset="utf-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>@ViewBag.Title - マイ ASP.NET アプリケーション</title> 8 <script src="https://code.jquery.com/jquery-3.4.1.min.js" 9 integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" 10 crossorigin="anonymous"></script> 11 <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script> 12</head> 13<body> 14 <div class="container body-content"> 15 @RenderBody() 16 <hr /> 17 <footer> 18 <p>© @DateTime.Now.Year - マイ ASP.NET アプリケーション</p> 19 </footer> 20 </div> 21 22</body> 23</html> 24
html(Index.cshtml)
1<div id="main"> 2 <h2>Ajax 部分ビュー更新</h2> 3 @Html.Partial("_app/_comment") 4</div>
html(_comment.cshtml)
1@model WebAjaxTest.Controllers.ViewModel 2 3@using (Ajax.BeginForm("Save", "ForAjax", null, new AjaxOptions { InsertionMode = InsertionMode.Replace, HttpMethod = "POST", UpdateTargetId = "replace-area"})) 4{ 5 <div id="replace-area"> 6 7 @Html.AntiForgeryToken() 8 9 <div class="button-area"> 10 <button name="save">保存</button> 11 </div> 12 13 @Html.TextArea( 14 "text-comment", 15 Model.comment, 16 new { @id = "comment-area" } 17 ) 18 </div> 19} 20
c#(HomeController)
1using System.Web.Mvc; 2 3namespace WebAjaxTest.Controllers 4{ 5 public class HomeController : Controller 6 { 7 public ActionResult Index() 8 { 9 var vm = new ViewModel(); 10 vm.comment = "初期表示"; 11 return View(vm); 12 } 13 14 } 15 16 // 記載か所が不適切だが取り急ぎの記述 17 public class ViewModel 18 { 19 public string comment { get; set; } 20 } 21}
c#(ForAjaxController.cs)
1using System.Web.Mvc; 2 3namespace WebAjaxTest.Controllers 4{ 5 public class ForAjaxController : Controller 6 { 7 [HttpPost] 8 [ValidateAntiForgeryToken] 9 public ActionResult Save() 10 { 11 if (!Request.IsAjaxRequest()) 12 { 13 return new EmptyResult(); 14 } 15 16 var comment = Request.Form["text-comment"]; 17 var vm = new ViewModel(); 18 19 // データなし 20 if (comment == "") 21 { 22 vm.comment = "ブランクでした"; 23 } 24 else 25 { 26 vm.comment = comment + "(値が入っていたので正常更新です)"; 27 } 28 return PartialView("_app/_comment", vm); 29 } 30 } 31 32} 33
実行 前後 のHtmlソース(開発者ツールから取得)
html(保存ボタンクリック前)
1<div id="main"> 2 <h2>Ajax 部分ビュー更新</h2> 3 <!--部分ビュー ここから--> 4 <form action="/ForAjax/Save" data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="#replace-area" id="form0" method="post"> 5 <div id="replace-area"> 6 7 <input name="__RequestVerificationToken" type="hidden" value="b0X1izesGdcOFWj7Jbo2gOfgarQfXczwOOTRqL6KB2fYEEY21UblfUNkA68EzkZp6jUFK27Rq4vfWs4At-OCB3KlGClF4hCZ53ST7LTGrFo1"> 8 9 <div class="button-area"> 10 <button name="save">保存</button> 11 </div> 12 13 <textarea cols="20" id="comment-area" name="text-comment" rows="2">初期表示</textarea> 14 15 </div> 16 </form> 17 <!--部分ビュー ここまで--> 18</div>
実行後はWeb操作は連続非同期処理できますが、以下のソースの置き換わり方が正しいのか気になります
(id=replace-area のdivが重複状態になってしまうため)
html(保存ボタンクリック後)
1<div id="main"> 2 <h2>Ajax 部分ビュー更新</h2> 3 <!--部分ビュー ここから--> 4<form action="/ForAjax/Save" data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="#replace-area" id="form0" method="post"> 5<div id="replace-area"> 6<!--部分ビュー ここから--> 7 <div id="replace-area"> 8 9 <input name="__RequestVerificationToken" type="hidden" value="2XUuEFyWynlKr9_DLUzke0bAdh1faQX7qyCwWpsl2Zbu2_7v3Tok5vBJXUMGMpbJHlbuVgzRgjA8MRQI2YxFegM1UsIYneW-DipyhqGxVCA1"> 10 11 <div class="button-area"> 12 <button name="save">保存</button> 13 </div> 14 15 <textarea cols="20" id="comment-area" name="text-comment" rows="2" style="width: 344px; height: 55px;">初期表示(値が入っていたので正常更新です)</textarea> 16 17 </div> 18<!--部分ビュー ここまで--> 19</div> 20</form> 21<!--部分ビュー ここまで--> 22</div>



回答2件
あなたの回答
tips
プレビュー