Monday, 14 October 2013

Handling multiple submit buttons on the same form - MVC Razor

Sometimes you required to have more than one submit buttons on the same form in mvc razor. In that case, how will you handle the click event of different buttons on your form?
In this article, I am going to expose the various ways for handling multiple buttons on the same form. Suppose you have a user signup form like as below:
In the above fig. we have Save, Submit & Cancel buttons. Suppose on Save button click you are saving data in the tempUser table & on Submit button you are saving data in RegUser table and more over on Cancel button click you are returning to home page. For handling all of the above buttons click we have the three methods as mention below:

Method 1 - Submit the form for each button

In this way each submit button will post the form to server but provides the different values - Save, Submit and NULL respectively for the commands. On the basis of command name we can implement our own logic in the controller's action method.

MultipleCommand.cshtml

  1. @using (Html.BeginForm("MultipleCommand", "Home", FormMethod.Post, new { id = "submitForm" }))
  2. {
  3. <fieldset>
  4. <legend>Registration Form</legend>
  5. <ol>
  6. <li>
  7. @Html.LabelFor(m => m.Name)
  8. @Html.TextBoxFor(m => m.Name, new { maxlength = 50 })
  9. @Html.ValidationMessageFor(m => m.Name)
  10. </li>
  11. <li>
  12. @Html.LabelFor(m => m.Address)
  13. @Html.TextAreaFor(m => m.Address, new { maxlength = 200 })
  14. @Html.ValidationMessageFor(m => m.Address)
  15. </li>
  16. <li>
  17. @Html.LabelFor(m => m.MobileNo)
  18. @Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })
  19. @Html.ValidationMessageFor(m => m.MobileNo)
  20. </li>
  21. </ol>
  22. <button type="submit" id="btnSave" name="Command" value="Save">Save</button>
  23. <button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>
  24. <button type="submit" id="btnCancel" name="Command" value="Cancel" onclick="$('#submitForm').submit()">Cancel (Server Side)</button>
  25. </fieldset>
  26. }

Action Method in Controller


Method 2 - Introducing Second From

We can also introduce the second form for handling Cancel button click. Now, on Cancel button click we will post the second form and will redirect to the home page.

MultipleCommand.cshtml

  1. @using (Html.BeginForm("MultipleCommand", "Home", FormMethod.Post, new { id = "submitForm" }))
  2. {
  3. <fieldset>
  4. <legend>Registration Form</legend>
  5. <ol>
  6. <li>
  7. @Html.LabelFor(m => m.Name)
  8. @Html.TextBoxFor(m => m.Name, new { maxlength = 50 })
  9. @Html.ValidationMessageFor(m => m.Name)
  10. </li>
  11. <li>
  12. @Html.LabelFor(m => m.Address)
  13. @Html.TextAreaFor(m => m.Address, new { maxlength = 200 })
  14. @Html.ValidationMessageFor(m => m.Address)
  15. </li>
  16. <li>
  17. @Html.LabelFor(m => m.MobileNo)
  18. @Html.TextBoxFor(m => m.MobileNo, new { maxlength = 10 })
  19. @Html.ValidationMessageFor(m => m.MobileNo)
  20. </li>
  21. </ol>
  22. <button type="submit" id="btnSave" name="Command" value="Save">Save</button>
  23. <button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>
  24. <button type="submit" id="btnCancelSecForm" name="Command" value="Cancel" onclick="$('#cancelForm').submit()"> Cancel (Server Side by Second Form)</button>
  25. </fieldset>
  26. }
  27. @using (Html.BeginForm("MultipleButtonCancel", "Home", FormMethod.Post, new { id = "cancelForm" })) { }

Action Method in Controller


Method 3 - Introducing Client Side Script

We can also use javascript or jquery for handling Cancel button click. Now, on Cancel button click we will directly redirect to the home page. In this way, there is no server side post back and this is the more convenient way to handle the cancel button click.

MultipleCommand.cshtml

  1. <button type="submit" id="btnSave" name="Command" value="Save">Save</button>
  2. <button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>
  3. <button name="ClientCancel" type="button" onclick=" document.location.href = $('#cancelUrl').attr('href');">Cancel (Client Side)</button>
  4. <a id="cancelUrl" href="@Html.AttributeEncode(Url.Action("Index", "Home"))" style="display:none;"></a>

ASP.NET MVC – Multiple buttons in the same form

I keep seeing this question in forums and on twitter so I thought I’d post all the various ways you can handle this and what the pros and cons are.

The Scenario

Imagine you have a user signup form. There are several textbox fields for entering the new account information and then two buttons: Signup and Cancel. Signup will process the account information and Cancel will return the user to the home page.

Option 1 – Each button submits the form but provides a different value

~/Views/Account/Register.aspx
  1: <% using (Html.BeginForm()) { %>
  2:     <div>
  3:         <fieldset>
  4:             <legend>Account Information</legend>
  5:             <p>
  6:                 <label for="username">Username:</label>
  7:                 <%= Html.TextBox("username") %>
  8:                 <%= Html.ValidationMessage("username") %>
  9:             </p>
 10:             <p>
 11:                 <label for="email">Email:</label>
 12:                 <%= Html.TextBox("email") %>
 13:                 <%= Html.ValidationMessage("email") %>
 14:             </p>
 15:             <p>
 16:                 <label for="password">Password:</label>
 17:                 <%= Html.Password("password") %>
 18:                 <%= Html.ValidationMessage("password") %>
 19:             </p>
 20:             <p>
 21:                 <label for="confirmPassword">Confirm password:</label>
 22:                 <%= Html.Password("confirmPassword") %>
 23:                 <%= Html.ValidationMessage("confirmPassword") %>
 24:             </p>
 25:                 <button name="button" value="register">Register</button>
 26:                 <button name="button" value="cancel">Cancel</button>
 27:             </p>
 28:         </fieldset>
 29:     </div>
 30:  <% } %>
~/Controllers/AccountController.cs
  1: [AcceptVerbs(HttpVerbs.Post)]
  2: public ActionResult Register(string button, string userName, string email, string password, string confirmPassword)
  3: {
  4:     if (button == "cancel")
  5:         return RedirectToAction("Index", "Home");
  6: 
  7:     ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
  8: 
  9:     if (ValidateRegistration(userName, email, password, confirmPassword))
 10:     {
 11:         // Attempt to register the user
 12:         MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email);
 13: 
 14:         if (createStatus == MembershipCreateStatus.Success)
 15:         {
 16:             FormsAuth.SignIn(userName, false /* createPersistentCookie */);
 17:             return RedirectToAction("Index", "Home");
 18:         }
 19:         else
 20:         {
 21:             ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus));
 22:         }
 23:     }
 24: 
 25:     // If we got this far, something failed, redisplay form
 26:     return View();
 27: }
The downside to this solution is that you have to add some yucky conditional logic to your controller and all the form data has to be submitted to the server just so the server can issue a redirect. To make the controller code a little better you could implement a custom ActionMethodSelectorAttribute like this:
  1: public class AcceptParameterAttribute : ActionMethodSelectorAttribute
  2: {
  3:     public string Name { get; set; }
  4:     public string Value { get; set; }
  5: 
  6:     public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
  7:     {
  8:         var req = controllerContext.RequestContext.HttpContext.Request;
  9:         return req.Form[this.Name] == this.Value;
 10:     }
 11: }
 12: 
Now I can split into two action methods like this:
  1: [ActionName("Register")]
  2: [AcceptVerbs(HttpVerbs.Post)]
  3: [AcceptParameter(Name="button", Value="cancel")]
  4: public ActionResult Register_Cancel()
  5: {
  6:     return RedirectToAction("Index", "Home");
  7: }
  8: 
  9: [AcceptVerbs(HttpVerbs.Post)]
 10: [AcceptParameter(Name="button", Value="register")]
 11: public ActionResult Register(string userName, string email, string password, string confirmPassword)
 12: {
 13:   // process registration
 14: }
Again, this isn’t the most efficient method but it does let you handle different buttons with different controller methods.

Option 2 – A second form

  1: <% using (Html.BeginForm()) { %>
  2:     <div>
  3:         <fieldset>
  4:             <legend>Account Information</legend>
  5:             <p>
  6:                 <label for="username">Username:</label>
  7:                 <%= Html.TextBox("username") %>
  8:                 <%= Html.ValidationMessage("username") %>
  9:             </p>
 10:             <p>
 11:                 <label for="email">Email:</label>
 12:                 <%= Html.TextBox("email") %>
 13:                 <%= Html.ValidationMessage("email") %>
 14:             </p>
 15:             <p>
 16:                 <label for="password">Password:</label>
 17:                 <%= Html.Password("password") %>
 18:                 <%= Html.ValidationMessage("password") %>
 19:             </p>
 20:             <p>
 21:                 <label for="confirmPassword">Confirm password:</label>
 22:                 <%= Html.Password("confirmPassword") %>
 23:                 <%= Html.ValidationMessage("confirmPassword") %>
 24:             </p>
 25:             <p>
 26:                 <button name="button">Register</button>
 27:                 <button name="button" type="button" onclick="$('#cancelForm').submit()">Cancel</button>
 28:             </p>
 29:         </fieldset>
 30:     </div>
 31: <% } %>
 32: <% using (Html.BeginForm("Register_Cancel", "Account", FormMethod.Post, new { id="cancelForm" })) {} %>
 33: 
All I did here was add a new form after the registration form and point it at my other controller action. I then changed the cancel button to type=”button” so that it would try to submit the form it was sitting in and added an onlick that uses a simple jQuery expression to submit my other “cancel” form. This is more efficient now that it wont submit all the registration data but it is still not the most efficient since it is still using the server to do a redirect.

Option 3: All client side script

  1: <p>
  2:     <button name="button">Register</button>
  3:     <button name="button" type="button" onclick="document.location.href=$('#cancelUrl').attr('href')">Cancel</button>
  4:     <a id="cancelUrl" href="<%= Html.AttributeEncode(Url.Action("Index", "Home")) %>" style="display:none;"></a>
  5: </p>
  6: 
This is the most efficient way to handle the cancel button. There is no interaction with the server to get the url to redirect to. I rendered a hidden <a> tag to contain the url but still used the <button> and some script so that the cancel option still looked like a button on the form. It would also work if I just displayed the <a> tag instead of the button. I’ve noticed several sites that have buttons for actions that submit data and links for actions like cancel that do not. I bet it has to do with this same sort of problem.

Monday, 2 September 2013

Popup

    <div id="pnlHowItWorks" class="customPopup">
        <div class="customPopup-bgShadow">
        </div>
        <div class="customPopupInner">
            <div class="popup-top">
                <img src="<%= Page.ResolveUrl("~/images/popup-top.png") %>" alt="" /></div>
            <div class="popup-bg">
                <div class="popup-close">
                    <img src="<%= Page.ResolveUrl("~/images/close.png") %>" onclick="hideHow();" alt=""
                        style="cursor: pointer;" />
                </div>
                <div class="popup-in">
                    <h6>
                        &nbsp;</h6>
                </div>
                <div class="faq">
                    <asp:Literal runat="server" ID="LtHowItWorks"></asp:Literal></div>
            </div>
            <div class="popup-top">
                <img src="<%= Page.ResolveUrl("~/images/popup-bot.png") %>" alt="" /></div>
        </div>
    </div>css
   .customPopup
        {
            display: none;
            float: left;
            width: 100%;
            height: 100%;
            opacity: 1;
            z-index: 999999;
            left: 0px;
            top: 0px;
            position: absolute;
        }
        .customPopupInner
        {
            width: 806px;
            z-index: 100000;
            margin: auto;
            position: relative;
            padding-top: 130px;
        }
        .customPopup-bgShadow
        {
            background: url(../images/bg-outer-shdow.png);
            height:  100%;
            left: 0;
            position: fixed;
            top: 0;
            width: 100%!important;
            z-index: 99999;
        }

Image Slider

http://wowslider.com/automatic-jquery-slider-noir-squares-demo.html
http://www.dynamicdrive.com/dynamicindex14/index.html