Tuesday, April 16, 2013

Returning a partial view on a MVC Ajax Form submit


In my previous post we talked about returning a Json object on a MVC Ajax form submit. There we had to write several Java-Script methods in order to process the response. In that case it was just about whether are registration (form1) was successful or not. But assume we need to show another form (form2) (without redirection), do some data filling there and submit it and that all these things have to be in Ajax.

One way you could achieve this, is to have both these forms in our html page and do a jquery show  and a hide on those forms. below given is the javascript code if are implementing this in our previous example.
function RegisterSuccess(data) {
    try {   
        if (data.Status == "0") {          
            $('#form1').hide();
            $('#form2').show();          
        } else {           
            $(".msg").addClass('error');
            $(".msg").html(data.Message);
        }
    } catch (e) {
    }
}

If we need to auto fill up some of the information in form2 from the database, we need to write javascript code to set the values for each of those fields. I remeber Scott Hanselman , saying "People who can read java-scripts are weird people!" (people who write too!) in one of this videos. So what if a js library writes all these javascripts for us and that we only need to return a view. Yes, Ajax.BeginForm takes care of all that. You just need to set the UpdateTargetId and the LoadingElementId parameters.

Ok now. Time for some coding! This is how are razor view look like.
@model AjaxMvc4.Models.RegisterModel
@{
    ViewBag.Title = "Register";
}

@ViewBag.Title.

Create a new account.

@using (Ajax.BeginForm("Register", "Account", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "formContent", LoadingElementId = "loader" })) { @Html.AntiForgeryToken() @Html.ValidationSummary()
Registration Form
  1. @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName)
  2. @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password)
  3. @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword)
}
@section Scripts { @Scripts.Render("~/bundles/jqueryval") }


In the controllers instead of returning a Json object we return a partial view. We can even pass a model and set if we need to fill some of the information in the new form (either from the database or from the previous model posted).



        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                try
                {
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password);
                    WebSecurity.Login(model.UserName, model.Password);

                    UserModel user = new UserModel();
                    user.UserName = model.UserName;

                    return PartialView("_UserContactDetailsPartial", user);               
                }
                catch (MembershipCreateUserException e)
                {                   
                    ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
                }
            }
            return PartialView("_ErrorPartial");    
        }

User Details Partial View :
@model AjaxMvc4.Models.UserModel





@using (Ajax.BeginForm("Account", "ContactInformation", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "formContent", LoadingElementId = "loader" }))
{
    @Html.ValidationSummary(true)

    
Contact Details
User Name
@Html.DisplayFor(model => model.UserName) @Html.HiddenFor(model => model.UserName)
First Name
@Html.EditorFor(model => model.FirstName) @Html.ValidationMessageFor(model => model.FirstName)
Last Name
@Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName)
Email Address
@Html.EditorFor(model => model.Email) @Html.ValidationMessageFor(model => model.Email)
Phone Number
@Html.EditorFor(model => model.PhoneNo) @Html.ValidationMessageFor(model => model.PhoneNo)
Mobile Number
@Html.EditorFor(model => model.Mobile) @Html.ValidationMessageFor(model => model.Mobile)
Address
@Html.EditorFor(model => model.Address) @Html.ValidationMessageFor(model => model.Address)

}
Don't forget to reference the jquery.validate.min.js and jquery.validate.unobtrusive.min.js for your ajax form to work!