回答編集履歴

2

追記

2022/02/03 02:41

投稿

退会済みユーザー
test CHANGED
@@ -190,7 +190,7 @@
190
190
 
191
191
  @*<h2>Index4</h2>*@
192
192
  ```
193
- の部分の @{ ... } をコメントアウトし、@*<h2>Index4</h2>*@ を解除して実行し、textarea に abc と入力して[保存]ボタンをクリックすると以下のようになります。
193
+ の部分の ```@{ ... }``` をコメントアウトし、```@*<h2>Index4</h2>*@``` のコメントを解除して実行し、textarea に abc と入力して[保存]ボタンをクリックすると以下のようになります。
194
194
 
195
195
  ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-02-03/78b70320-09e4-4c8d-81b1-10fff872315f.jpeg)
196
196
 

1

2022/02/03 02:17

投稿

退会済みユーザー
test CHANGED
@@ -3,3 +3,201 @@
3
3
 
4
4
  MVC5 で AjaxHelper が働かない
5
5
  http://surferonwww.info/BlogEngine/post/2018/05/28/ajaxhelpers-do-not-work-on-mvc5-application-created-by-visual-studio-template.aspx
6
+
7
+ ---
8
+
9
+ **追記**
10
+
11
+ 下のコメント欄の 2022/02/03 09:35 私のコメントで、
12
+
13
+ > 「Post/Redirect/Get パターンを使おうとして先の私のコードを書き換えた時」のコードが見つかって、質問に書いてある「一回目は OK だが二回目以降がダメ」が再現できました。後で回答欄に追記しておきます。
14
+
15
+ ・・・と書いた件です。
16
+
17
+ > <参考にした質問ページ>
18
+ > https://teratail.com/questions/137630
19
+
20
+ の私の回答のコードを、Post/Redirect/Get パターンを使うように書き直したものが以下のコードです。
21
+
22
+ 提示したコードではビュー Index4.cshtml に対症療法を施していますので「一回目は OK だが二回目以降がダメ」という問題は出ませんが、この追記の下の方に問題を再現する方法を書きます。
23
+
24
+ もし、Post/Redirect/Get パターンというのが何か不明でしたら以下の記事の中頃の画像以下を読んでください。
25
+
26
+ EditorFor と DisplayFor の違い
27
+ http://surferonwww.info/BlogEngine/post/2013/03/27/editorfor-and-displayfor-display-different-values.aspx
28
+
29
+ **モデル TextAreaModel**
30
+
31
+ ```
32
+ using System.ComponentModel.DataAnnotations;
33
+
34
+ namespace Mvc5App.Models
35
+ {
36
+ public class TextAreaModel
37
+ {
38
+
39
+ [Required]
40
+ [StringLength(15)]
41
+ [DataType(DataType.MultilineText)]
42
+ public string Comment { get; set; }
43
+ }
44
+ }
45
+ ```
46
+
47
+ **ビュー Index4.cshtml**
48
+
49
+ ```
50
+ @using Mvc5App.Models
51
+ @model Mvc5App.Models.TextAreaModel
52
+
53
+ @{
54
+ ViewBag.Title = "Index4";
55
+ }
56
+
57
+ @{
58
+ // Redirect/Get のとき _ViewStart.cshtml で設定されている_Layout.cshtml が
59
+ // ダブる。<h2>Index4</h2> もダブる。そうなると Ajax.BeginForm が働かない。
60
+ // これはその対症療法
61
+ TextAreaModel model = TempData["ValidatedModel"] as TextAreaModel;
62
+ if (model != null)
63
+ {
64
+ Layout = null;
65
+ }
66
+ else
67
+ {
68
+ <h2>Index4</h2>
69
+ }
70
+ }
71
+
72
+ @*<h2>Index4</h2>*@
73
+
74
+ <div>
75
+ @Html.Partial("_Comment", Model)
76
+ </div>
77
+
78
+ @section Scripts {
79
+ @Scripts.Render("~/bundles/jqueryval")
80
+
81
+ <script type="text/javascript">
82
+ //<![CDATA[
83
+ function disableSaveButton() {
84
+ $("#save-button").attr('disabled', 'disabled');
85
+ }
86
+
87
+ function enableSaveButton() {
88
+ $("#save-button").removeAttr('disabled');
89
+ }
90
+ //]]>
91
+ </script>
92
+ }
93
+ ```
94
+
95
+ **部分ビュー _Comment.cshtml**
96
+
97
+ ```
98
+ @model Mvc5App.Models.TextAreaModel
99
+
100
+ @using (Ajax.BeginForm(
101
+ "Save",
102
+ "Ajax",
103
+ new AjaxOptions
104
+ {
105
+ InsertionMode = InsertionMode.Replace,
106
+ HttpMethod = "POST",
107
+ UpdateTargetId = "replaceArea",
108
+ OnBegin = "disableSaveButton",
109
+ OnComplete = "enableSaveButton"
110
+ }))
111
+ {
112
+ // Html.AntiForgeryToken はここではダメ。
113
+
114
+ <div id="replaceArea">
115
+ @Html.AntiForgeryToken()
116
+ @Html.EditorFor(model => model.Comment)
117
+ @Html.ValidationMessageFor(model => model.Comment)
118
+ <br />
119
+ <input id="save-button" type="submit" value="保存">
120
+ </div>
121
+ }
122
+ ```
123
+
124
+ **コントローラー AjaxController**
125
+
126
+ ```
127
+ using System.Linq;
128
+ using System.Web.Mvc;
129
+ using Mvc5App.Models;
130
+
131
+ namespace Mvc5App.Controllers
132
+ {
133
+ public class AjaxController : Controller
134
+ {
135
+ public ActionResult Index4()
136
+ {
137
+ TextAreaModel model = TempData["ValidatedModel"] as TextAreaModel;
138
+ if (model == null)
139
+ {
140
+ // 初期画面
141
+ model = new TextAreaModel();
142
+ model.Comment = "初期値";
143
+ }
144
+ return View(model);
145
+ }
146
+
147
+ [HttpPost]
148
+ [ValidateAntiForgeryToken]
149
+ public ActionResult Save(TextAreaModel model)
150
+ {
151
+ if (!Request.IsAjaxRequest())
152
+ {
153
+ return Content("AJAX を使った非同期呼び出ししかできません。");
154
+ }
155
+
156
+ if (ModelState.IsValid)
157
+ {
158
+ // コメントの取得
159
+ string comment = model.Comment;
160
+
161
+ // DB の更新。コードは省略
162
+
163
+ // Post/Redirect/Get パターンを使う
164
+ TempData["ValidatedModel"] = model;
165
+ return RedirectToAction("Index4");
166
+ }
167
+ return PartialView("_Comment", model);
168
+ }
169
+ }
170
+ }
171
+ ```
172
+
173
+ 上に「この追記の下の方に問題を再現する方法を書きます」と書いた件ですが、ビュー Index4.cshtml に施した対症療法を解除すると再現できます。
174
+
175
+ ```
176
+ @{
177
+ // Redirect/Get のとき _ViewStart.cshtml で設定されている_Layout.cshtml が
178
+ // ダブる。<h2>Index4</h2> もダブる。そうなると Ajax.BeginForm が働かない。
179
+ // これはその対症療法
180
+ TextAreaModel model = TempData["ValidatedModel"] as TextAreaModel;
181
+ if (model != null)
182
+ {
183
+ Layout = null;
184
+ }
185
+ else
186
+ {
187
+ <h2>Index4</h2>
188
+ }
189
+ }
190
+
191
+ @*<h2>Index4</h2>*@
192
+ ```
193
+ の部分の @{ ... } をコメントアウトして、@*<h2>Index4</h2>*@ を解除して実行し、textarea に abc と入力して[保存]ボタンをクリックすると以下のようになります。
194
+
195
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-02-03/78b70320-09e4-4c8d-81b1-10fff872315f.jpeg)
196
+
197
+ こうなってしまうと Ajax.BeginForm は働かず、次の[保存]ボタンクリックで以下のようになってしまいます。
198
+
199
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-02-03/39f5fa21-1053-4f91-88c2-1f8378fa931a.jpeg)
200
+
201
+ 質問者さんのコードとは違うとは思いますが、問題としている現象は同じということは、似たようなことにっているのではないでしょうか?
202
+
203
+ なお、原因は調べ切れていません。対症療法で逃げてしまったので。想像ですが、Ajax.BeginForm は本来は上のような使い方をするものではなく、想定外のことに対応できていないということのような気がします。