Weapsy 分析三(Web层) 3 关于MVC3中一个表单多个按钮的处理方案
很多人在做MVC3的时候问过这样的问题:我在一个表单中有几个按钮,如何提交到不同的方法。
<% Html.BeginForm("MyAction", "MyController", FormMethod.Post); %> <input type="submit" value="Send" /> <input type="submit" value="Cancel" /> <% Html.EndForm(); %>
现在比较常用的方式是用多个表单:如
<% 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(); %>
当然也可以给你的按钮一个名称,通过判断来解决这个问题
<% 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")); } }不过,还有更好的方案。
<% using (Html.BeginForm()) { %> <div> <fieldset> <legend>Account Information</legend> <p> <label for="username">Username:</label> <%= Html.TextBox("username") %> <%= Html.ValidationMessage("username") %> </p> <p> <label for="email">Email:</label> <%= Html.TextBox("email") %> <%= Html.ValidationMessage("email") %> </p> <p> <label for="password">Password:</label> <%= Html.Password("password") %> <%= Html.ValidationMessage("password") %> </p> <p> <label for="confirmPassword">Confirm password:</label> <%= Html.Password("confirmPassword") %> <%= Html.ValidationMessage("confirmPassword") %> </p> <button name="button" value="register">Register</button> <button name="button" value="cancel">Cancel</button> </p> </fieldset> </div> <% } %>
~/Controllers/AccountController.cs
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Register(string button, string userName, string email, string password, string confirmPassword) { if (button == "cancel") return RedirectToAction("Index", "Home"); ViewData["PasswordLength"] = MembershipService.MinPasswordLength; if (ValidateRegistration(userName, email, password, confirmPassword)) { // Attempt to register the user MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email); if (createStatus == MembershipCreateStatus.Success) { FormsAuth.SignIn(userName, false /* createPersistentCookie */); return RedirectToAction("Index", "Home"); } else { ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus)); } } // If we got this far, something failed, redisplay form return View(); }
public class AcceptParameterAttribute : ActionMethodSelectorAttribute { public string Name { get; set; } public string Value { get; set; } public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { var req = controllerContext.RequestContext.HttpContext.Request; return req.Form[this.Name] == this.Value; } }
[ActionName("Register")] [AcceptVerbs(HttpVerbs.Post)] [AcceptParameter(Name="button", Value="cancel")] public ActionResult Register_Cancel() { return RedirectToAction("Index", "Home"); } [AcceptVerbs(HttpVerbs.Post)] [AcceptParameter(Name="button", Value="register")] public ActionResult Register(string userName, string email, string password, string confirmPassword) { // process registration }
<% using (Html.BeginForm()) { %> <div> <fieldset> <legend>Account Information</legend> <p> <label for="username">Username:</label> <%= Html.TextBox("username") %> <%= Html.ValidationMessage("username") %> </p> <p> <label for="email">Email:</label> <%= Html.TextBox("email") %> <%= Html.ValidationMessage("email") %> </p> <p> <label for="password">Password:</label> <%= Html.Password("password") %> <%= Html.ValidationMessage("password") %> </p> <p> <label for="confirmPassword">Confirm password:</label> <%= Html.Password("confirmPassword") %> <%= Html.ValidationMessage("confirmPassword") %> </p> <p> <button name="button">Register</button> <button name="button" type="button" onclick="$('#cancelForm').submit()">Cancel</button> </p> </fieldset> </div> <% } %> <% using (Html.BeginForm("Register_Cancel", "Account", FormMethod.Post, new { id="cancelForm" })) {} %>
呵呵 。很有意思的解决方案。。。 真是有才。 不过还有个非常棒的方案 ~~~
<button name="button" type="button" onclick="$('#cancelForm').submit()">Cancel</button>
using (Html.BeginForm("Register_Cancel", "Account", FormMethod.Post, new { id="cancelForm" })) {}
好吧,暂时把它称为最终解决方案。^_^
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(…) { //… } }
ok ,这个解决方案非常的nice,很性感。喜欢的朋友可以使用~~~
最后提供下最终解决方案的Demo:MVC一个表单中多个按钮的解决方案