English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
時々このような状況に直面します:フォーム上に複数のボタンが必要で、それぞれ異なる機能を持っています。例えば、シンプルな承認機能などです。
WebFormを使用する場合、これについて議論する必要はありませんが、ASP.NET MVCではフォームは1つのActionハンドラにのみ提交できますが、少し厄介です。
方法1:クライアントサイドスクリプトの使用
例えば、Viewでこんな感じで書きます:
<input type="submit" value="承認通过" onclick='this.form.action="<%=Url.Action("Action1)%>"/>}} <input type="submit" value="承認不通过" onclick='this.form.action="<%=Url.Action("Action2)%>" />}} <input type="submit" value="戻る" onclick='this.form.action="<%=Url.Action("Action3)%>" />}}
提交ボタンをクリックした際に、まずFormのaction属性を変更し、フォームをボタンに関連付けられたactionハンドラに送信します。
しかし、時にはAction1および2のロジックは非常に似ており、たぶんあるフィールドの値を変更しているだけかもしれません1または0であれば、2つのactionに分けていくのは少し余計に感じられます。
方法2:Actionでどのボタンで送信されたかを判断します
Viewでは、クライアントサイドのスクリプトを使用せず、各ボタンのname属性を適切に設定します:
<input type="submit" value="承認通过" name="action" />}} <input type="submit" value="承認不通过" name="action"/>}} <input type="submit" value="戻る" name="action"/>}}
それでは、コントローラーで判断します:
[HttpPost] public ActionResult Index(string action /* 他のパラメータ*/) { if (action=="承認通过") { // } else if (action=="承認不通过") { // } else { // } }
数年前にaspのコードを書いていたときはよくこんな方法を使っていました…
Viewはシンプルになったが、Controllerは複雑化しました。
Viewに過度に依存すると、問題が発生する可能性があります。もし、ある日、顧客が「ボタンのテキストを「承認済み」と変更する」または「多言語版を作成する」と言ったら、面倒なことになります。
方法3:ActionSelectorの使用
ActionSelectorの基本原理について詳しく見てみるには、このPOSTを使用してActionSelectorでActionの選択を制御する方法が参考になります。
このメソッドを使用すると、以下のようにコントローラを書くことができます:
[HttpPost] [MultiButton("action1) public ActionResult Action1(), { // return View(); } [HttpPost] [MultiButton("action2) public ActionResult Action2(), { // return View(); }
Viewの中で:
<input type="submit" value="承認可" name="action1" />}} <input type="submit" value="承認不可" name="action2"/>}} <input type="submit" value="戻る" name="action3"/>}}
この時点で、ControllerはボタンのValue値に依存する必要はありません。
MultiButtonAttributeの定義は以下の通りです:
public class MultiButtonAttribute : ActionNameSelectorAttribute { public string Name { get; set; } public MultiButtonAttribute(string name) { this.Name = name; } public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo) { if (string.IsNullOrEmpty(this.Name)) { return false; } return controllerContext.HttpContext.Request.Form.AllKeys.Contains(this.Name); } }
方法四:改善
Controller:
[HttpPost] [MultiButton(Name = "delete", Argument = "id")] public ActionResult Delete(string id) { var response = System.Web.HttpContext.Current.Response; response.Write("Delete action was invoked with " + id); return View(); }
View:
<input type="submit" value="not important" name="delete" />}} <input type="submit" value="not important" name="delete:id" />}}
MultiButtonAttribute定義:
コード
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public class MultiButtonAttribute : ActionNameSelectorAttribute { public string Name { get; set; } public string Argument { get; set; } public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) { var key = ButtonKeyFrom(controllerContext); var keyIsValid = IsValid(key); if (keyIsValid) { UpdateValueProviderIn(controllerContext, ValueFrom(key)); } return keyIsValid; } private string ButtonKeyFrom(ControllerContext controllerContext) { var keys = controllerContext.HttpContext.Request.Params.AllKeys; return keys.FirstOrDefault(KeyStartsWithButtonName); } private static bool IsValid(string key) { return key != null; } private static string ValueFrom(string key) { var parts = key.Split(":".ToCharArray()); return parts.Length < 2 ? null : parts[1]; } private void UpdateValueProviderIn(ControllerContext controllerContext, string value) { if (string.IsNullOrEmpty(Argument)) return; controllerContext.Controller.ValueProvider[Argument] = new ValueProviderResult (value, value, null); } private bool KeyStartsWithButtonName(string key) { return key.StartsWith(Name, StringComparison.InvariantCultureIgnoreCase); } } //MVCの場合 2.0の話、UpdateValueProviderInメソッドを変更します: private void UpdateValueProviderIn(ControllerContext controllerContext, string value) { if (string.IsNullOrEmpty(Argument)) return; controllerContext.RouteData.Values[this.Argument] = value; }
これで本文のすべての内容が終わりました。皆様の学習に役立つことを願っています。また、呐喊教程を多くのサポートをお願いします。
声明:本文の内容はインターネットから取得しており、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、本サイトは所有権を有しておらず、人工的な編集処理も行われていません。著作権侵害を疑う内容がある場合は、以下のメールアドレスまでご連絡ください:notice#oldtoolbag.com(メールを送信する際には、#を@に変更してください。報告を行い、関連する証拠を提供してください。一旦確認がついたら、本サイトは即座に侵害を疑われる内容を削除します。)