質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

2回答

3773閲覧

MVC5 Ajax.BeginForm の使い方について(部分ビュー更新)

Kai

総合スコア10

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

0クリップ

投稿2022/01/31 10:54

編集2022/02/03 14:54

Ajax.BeginFormを利用して、部分ビューを更新したいです。
詳細は以下です。

やりたいこと

  1. ボタンクリックで部分ビュー更新
  2. 更新後再描画された部分ビューで連続してボタンクリックによる部分ビュー更新ができる

起きている問題

  1. 想定通りに部分ビューが置き換わらない(UpdateTargetの中だけでなくフォーム全体が描画される…詳細は下部コード『html(画面で見た更新後のhtml)』参照)
  2. 更新後の部分ビューでは連続してボタンクリックによる部分ビューの更新ができない

コード

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>&copy; @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>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/02/01 00:13

MVC4 ではなく MVC5 だと思いますが、であれば ASP.NET MVC 4 のタグは外してください。
退会済みユーザー

退会済みユーザー

2022/02/03 00:36

回答のコメントに書いた「Post/Redirect/Get パターンを使おうとして先の私のコードを書き換えた時」のコードが見つかって、質問に書いてある「一回目は OK だが二回目以降がダメ」が再現できました。後で回答欄に追記しておきます。
guest

回答2

0

↓ こういう話とは違いますか?

MVC5 で AjaxHelper が働かない
http://surferonwww.info/BlogEngine/post/2018/05/28/ajaxhelpers-do-not-work-on-mvc5-application-created-by-visual-studio-template.aspx


追記

下のコメント欄の 2022/02/03 09:35 私のコメントで、

「Post/Redirect/Get パターンを使おうとして先の私のコードを書き換えた時」のコードが見つかって、質問に書いてある「一回目は OK だが二回目以降がダメ」が再現できました。後で回答欄に追記しておきます。

・・・と書いた件です。

<参考にした質問ページ>
https://teratail.com/questions/137630

の私の回答のコードを、Post/Redirect/Get パターンを使うように書き直したものが以下のコードです。

提示したコードではビュー Index4.cshtml に対症療法を施していますので「一回目は OK だが二回目以降がダメ」という問題は出ませんが、この追記の下の方に問題を再現する方法を書きます。

もし、Post/Redirect/Get パターンというのが何か不明でしたら以下の記事の中頃の画像以下を読んでください。

EditorFor と DisplayFor の違い
http://surferonwww.info/BlogEngine/post/2013/03/27/editorfor-and-displayfor-display-different-values.aspx

モデル TextAreaModel

using System.ComponentModel.DataAnnotations; namespace Mvc5App.Models { public class TextAreaModel { [Required] [StringLength(15)] [DataType(DataType.MultilineText)] public string Comment { get; set; } } }

ビュー Index4.cshtml

@using Mvc5App.Models @model Mvc5App.Models.TextAreaModel @{ ViewBag.Title = "Index4"; } @{ // Redirect/Get のとき _ViewStart.cshtml で設定されている_Layout.cshtml が // ダブる。<h2>Index4</h2> もダブる。そうなると Ajax.BeginForm が働かない。 // これはその対症療法 TextAreaModel model = TempData["ValidatedModel"] as TextAreaModel; if (model != null) { Layout = null; } else { <h2>Index4</h2> } } @*<h2>Index4</h2>*@ <div> @Html.Partial("_Comment", Model) </div> @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script type="text/javascript"> //<![CDATA[ function disableSaveButton() { $("#save-button").attr('disabled', 'disabled'); } function enableSaveButton() { $("#save-button").removeAttr('disabled'); } //]]> </script> }

部分ビュー _Comment.cshtml

@model Mvc5App.Models.TextAreaModel @using (Ajax.BeginForm( "Save", "Ajax", new AjaxOptions { InsertionMode = InsertionMode.Replace, HttpMethod = "POST", UpdateTargetId = "replaceArea", OnBegin = "disableSaveButton", OnComplete = "enableSaveButton" })) { // Html.AntiForgeryToken はここではダメ。 <div id="replaceArea"> @Html.AntiForgeryToken() @Html.EditorFor(model => model.Comment) @Html.ValidationMessageFor(model => model.Comment) <br /> <input id="save-button" type="submit" value="保存"> </div> }

コントローラー AjaxController

using System.Linq; using System.Web.Mvc; using Mvc5App.Models; namespace Mvc5App.Controllers { public class AjaxController : Controller { public ActionResult Index4() { TextAreaModel model = TempData["ValidatedModel"] as TextAreaModel; if (model == null) { // 初期画面 model = new TextAreaModel(); model.Comment = "初期値"; } return View(model); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Save(TextAreaModel model) { if (!Request.IsAjaxRequest()) { return Content("AJAX を使った非同期呼び出ししかできません。"); } if (ModelState.IsValid) { // コメントの取得 string comment = model.Comment; // DB の更新。コードは省略 // Post/Redirect/Get パターンを使う TempData["ValidatedModel"] = model; return RedirectToAction("Index4"); } return PartialView("_Comment", model); } } }

上に「この追記の下の方に問題を再現する方法を書きます」と書いた件ですが、ビュー Index4.cshtml に施した対症療法を解除すると再現できます。

@{ // Redirect/Get のとき _ViewStart.cshtml で設定されている_Layout.cshtml が // ダブる。<h2>Index4</h2> もダブる。そうなると Ajax.BeginForm が働かない。 // これはその対症療法 TextAreaModel model = TempData["ValidatedModel"] as TextAreaModel; if (model != null) { Layout = null; } else { <h2>Index4</h2> } } @*<h2>Index4</h2>*@

の部分の @{ ... } をコメントアウトし、@*<h2>Index4</h2>*@ のコメントを解除して実行し、textarea に abc と入力して[保存]ボタンをクリックすると以下のようになります。

イメージ説明

こうなってしまうと Ajax.BeginForm は働かず、次の[保存]ボタンクリックで以下のようになってしまいます。

イメージ説明

質問者さんのコードとは違うとは思いますが、問題としている現象は同じということは、似たようなことにっているのではないでしょうか?

なお、原因は調べ切れていません。対症療法で逃げてしまったので。想像ですが、Ajax.BeginForm は本来は上のような使い方をするものではなく、想定外のことに対応できていないということのような気がします。

投稿2022/01/31 12:05

編集2022/02/03 02:41
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kai

2022/01/31 12:52

ご回答ありがとうございます。 ご提示いただきましたページの内容は、質問内容「その他情報」に記載しました通り、ほぼ、対応済みなのですが、Bundleの部分だけができていません。(出来ていない理由も「その他情報に記載」) Bundleの利用なしには、AjaxBegin.Formは扱えないのでしたら、諦めようかと思っています。 ※BundleConfig.csを追加して原因究明のために検証はしてみようと思います。
退会済みユーザー

退会済みユーザー

2022/01/31 13:04

> Bundleの利用なしには、AjaxBegin.Formは扱えない 少なくともそんなことはないです。バンドル&ミニファイが不要なら普通に script タグを使って必要な js ファイルを取得できます。
Kai

2022/01/31 13:16

>少なくともそんなことはないです。バンドル&ミニファイが不要なら普通に script タグを使って必要な js ファイルを取得できます。 ありがとうございます。 やはりそうですよね。 Bundleを正確に理解できていないですが、スクリプトの読み込みを楽にするものと理解しているので、Bundleが使えないことは関係ないと推測しておりました。 jQuery読込より後のタイミングでjquery.unobtrusive-ajax.jsを読み込むようには記述していますが、まだ何か足りないのでしょうか。 (読み込む際の記述↓) <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
退会済みユーザー

退会済みユーザー

2022/02/01 00:20

> jQuery読込より後のタイミング BundleConfig.cs は使わないとのことですが、それで js 関係の設定はどうやっているのですか? テンプレートで生成された _Layout.cshtml を使っていれば js 関係の設定は BundleConfig.cs を使うようになっているはずですが、どのようにして使わないように変更したのですか? > (読み込む際の記述↓) > <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script> それをどこに書いたのですか? ~ 演算子を使えない場所にそれを書いていませんか?
退会済みユーザー

退会済みユーザー

2022/02/01 00:25

質問に、 > 初期表示時にボタンクリックしたときに、1回は非同期通信ができています。 と書いてありましたが、「非同期通信ができています」というのはどのように確認したのですか? Ajax.BeginForm が期待通り動いているわけではなくて、何か思い違いをしているということはないですか?
Kai

2022/02/01 00:50 編集

非同期通信ができているかどうかの確認について controller側の以下の記述で確認ができると思っているのですが違うのでしょうか? if(!Request.IsAjaxRequest()) { return new EmptyResult(); }
Kai

2022/02/01 01:07

補足です jquery.unobtrusive-ajax.jsの読み込みについてですが 上記jsをブラウザの開発者ツールで見れますし、ブレイクポイントを設定してデバッグすることもできているので、読み込めていないということは無いと思います。
退会済みユーザー

退会済みユーザー

2022/02/01 02:02 編集

できれば、問題を再現できる必要最低限のごく簡単なサンプルで良いので、全体が分かるコードを追加してもらえませんか。今の情報だけでは追いかけきれません。コピペすれば動いて検証できるものが望ましいです。
退会済みユーザー

退会済みユーザー

2022/02/01 02:50

ちなみに、 > <参考にした質問ページ> > https://teratail.com/questions/137630 の私の回答のコードは、動かして確認してみましたが、期待通りちゃんと動きます。私の「期待」と質問者さんの「期待」が違うのかもしれませんが。
Kai

2022/02/01 08:14

何度も、お時間割いていただき感謝いたします。 動くサンプルコードを追記しました。 追記したコードは自分で検証用に用意していたコードで、追記内容にも記載している通り、問題発生中のプロジェクトと同じ構成と書き方にもかかわらず、期待通りの動作となります。(問題を再現できない) (期待通り)  ・非同期通信を連続で行うことができる。  ・非同期通信後描画されるHtmlにて、<form></form>が重複しない。 したがって、参考になるか怪しいところです。 問題のあるコードと、検証用のコードで動作が異なっているのは事実のため、何か差異があるはずだと思って、調査中ですがまだ判明していません。。。
退会済みユーザー

退会済みユーザー

2022/02/01 09:08

そういうことですと、質問者さんの方で頑張って「問題のあるコードと、検証用のコード」の違いを探していただく他なさそうですが・・・
Kai

2022/02/01 09:50

おっしゃる通りで恐縮な限りです。 数日進展なしで非常に困っており、処理実行後のHTMLの置き換わり方が違う点だけでも共有すれば何かヒントが得られるのではと思った次第です。 ひとまず引き続き調査し、解決できましたら原因と解決方法を記載しようと思います。
退会済みユーザー

退会済みユーザー

2022/02/02 01:59

Post/Redirect/Get パターンを使おうとして先の私のコードを書き換えた時に、_Layout.cshtml がダブって使われたということが記憶にありますが、そういうことはないですか?
退会済みユーザー

退会済みユーザー

2022/02/03 00:35

上のコメントの「Post/Redirect/Get パターンを使おうとして先の私のコードを書き換えた時」のコードが見つかって、質問に書いてある「一回目は OK だが二回目以降がダメ」が再現できました。後で回答欄に追記しておきます。
Kai

2022/02/03 05:50

回答が遅くなり申し訳ありません。 昨日(2/2)当サイトにアクセスしようとしたときには既にアクセスできない状態になっていました… コードの記載ありがとうございます。 恥ずかしながら、PRGパターンの知識を持ち合わせておりませんでしたので、大変勉強になりました。 恐らくご提示いただいた現象と同じことが起きていたのだと思います。 _comment.cshtml がダブっていたのかと。 やりとりさせていただいた情報をもとに、何がダメで何が問題ないのか明確になり、一つ一つ精査したところ無事に、解決することができました。 script参照の記載箇所や記載順番を整理したところ、問題の事象が解決できたので、原因としてはケアレスミスのような形で、多くの時間を割いていただいたのに本当に恐縮な思いです。 とても助かりましたし、仕組みも今回の事象もざっくりとしか把握できていなかったので、SurferOnWww様のおかげで理解を深めることができました。ありがとうございました。
guest

0

自己解決

script参照の記載箇所や記載順番を整理したところ、問題の事象が解決しました。
ただし、事象の状況などの正確な情報は SurferOnWwwさんの投稿してくださった回答内容の通りだと思います。

投稿2022/02/03 05:54

Kai

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問