Thursday, December 10, 2015

ASP.NET MVC: Posting to controller method with an Ajax call

Points of Interest

  • GET method for displaying form using a Razor view that contains JavaScript for POSTing data asynchronously.
  • POST method for saving changes - a regular ASP.NET MVC Controller method that returns JSON
  • jQuery $.post for posting values to the POST method
  • $.post is a shortcut method for .ajax
  • See $.get and $.load shortcut methods for GETting data from the Server
  • $.load retrieves and loads data into a DOM element in one shot. For example, retrieve a partial view from server display in a div.

Model

public class ContactViewModel
{
[Required]
public string Name { get; set; }
[Required]
public string Phone { get; set; }
}

Controller

public class HomeController : Controller
{
// Display the form for user entry
[HttpGet]
public ActionResult Index(ContactViewModel model)
{
return View(model);
}

// Invoked with an Ajax Call from the form
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Index(ContactViewModel model, FormCollection collection)
{
if (ModelState.IsValid)
{
// all good, save changes, return any data you want to show to user via js
return Json(new { success = true });
}

// validation failed - set status code and return error information
Response.StatusCode = (int) HttpStatusCode.BadRequest;
return Json(new { success = false, error = "Validation failed" });
}
}

View

@model ASPNetMVCAjaxPost.Models.ContactViewModel
@{
    ViewBag.Title = "Contact Form";
}

<h3>Contact Form</h3>

@using (Html.BeginForm("Index", "Home", FormMethod.Post,
    new { @class = "form-horizontal", role = "form", name = "ContactForm" }))
{
    @Html.AntiForgeryToken()
    <div class="form-group">
        @Html.LabelFor(m => m.Name, new { @class = "col-sm-2 control-label" })
        <div class="col-sm-10">
            @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.Phone, new { @class = "col-sm-2 control-label" })
        <div class="col-sm-10">
            @Html.TextBoxFor(m => m.Phone, new { @class = "form-control" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
}


@section Scripts {
<script>
function fmtJSON(data) {
    return JSON.stringify(data, null, 2);
}

$(
function () {
    $('form').submit(
        function (event) {
            event.preventDefault();
                var formData = $('form').serializeArray();
                var url = '/Home/Index';
                var posting = $.post(url, formData);
                posting.done(function (data, textStatus, jqXHR) {
                    alert("DONE handler\ndata:\n" + fmtJSON(data) +
                        "\ntextStatus:\n" + textStatus +
                        "\njqXHR:\n" + fmtJSON(jqXHR));
                });
                posting.fail(function (jqXHR, textStatus, errorThrown) {
                    alert("FAIL handler\njqXHR:\n" + fmtJSON(jqXHR) +
                        "\ntextStatus:\n" + textStatus +
                        "\nerrorThrown:\n" + errorThrown);
                });
            }
            );
    }
    );
</script>
}

Form

Failure



Success



Failure - Unhandled Error by Controller Method

Example: Invalid Antiforgery token, authorization failure, etc.