是否有一些简单的方法来处理来自同一个表单的多个提交按钮?例如:
<% 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框架测试版?我在谷歌上搜索的所有例子中都有单个按钮。
当前回答
这是我发现的最好的方法:
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);
}
}
}
享受一个没有代码气味的多提交按钮的未来。
谢谢你!
其他回答
我的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')" >
给你的提交按钮一个名字,然后在你的控制器方法中检查提交的值:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="Send" />
<input type="submit" name="submitButton" value="Cancel" />
<% Html.EndForm(); %>
发布到
public class MyController : Controller {
public ActionResult MyAction(string submitButton) {
switch(submitButton) {
case "Send":
// delegate sending to another controller action
return(Send());
case "Cancel":
// call another action to perform the cancellation
return(Cancel());
default:
// If they've submitted the form without a submitButton,
// just return the view again.
return(View());
}
}
private ActionResult Cancel() {
// process the cancellation request here.
return(View("Cancelled"));
}
private ActionResult Send() {
// perform the actual send operation here.
return(View("SendConfirmed"));
}
}
编辑:
要将此方法扩展到本地化站点,请将您的消息隔离在其他地方(例如将资源文件编译为强类型资源类)
然后修改代码,使其像这样工作:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="submitButton" value="<%= Html.Encode(Resources.Messages.Send)%>" />
<input type="submit" name="submitButton" value="<%=Html.Encode(Resources.Messages.Cancel)%>" />
<% Html.EndForm(); %>
你的控制器应该是这样的:
// Note that the localized resources aren't constants, so
// we can't use a switch statement.
if (submitButton == Resources.Messages.Send) {
// delegate sending to another controller action
return(Send());
} else if (submitButton == Resources.Messages.Cancel) {
// call another action to perform the cancellation
return(Cancel());
}
对于每个提交按钮,只需添加:
$('#btnSelector').click(function () {
$('form').attr('action', "/Your/Action/);
$('form').submit();
});
你可以这样写:
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %>
<input type="submit" name="button" value="Send" />
<input type="submit" name="button" value="Cancel" />
<% Html.EndForm(); %>
然后在页面中检查name == "Send"或者name == "Cancel"…
下面是基于Maarten Balliauw的帖子和评论,针对多个提交按钮问题的一个非常干净的基于属性的解决方案。
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
public string Name { get; set; }
public string Argument { get; set; }
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
var isValidName = false;
var keyValue = string.Format("{0}:{1}", Name, Argument);
var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);
if (value != null)
{
controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
isValidName = true;
}
return isValidName;
}
}
剃须刀:
<form action="" method="post">
<input type="submit" value="Save" name="action:Save" />
<input type="submit" value="Cancel" name="action:Cancel" />
</form>
和控制器:
[HttpPost]
[MultipleButton(Name = "action", Argument = "Save")]
public ActionResult Save(MessageModel mm) { ... }
[HttpPost]
[MultipleButton(Name = "action", Argument = "Cancel")]
public ActionResult Cancel(MessageModel mm) { ... }
更新:Razor页面提供相同的功能开箱即用。对于新的开发来说,它可能更可取。