是否有一些简单的方法来处理来自同一个表单的多个提交按钮?例如:
<% 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框架测试版?我在谷歌上搜索的所有例子中都有单个按钮。
当前回答
Modified version of HttpParamActionAttribute method but with a bug fix for not causing an error on expired/invalid session postbacks. To see if this is a problem with your current site, open the your form in a window and just before you go to click Save or Publish, open a duplicate window, and logout. Now go back to your first window and try to submit your form using either button. For me I got an error so this change solves that problem for me. I omit a bunch of stuff for the sake of brevity but you should get the idea. The key parts are the inclusion of ActionName on the attribute and making sure the name passed in is the name of the View that shows the form
属性类
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
private readonly string actionName;
public HttpParamActionAttribute(string actionName)
{
this.actionName = actionName;
}
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
return true;
if (!actionName.Equals(this.actionName, StringComparison.InvariantCultureIgnoreCase))
return false;
var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;
}
}
控制器
[Authorize(Roles="CanAddContent")]
public ActionResult CreateContent(Guid contentOwnerId)
{
var viewModel = new ContentViewModel
{
ContentOwnerId = contentOwnerId
//populate rest of view model
}
return View("CreateContent", viewModel);
}
[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult SaveDraft(ContentFormModel model)
{
//Save as draft
return RedirectToAction("CreateContent");
}
[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult Publish(ContentFormModel model)
{
//publish content
return RedirectToAction("CreateContent");
}
View
@using (Ajax.BeginForm("CreateContent", "MyController", new { contentOwnerId = Model.ContentOwnerId }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(x => x.ContentOwnerId)
<!-- Rest of your form controls -->
<input name="SaveDraft" type="submit" value="SaveDraft" />
<input name="Publish" type="submit" value="Publish" />
}
其他回答
我来派对已经很晚了,但现在开始… 我的实现借用了@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;
}
}
如果你对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
我的解决方案是使用2个asp面板:
< asp:面板ID = " . . "DefaultButton = " ID_OF_SHIPPING_SUBMIT_BUTTON "…> < / asp:面板>
你可以这样写:
<% 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"…
Modified version of HttpParamActionAttribute method but with a bug fix for not causing an error on expired/invalid session postbacks. To see if this is a problem with your current site, open the your form in a window and just before you go to click Save or Publish, open a duplicate window, and logout. Now go back to your first window and try to submit your form using either button. For me I got an error so this change solves that problem for me. I omit a bunch of stuff for the sake of brevity but you should get the idea. The key parts are the inclusion of ActionName on the attribute and making sure the name passed in is the name of the View that shows the form
属性类
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HttpParamActionAttribute : ActionNameSelectorAttribute
{
private readonly string actionName;
public HttpParamActionAttribute(string actionName)
{
this.actionName = actionName;
}
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
if (actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase))
return true;
if (!actionName.Equals(this.actionName, StringComparison.InvariantCultureIgnoreCase))
return false;
var request = controllerContext.RequestContext.HttpContext.Request;
return request[methodInfo.Name] != null;
}
}
控制器
[Authorize(Roles="CanAddContent")]
public ActionResult CreateContent(Guid contentOwnerId)
{
var viewModel = new ContentViewModel
{
ContentOwnerId = contentOwnerId
//populate rest of view model
}
return View("CreateContent", viewModel);
}
[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult SaveDraft(ContentFormModel model)
{
//Save as draft
return RedirectToAction("CreateContent");
}
[Authorize(Roles="CanAddContent"), HttpPost, HttpParamAction("CreateContent"), ValidateAntiForgeryToken]
public ActionResult Publish(ContentFormModel model)
{
//publish content
return RedirectToAction("CreateContent");
}
View
@using (Ajax.BeginForm("CreateContent", "MyController", new { contentOwnerId = Model.ContentOwnerId }))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(x => x.ContentOwnerId)
<!-- Rest of your form controls -->
<input name="SaveDraft" type="submit" value="SaveDraft" />
<input name="Publish" type="submit" value="Publish" />
}