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一个表单中多个按钮的解决方案

posted @ 2012-05-19 21:31  陈卓杰  阅读(1268)  评论(3编辑  收藏  举报