ASP.NET MVC-GETを介して送信するときにHtml.BeginForm()にクエリ文字列パラメーターを記憶させる
-
10-07-2019 - |
質問
Html.BeginForm()を介してレンダリングされたフォームがあり、マスターページのコンポーネントとして存在するため、アプリケーションのすべてのページに表示されます。 Mvc FuturesアセンブリのHtml.RenderAction()を使用してこれを実行しました。これは、検索フォーム自体の下にある同じコンポーネント内のいくつかのアイテムを更新し、クエリ文字列に検索語が表示されるようにGETを実行する単純な検索フォームです。
<div class="sideBarContent">
<h2>Search Products</h2>
<% using (Html.BeginForm(ViewContext.RouteData.Values["action"].ToString(),
ViewContext.RouteData.Values["controller"].ToString(), FormMethod.Get)) { %>
<fieldset>
<legend>Search Products</legend>
<div class="formRow">
<label for="ProductsSearch">Search</label>
<%= Html.TextBox("ProductsSearch") %>
</div>
<input type="submit" value="Search" class="button" />
</fieldset>
<% } %>
<ul>
// Products will eventually be listed here
</ul>
</div>
次のことを行うには、このフォームが必要です:
1)クエリ文字列パラメーターとして 'ProductsSearch'を追加する際に、現在のページにGETを実行する必要があります(例: example.com/?ProductsSearch=test または example.com / books / fiction?ProductsSearch = test )
2)クエリ文字列に既に存在する既存のクエリ文字列パラメータを記憶し、[検索]ボタンをクリックした後、それらを維持する必要があります。 example.com/myOrders?page=2 検索をクリックした後、 example.com/myOrders?page=2 <!> amp; ProductsSearch = test に移動する必要があります)
1)実行できますが、2)解決できません。
通常、fromからGETへとクエリ文字列パラメーターを追加するために、非表示フォームフィールドが必要であるため、任意のクエリ文字列値に対して多数の非表示フォームフィールドを自動的に追加するユーティリティ関数を作成できますが、チェックしたい簡単なアプローチがなかった、または間違った方法で行っている可能性があります。
乾杯!
解決
非表示フォームフィールドメソッドを実行する必要があります。
<!> lt; form <!> gt;のaction属性で、クエリ文字列全体をURLの末尾に添付できる場合でもタグ、ブラウザはGETフォーム送信を行うときにこれに注意を払いません。
あなたの方法はそれほど難しくありません。次のようなことをしたいでしょう:
public static string QueryStringAsHidden(this HtmlHelper helper)
{
var sb = new StringBuilder();
foreach (var key in HttpContext.Current.Request.QueryString.AllKeys)
{
if (! key.StartsWith("ProductSearch"))
sb.Append(helper.Hidden(key, HttpContext.Current.Request.QueryString[key]));
}
return sb.ToString();
}
.StartsWith()を挿入します。検索ページに移動して検索文字列を2回送信したくないためです(そして、ProductSearchでページングやその他の検索固有の変数を追加できるようになりました。
編集:PS:現在のページに投稿するフォームを取得するには、アクションとコントローラーを明示的に提供する必要はありません。nullを送信することもできます。
Edit2:ヘルパーメソッドが必要なのはなぜですか? :)
<% HttpContext.Current.Request.QueryString.AllKeys.Where(k => !k.StartsWith("ProductSearch")).ToList().ForEach(k => Response.Write(Html.Hidden(k, HttpContext.Current.Request.QueryString[k]))); %>
ジェームズ
他のヒント
BeginForm()を直接呼び出すと、クエリ文字列値が保持されます。その他の過負荷は失敗する傾向があります。私はフォームからBeginForm()を簡単に使用できることを気に入っていますが、アクションでクエリ文字列の値を失わない特定の方法ですべてのスタイル付きフォームを分類する方法が必要でした。
ここに私が思いついたものがあります:
public static MvcForm BeginNormalForm<T>(this HtmlHelper<T> htmlHelper)
{
var dictionary = new Dictionary<string, object> {{"class", "normal"}};
var rvd = new RouteValueDictionary();
if (htmlHelper.ViewContext.HttpContext != null && htmlHelper.ViewContext.HttpContext.Request != null)
{
foreach (var key in htmlHelper.ViewContext.HttpContext.Request.QueryString.AllKeys)
{
rvd[key] = htmlHelper.ViewContext.HttpContext.Request.QueryString[key];
}
}
var form = htmlHelper.BeginForm(null, null, rvd, FormMethod.Post, dictionary);
return form;
}
うまく機能しているようで、クラス属性を保持しています。
routeValuesオブジェクトまたは辞書を受け取るBeginFormのオーバーロードの1つを使用します。
ルートにない追加のプロパティは、クエリパラメーターとして追加されます。