是否有一些简单的方法来处理来自同一个表单的多个提交按钮?例如:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>
知道如何在ASP中做到这一点吗?NET框架测试版?我在谷歌上搜索的所有例子中都有单个按钮。
是否有一些简单的方法来处理来自同一个表单的多个提交按钮?例如:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" value="Send" />
<input type="submit" value="Cancel" />
<% Html.EndForm(); %>
知道如何在ASP中做到这一点吗?NET框架测试版?我在谷歌上搜索的所有例子中都有单个按钮。
当前回答
如果你对HTML 5的使用没有限制,你可以使用带有formaction的<button>标签:
<form action="demo_form.asp" method="get">
First name: <input type="text" name="fname" /><br />
Last name: <input type="text" name="lname" /><br />
<button type="submit">Submit</button><br />
<button type="submit" formaction="demo_admin.asp">Submit as admin</button>
</form>
参考:http://www.w3schools.com/html5/att_button_formaction.asp
其他回答
我来派对已经很晚了,但现在开始… 我的实现借用了@mkozicki,但需要更少的硬编码字符串来出错。需要4.5+框架。实际上,控制器方法名应该是路由的关键。
标记。按钮名称必须以“action:[controllerMethodName]”为键
(注意使用c# 6的API名称,提供了对希望调用的控制器方法名称的特定类型引用。
<form>
... form fields ....
<button name="action:@nameof(MyApp.Controllers.MyController.FundDeathStar)" type="submit" formmethod="post">Fund Death Star</button>
<button name="action:@nameof(MyApp.Controllers.MyController.HireBoba)" type="submit" formmethod="post">Hire Boba Fett</button>
</form>
控制器:
namespace MyApp.Controllers
{
class MyController
{
[SubmitActionToThisMethod]
public async Task<ActionResult> FundDeathStar(ImperialModel model)
{
await TrainStormTroopers();
return View();
}
[SubmitActionToThisMethod]
public async Task<ActionResult> HireBoba(ImperialModel model)
{
await RepairSlave1();
return View();
}
}
}
属性的魔法。注意使用CallerMemberName功能。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class SubmitActionToThisMethodAttribute : ActionNameSelectorAttribute
{
public SubmitActionToThisMethodAttribute([CallerMemberName]string ControllerMethodName = "")
{
controllerMethod = ControllerMethodName;
actionFormat = string.Concat(actionConstant, ":", controllerMethod);
}
const string actionConstant = "action";
readonly string actionFormat;
readonly string controllerMethod;
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
var isValidName = false;
var value = controllerContext.Controller.ValueProvider.GetValue(actionFormat);
if (value != null)
{
controllerContext.Controller.ControllerContext.RouteData.Values[actionConstant] = controllerMethod;
isValidName = true;
}
return isValidName;
}
}
刚刚写了一篇相关的文章: 多个提交按钮与ASP。NET MVC:
基本上,我用的不是ActionMethodSelectorAttribute,而是 ActionNameSelectorAttribute,它允许我假装动作名是我想要的任何东西。幸运的是,ActionNameSelectorAttribute不只是让我指定操作名称,而是我可以选择当前操作是否与请求匹配。
这就是我的班级(顺便说一句,我不太喜欢这个名字):
public class HttpParamActionAttribute : ActionNameSelectorAttribute {
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) {
if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
return true;
if (!actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
return false;
var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;
}
}
只需要像这样定义一个表单:
<% using (Html.BeginForm("Action", "Post")) { %>
<!— …form fields… -->
<input type="submit" name="saveDraft" value="Save Draft" />
<input type="submit" name="publish" value="Publish" />
<% } %>
控制器有两个方法
public class PostController : Controller {
[HttpParamAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveDraft(…) {
//…
}
[HttpParamAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Publish(…) {
//…
}
}
如您所见,该属性根本不需要指定任何内容。此外,按钮的名称直接转换为方法名称。此外(我还没有尝试过)这些应该作为正常的动作以及,所以你可以张贴到他们中的任何一个 直接。
我已经为HtmlHelper创建了一个ActionButton方法。它将在OnClick事件中生成带有javascript的普通输入按钮,将表单提交给指定的控制器/动作。
像这样使用辅助器
@Html.ActionButton("MyControllerName", "MyActionName", "button text")
这将生成以下HTML
<input type="button" value="button text" onclick="this.form.action = '/MyWebsiteFolder/MyControllerName/MyActionName'; this.form.submit();">
下面是扩展方法代码:
VB。网
<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));
}
这些方法具有各种参数,但是为了便于使用,您可以创建一些重载,只使用所需的参数。
这是我发现的最好的方法:
http://iwayneo.blogspot.co.uk/2013/10/aspnet-mvc-action-selector-with-list.html
代码如下:
/// <summary>
/// ActionMethodSelector to enable submit buttons to execute specific action methods.
/// </summary>
public class AcceptParameterAttribute : ActionMethodSelectorAttribute
{
/// <summary>
/// Gets or sets the value to use to inject the index into
/// </summary>
public string TargetArgument { get; set; }
/// <summary>
/// Gets or sets the value to use in submit button to identify which method to select. This must be unique in each controller.
/// </summary>
public string Action { get; set; }
/// <summary>
/// Gets or sets the regular expression to match the action.
/// </summary>
public string ActionRegex { get; set; }
/// <summary>
/// Determines whether the action method selection is valid for the specified controller context.
/// </summary>
/// <param name="controllerContext">The controller context.</param>
/// <param name="methodInfo">Information about the action method.</param>
/// <returns>true if the action method selection is valid for the specified controller context; otherwise, false.</returns>
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
Func<NameValueCollection> formGetter;
Func<NameValueCollection> queryStringGetter;
ValidationUtility.GetUnvalidatedCollections(HttpContext.Current, out formGetter, out queryStringGetter);
var form = formGetter();
var queryString = queryStringGetter();
var req = form.AllKeys.Any() ? form : queryString;
if (!string.IsNullOrEmpty(this.ActionRegex))
{
foreach (var key in req.AllKeys.Where(k => k.StartsWith(Action, true, System.Threading.Thread.CurrentThread.CurrentCulture)))
{
if (key.Contains(":"))
{
if (key.Split(':').Count() == this.ActionRegex.Split(':').Count())
{
bool match = false;
for (int i = 0; i < key.Split(':').Count(); i++)
{
if (Regex.IsMatch(key.Split(':')[0], this.ActionRegex.Split(':')[0]))
{
match = true;
}
else
{
match = false;
break;
}
}
if (match)
{
return !string.IsNullOrEmpty(req[key]);
}
}
}
else
{
if (Regex.IsMatch(key, this.Action + this.ActionRegex))
{
return !string.IsNullOrEmpty(req[key]);
}
}
}
return false;
}
else
{
return req.AllKeys.Contains(this.Action);
}
}
}
享受一个没有代码气味的多提交按钮的未来。
谢谢你!
以下是最适合我的方法:
<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();
}