31

I would like to know if there is a specific way to submit a form using jQuery AJAX in MVC6, still using the Auto Binding features of ASP.NET MVC. I believe in other versions of MVC you could use jquery.unobtrusive-ajax and simply use

@using (Ajax.BeginForm("SaveData", new AjaxOptions(){}

Since there have been some changes with MVC6 I am wondering what the new recommended way to do this would be besides doing a normal AJAX post to the server when the form is submitted. This meaning I would manually get the values of each input field, turn them into JSON and send them over to the controller so everything will get bound to the ViewModel.

If I use the following JavaScript for AJAX do any of the AJAX form settings even matter?

$('form').submit(function () {
    $.ajax({
        type: "POST",
        url: "/Products/Create/",
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    });
});
Sami Kuhmonen
  • 30,146
  • 9
  • 61
  • 74
Blake Rivell
  • 13,105
  • 31
  • 115
  • 231

3 Answers3

73

Ajax works the same way, but instead of the @Ajax helper's, use the new MVC 6 Tag Helpers (don't forget to reference 'jquery' and 'jquery.unobtrusive-ajax' scripts).

JQuery Unobtrusive Ajax exists in the Asp.Net GitHub repo and can be Bower pulled.

Using the new MVC TagHelpers, you simply declare the form like the following:

<form asp-controller="Home" asp-action="SaveForm" data-ajax="true" data-ajax-method="POST">
...
</form>

To use the AjaxOptions that existed on the Ajax Helper on previous MVC versions, just add those attributes do the form tag like this:

<form asp-controller="Home" asp-action="SaveForm" data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="#content">
...
</form>
<div id="content"></div>

The HTML attributes (formerly AjaxOptions) that you can use in the form are the following (original source):

+------------------------+-----------------------------+
|      AjaxOptions       |       HTML attribute        |
+------------------------+-----------------------------+
| Confirm                | data-ajax-confirm           |
| HttpMethod             | data-ajax-method            |
| InsertionMode          | data-ajax-mode              |
| LoadingElementDuration | data-ajax-loading-duration  |
| LoadingElementId       | data-ajax-loading           |
| OnBegin                | data-ajax-begin             |
| OnComplete             | data-ajax-complete          |
| OnFailure              | data-ajax-failure           |
| OnSuccess              | data-ajax-success           |
| UpdateTargetId         | data-ajax-update            |
| Url                    | data-ajax-url               |
+------------------------+-----------------------------+

Another significant change is how you check on the server side if the request is indeed an AJAX request. On previous versions we simply used Request.IsAjaxRequest().

On MVC6, you have to create a simple extension to add the same options that existed on previous MVC versions (original source):

/// <summary>
/// Determines whether the specified HTTP request is an AJAX request.
/// </summary>
/// 
/// <returns>
/// true if the specified HTTP request is an AJAX request; otherwise, false.
/// </returns>
/// <param name="request">The HTTP request.</param><exception cref="T:System.ArgumentNullException">The <paramref name="request"/> parameter is null (Nothing in Visual Basic).</exception>
public static bool IsAjaxRequest(this HttpRequest request)
{
  if (request == null)
    throw new ArgumentNullException("request");

  if (request.Headers != null)
    return request.Headers["X-Requested-With"] == "XMLHttpRequest";
  return false;
}
Community
  • 1
  • 1
João Pereira
  • 1,647
  • 15
  • 18
  • Thank you very much for the in depth response. So with all of the above settings I still would have this in my JavaScript right? $('form').submit(function () { $.ajax({ ... }); }); Believe it or not it all worked with no settings specified in the form declaration besides asp-action="Create". Maybe I am misunderstanding what the purpose of 'data-ajax' and 'data-ajax-method' vs just writing the code I used above to get AJAX. Can you tell me how those properties help with my AJAX since it was working without? Or at least seemed like it was working since I ended up in the Create action – Blake Rivell Feb 12 '16 at 15:35
  • At the bottom of my post I pasted my AJAX code. So if you can clear up what these data-ajax helpers are good for vs what I have that would be great. I would like to know if I need both. It would be great if I can still use the built-in Unobtrusive Validation along with AJAX. – Blake Rivell Feb 12 '16 at 15:39
  • 1
    You can remove that piece of javascript code. Just make sure you reference both JQuery and JQuery unobtrusive Ajax. The data-ajax helpers will do that for you under the wood. – João Pereira Feb 12 '16 at 16:00
  • 1
    That a look at the source code for the [JQuery Unobtrusive Ajax](https://github.com/aspnet/jquery-ajax-unobtrusive/blob/master/jquery.unobtrusive-ajax.js) and you will get a clear picture of what are that 'data-ajax' attributes all about. – João Pereira Feb 12 '16 at 16:10
  • Should the #content div be inside the form element? This is how it works in this tutorial: https://damienbod.com/2018/11/09/asp-net-core-mvc-ajax-form-requests-using-jquery-unobtrusive/ – Jess Aug 27 '19 at 13:41
  • 1
    @Jess it doesn't really matter if it is inside, outside or the #content div wraps the form. It all depends on what is returned from the controller. If the controller only returns the form fields, then it should be inside. If the controller only returns a success message, then it should be outside. If the controller return a partial view that contains a form, then the #content must wrap the calling form. Hope it helps! – João Pereira Aug 27 '19 at 13:48
  • There is a nuget package for this: Microsoft.jQuery.Unobtrusive.Ajax – Andrew Sep 13 '19 at 12:45
4

Here's a really nice YouTube tutorial on AJAX forms, and you can download the project from this GitHub link. It contain the script to be used for AJAX.

Sample style copied from the above project:

<form asp-controller="Home1" asp-action="SaveForm" 
      data-ajax="true" 
      data-ajax-method="POST"
      data-ajax-mode="replace" 
      data-ajax-update="#content"
      data-ajax-loading  ="#divloading"
      data-ajax-success="Success"
      data-ajax-failure ="Failure">
    <div class="form-group">
        <div>  <h4>@Html.Label("Name")</h4> </div>
        <div>  @Html.TextBox("Name","",htmlAttributes:new { @class="form-control",id="Name"})</div>
    </div>
    <div class="form-group">
        <div><h4>@Html.Label("Age")</h4></div>
        <div>@Html.TextBox("Age", "", htmlAttributes: new { @class = "form-control", id ="Age" })</div>
    </div>
    <br/>
    <input type="submit" name="Submit"  class="btn btn-block btn-success" />
</form>
BSMP
  • 4,596
  • 8
  • 33
  • 44
Uncle Tech
  • 84
  • 5
  • Does anybody know how to grab the response from the "data-ajax-failure" callback? I am throwing custom Exceptions on the backend and want to show custom error feeback to the user based on the Exception Type in the response. But I just cannot figure out how to grab the response in the callback. This must be possible. No? – Sam Jun 28 '18 at 13:33
2

https://github.com/Behrouz-Goudarzi/AjaxTagHelper

AjaxTagHelper

A simple solution to using links and ajax forms using Tag Helper in aspnet core

First, copy the AjaxTagHelper class from the Extensions folder to your project.

Second, copy the AjaxTagHelper.js file from js folder in wwwroot and add it to your project.

Then do the following: Open the viewImports file and add the following code

@using AjaxTagHelper.Extensions
@using AjaxTagHelper
@using AjaxTagHelper.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, AjaxTagHelper

To use Action Ajax, add the following code instead of the tag.

  <ajax-action ajax-action="Delete" ajax-controller="Home" ajax-data-id="@Model.Id"
                 class="btn btn-danger btn-sm" ajax-success-func="SuccessDelete">
        Delete
    </ajax-action>

Use the following code to use AJAX to send the form to server.

<div class="row">
    <form id="frmCreate" class="col-sm-9">
        <div class="row">
            <div class="col-sm-4 form-control">
                <input placeholder="Enter Name" name="Name" class="input-group" type="text" />
            </div>
            <div class="col-sm-4 form-control">
                <input placeholder="Enter Family" name="Family" class="input-group" type="text" />
            </div>
            <div class="col-sm-4 form-control">
                <input placeholder="Enter Email@site.com " name="Email" class="input-group" type="email" />
            </div>
        </div>
    </form>
    <div class="col-sm-3">
        <ajax-button ajax-controller="Home" ajax-action="Create" ajax-form-id="frmCreate" ajax-success-func="SuccessCreate"
                     class="btn btn-sm btn-success">
            Create
        </ajax-button>
    </div>
</div>

Finally, add the scripts you need to view it, check the code below

<script>
    function SuccessCreate(data) {
        console.log(data);
        $("#tbodyPerson").append(data);


    }
    function SuccessDelete(data) {
        $("#tr" + data.id).fadeOut();
    }
</script>
<script src="~/js/AjaxHelper.js"></script>
  • While this may answer the question, [it would be preferable](http://meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Rallen May 23 '19 at 14:01
  • I made the changes, okay? @Rallen – Behrouz Goudarzi May 23 '19 at 14:18