我建议有兴趣的人士 看看Maarten Balliauw的解决方案 。我觉得它非常优雅。
如果链接消失,它正在使用 MultiButton 应用于控制器操作的属性,以指示该操作应与哪个按钮单击相关。
MultiButton
如果您的浏览器支持输入按钮的属性格式(IE 10+,不确定其他浏览器),则以下内容应该有效:
@using (Html.BeginForm()){ //put form inputs here <input id="sendBtn" value="Send" type="submit" formaction="@Url.Action("Name Of Send Action")" /> <input id="cancelBtn" value="Cancel" type="submit" formaction="@Url.Action("Name of Cancel Action") /> }
我创造了一个 的 ActionButton 强> 的方法 的 的HtmlHelper 强> 。它将生成一些正常的输入按钮 的 JavaScript的 强> 在里面 的 OnClick事件 强> 将表单提交给指定的Controller / Action。
你使用这样的助手
@Html.ActionButton("MyControllerName", "MyActionName", "button text")
这将生成以下HTML
<input type="button" value="button text" onclick="this.form.action = '/MyWebsiteFolder/MyControllerName/MyActionName'; this.form.submit();">
这是扩展方法代码:
的 VB.Net 强>
<System.Runtime.CompilerServices.Extension()> Function ActionButton(pHtml As HtmlHelper, pAction As String, pController As String, pRouteValues As Object, pBtnValue As String, pBtnName As String, pBtnID As String) As MvcHtmlString Dim urlHelperForActionLink As UrlHelper Dim btnTagBuilder As TagBuilder Dim actionLink As String Dim onClickEventJavascript As String urlHelperForActionLink = New UrlHelper(pHtml.ViewContext.RequestContext) If pController <> "" Then actionLink = urlHelperForActionLink.Action(pAction, pController, pRouteValues) Else actionLink = urlHelperForActionLink.Action(pAction, pRouteValues) End If onClickEventJavascript = "this.form.action = '" & actionLink & "'; this.form.submit();" btnTagBuilder = New TagBuilder("input") btnTagBuilder.MergeAttribute("type", "button") btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript) If pBtnValue <> "" Then btnTagBuilder.MergeAttribute("value", pBtnValue) If pBtnName <> "" Then btnTagBuilder.MergeAttribute("name", pBtnName) If pBtnID <> "" Then btnTagBuilder.MergeAttribute("id", pBtnID) Return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal)) End Function
的 C# 强> (C#代码只是从VB DLL反编译,所以它可以得到一些美化......但时间太短了:-))
public static MvcHtmlString ActionButton(this HtmlHelper pHtml, string pAction, string pController, object pRouteValues, string pBtnValue, string pBtnName, string pBtnID) { UrlHelper urlHelperForActionLink = new UrlHelper(pHtml.ViewContext.RequestContext); bool flag = Operators.CompareString(pController, "", true) != 0; string actionLink; if (flag) { actionLink = urlHelperForActionLink.Action(pAction, pController, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues)); } else { actionLink = urlHelperForActionLink.Action(pAction, System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(pRouteValues)); } string onClickEventJavascript = "this.form.action = '" + actionLink + "'; this.form.submit();"; TagBuilder btnTagBuilder = new TagBuilder("input"); btnTagBuilder.MergeAttribute("type", "button"); btnTagBuilder.MergeAttribute("onClick", onClickEventJavascript); flag = (Operators.CompareString(pBtnValue, "", true) != 0); if (flag) { btnTagBuilder.MergeAttribute("value", pBtnValue); } flag = (Operators.CompareString(pBtnName, "", true) != 0); if (flag) { btnTagBuilder.MergeAttribute("name", pBtnName); } flag = (Operators.CompareString(pBtnID, "", true) != 0); if (flag) { btnTagBuilder.MergeAttribute("id", pBtnID); } return MvcHtmlString.Create(btnTagBuilder.ToString(TagRenderMode.Normal)); }
这些方法有各种参数,但为了便于使用,您可以创建一些只需要您需要的参数的重载。
您可以检查操作中的名称,但您可能会考虑这是否是一个好的设计。考虑操作的责任并且不要将此设计与按钮名称等UI方面过多地结合在一起是一个好主意。因此,请考虑使用2个表单和2个操作:
<% Html.BeginForm("Send", "MyController", FormMethod.Post); %> <input type="submit" name="button" value="Send" /> <% Html.EndForm(); %> <% Html.BeginForm("Cancel", "MyController", FormMethod.Post); %> <input type="submit" name="button" value="Cancel" /> <% Html.EndForm(); %>
此外,在“取消”的情况下,您通常只是不处理表单并转到新的URL。在这种情况下,您根本不需要提交表单,只需要一个链接:
<%=Html.ActionLink("Cancel", "List", "MyController") %>
[HttpPost] public ActionResult ConfirmMobile(string nameValueResend, string nameValueSubmit, RegisterModel model) { var button = nameValueResend ?? nameValueSubmit; if (button == "Resend") { } else { } } Razor file Content: @using (Html.BeginForm() { <div class="page registration-result-page"> <div class="page-title"> <h1> Confirm Mobile Number</h1> </div> <div class="result"> @Html.EditorFor(model => model.VefificationCode) @Html.LabelFor(model => model.VefificationCode, new { }) @Html.ValidationMessageFor(model => model.VefificationCode) </div> <div class="buttons"> <button type="submit" class="btn" name="nameValueResend" value="Resend"> Resend </button> <button type="submit" class="btn" name="nameValueSubmit" value="Verify"> Submit </button> </div> </div> }
基于mkozicki答案,我提出了一个不同的解决方案。我还在用 ActionNameSelectorAttribute 但我需要处理两个按钮'保存'和'同步'。他们几乎一样,所以我不想有两个动作。
ActionNameSelectorAttribute
的 属性 强> :
public class MultipleButtonActionAttribute : ActionNameSelectorAttribute { private readonly List<string> AcceptedButtonNames; public MultipleButtonActionAttribute(params string[] acceptedButtonNames) { AcceptedButtonNames = acceptedButtonNames.ToList(); } public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) { foreach (var acceptedButtonName in AcceptedButtonNames) { var button = controllerContext.Controller.ValueProvider.GetValue(acceptedButtonName); if (button == null) { continue; } controllerContext.Controller.ControllerContext.RouteData.Values.Add("ButtonName", acceptedButtonName); return true; } return false; } }
的 视图 强>
<input type="submit" value="Save" name="Save" /> <input type="submit" value="Save and Sync" name="Sync" />
的 调节器 强>
[MultipleButtonAction("Save", "Sync")] public ActionResult Sync(OrgSynchronizationEditModel model) { var btn = this.RouteData.Values["ButtonName"];
我还想指出,如果行动做不同的事情,我可能会关注mkozicki帖子。
你应该能够命名按钮并给它们一个值;然后将此名称映射为操作的参数。或者,使用2个单独的动作链接或2个表单。
David Findley在他的ASP.Net博客上写了大约3种不同的选项。
阅读文章 同一形式的多个按钮 看他的解决方案,以及各自的优缺点。恕我直言,他提供了一个非常优雅的解决方案,利用你装饰你的行动的属性。
Eilon建议你可以这样做:
如果你有多个按钮 可以通过给予来区分它们 每个按钮一个名字: <input type="submit" name="SaveButton" value="Save data" /> <input type="submit" name="CancelButton" value="Cancel and go back to main page" /> 在您的控制器操作方法中 可以添加以。之后命名的参数 HTML输入标签名称: public ActionResult DoSomeStuff(string saveButton, string cancelButton, ... other parameters ...) { ... } 如果任何值被发布到其中一个 那些参数,这意味着 按钮是被点击的那个。 Web浏览器仅发布值 为了 一 点击的按钮。 所有其他值将为null。 if (saveButton != null) { /* do save logic */ } if (cancelButton != null) { /* do cancel logic */ }
如果你有多个按钮 可以通过给予来区分它们 每个按钮一个名字:
<input type="submit" name="SaveButton" value="Save data" /> <input type="submit" name="CancelButton" value="Cancel and go back to main page" />
在您的控制器操作方法中 可以添加以。之后命名的参数 HTML输入标签名称:
public ActionResult DoSomeStuff(string saveButton, string cancelButton, ... other parameters ...) { ... }
如果任何值被发布到其中一个 那些参数,这意味着 按钮是被点击的那个。 Web浏览器仅发布值 为了 一 点击的按钮。 所有其他值将为null。
if (saveButton != null) { /* do save logic */ } if (cancelButton != null) { /* do cancel logic */ }
我喜欢这个方法,因为它不依赖于提交按钮的value属性,它比分配的名称更有可能更改,并且不需要启用javascript
看到: http://forums.asp.net/p/1369617/2865166.aspx#2865166
我的JQuery方法使用扩展方法:
public static MvcHtmlString SubmitButtonFor<TController>(this HtmlHelper helper, Expression<Action<TController>> action, string value) where TController : Controller { RouteValueDictionary routingValues = Microsoft.Web.Mvc.Internal.ExpressionHelper.GetRouteValuesFromExpression(action); var onclick = string.Format("$('form').first().attr('action', '/{0}')", string.Join("/", routingValues.Values.ToArray().Where(x => x != null).Select(x => x.ToString()).ToArray())); var html = "<input type=\"submit\" value=\"" + value + "\" onclick=\"" + onclick + "\" />"; return MvcHtmlString.Create(html); }
你可以像这样使用它:
@(Html.SubmitButtonFor<FooController>(c => c.Save(null), "Save"))
它呈现如下:
<input type="submit" value="Save" onclick="$('form').first().attr('action', '/Foo/Save')" >
我试图对所有解决方案进行综合,并创建了一个[ButtenHandler]属性,可以轻松处理表单上的多个按钮。
我在CodeProject上描述过它 ASP.NET MVC中的多个参数化(可本地化)表单按钮 。
要处理此按钮的简单情况:
<button type="submit" name="AddDepartment">Add Department</button>
您将拥有类似以下操作方法的内容:
[ButtonHandler()] public ActionResult AddDepartment(Company model) { model.Departments.Add(new Department()); return View(model); }
请注意按钮的名称与操作方法的名称是否匹配。本文还介绍了如何使用带有索引的值和按钮的按钮。
此脚本允许指定data-form-action属性,该属性将作为所有浏览器中的HTML5格式属性(以不显眼的方式):
$(document).on('click', '[type="submit"][data-form-action]', function(event) { var $this = $(this), var formAction = $this.attr('data-form-action'), $form = $($this.closest('form')); $form.attr('action', formAction); });
包含该按钮的表单将发布到data-form-action属性中指定的URL:
<button type="submit" data-form-action="different/url">Submit</button>
这需要jQuery 1.7。对于以前的版本,您应该使用 live() 代替 on() 。
live()
on()
关于ActionSelectName,我不喜欢的是为控制器中的每个操作方法调用IsValidName;我不知道它为什么会这样。我喜欢一个解决方案,其中每个按钮根据它的作用有不同的名称,但我不喜欢你必须在动作方法中拥有与表单中的按钮一样多的参数。我为所有按钮类型创建了一个枚举:
public enum ButtonType { Submit, Cancel, Delete }
而不是ActionSelectName,我使用ActionFilter:
public class MultipleButtonsEnumAttribute : ActionFilterAttribute { public Type EnumType { get; set; } public MultipleButtonsEnumAttribute(Type enumType) { EnumType = enumType; } public override void OnActionExecuting(ActionExecutingContext filterContext) { foreach (var key in filterContext.HttpContext.Request.Form.AllKeys) { if (Enum.IsDefined(EnumType, key)) { var pDesc = filterContext.ActionDescriptor.GetParameters() .FirstOrDefault(x => x.ParameterType == EnumType); filterContext.ActionParameters[pDesc.ParameterName] = Enum.Parse(EnumType, key); break; } } } }
过滤器将在表单数据中找到按钮名称,如果按钮名称与枚举中定义的任何按钮类型匹配,它将在操作参数中找到ButtonType参数:
[MultipleButtonsEnumAttribute(typeof(ButtonType))] public ActionResult Manage(ButtonType buttonPressed, ManageViewModel model) { if (button == ButtonType.Cancel) { return RedirectToAction("Index", "Home"); } //and so on return View(model) }
然后在视图中,我可以使用:
<input type="submit" value="Button Cancel" name="@ButtonType.Cancel" /> <input type="submit" value="Button Submit" name="@ButtonType.Submit" />
//model public class input_element { public string Btn { get; set; } } //views--submit btn can be input type also... @using (Html.BeginForm()) { <button type="submit" name="btn" value="verify"> Verify data</button> <button type="submit" name="btn" value="save"> Save data</button> <button type="submit" name="btn" value="redirect"> Redirect</button> } //controller public ActionResult About() { ViewBag.Message = "Your app description page."; return View(); } [HttpPost] public ActionResult About(input_element model) { if (model.Btn == "verify") { // the Verify button was clicked } else if (model.Btn == "save") { // the Save button was clicked } else if (model.Btn == "redirect") { // the Redirect button was clicked } return View(); }
你可以写:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %> <input type="submit" name="button" value="Send" /> <input type="submit" name="button" value="Cancel" /> <% Html.EndForm(); %>
然后在页面中检查名称==“发送”或名称==“取消”...
这是我使用的技术,我还没有在这里看到它。链接(由Saajid Ismail发布 )激发这种解决方案的是 http://weblogs.asp.net/dfindley/archive/2009/05/31/asp-net-mvc-multiple-buttons-in-the-same-form.aspx )。它使Dylan Beattie的答案适应本地化而没有任何问题。
在视图中:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %> <button name="button" value="send"><%: Resources.Messages.Send %></button> <button name="button" value="cancel"><%: Resources.Messages.Cancel %></button> <% Html.EndForm(); %>
在控制器中:
public class MyController : Controller { public ActionResult MyAction(string button) { switch(button) { case "send": this.DoSend(); break; case "cancel": this.DoCancel(); break; } } }
对于每个提交按钮,只需添加:
$('#btnSelector').click(function () { $('form').attr('action', "/Your/Action/); $('form').submit(); });
这对我最有用:
<input type="submit" value="Delete" name="onDelete" /> <input type="submit" value="Save" name="onSave" /> public ActionResult Practice(MyModel model, string onSave, string onDelete) { if (onDelete != null) { // Delete the object ... return EmptyResult(); } // Save the object ... return EmptyResult(); }
它很短且套房:
有人回答说 Jeroen Dop
<input type="submit" name="submitbutton1" value="submit1" /> <input type="submit" name="submitbutton2" value="submit2" />
并在代码behinde中这样做
if( Request.Form["submitbutton1"] != null) { // Code for function 1 } else if(Request.Form["submitButton2"] != null ) { // code for function 2 }
祝好运。
我没有足够的代表在正确的地方发表评论,但我整天都花在这上面,所以想分享。
在尝试实现“MultipleButtonAttribute”解决方案时 ValueProvider.GetValue(keyValue) 会错误地回来 null 。
ValueProvider.GetValue(keyValue)
null
事实证明,当它应该是4.0(其他程序集是4.0)时,我引用的是System.Web.MVC 3.0版。我不知道为什么我的项目没有正确升级,我没有其他明显的问题。
所以,如果你的 ActionNameSelectorAttribute 不工作......检查一下。