3

I am trying to update records in a database using AJAX requests. I'm able to insert using similar to the below, but am not successful when I attempt to update or delete.

Here is my ajax PUT method:

$('#updateCr').click(function(e) {
    e.preventDefault();
    var updatedData = {
        CrId: $('#CrId').val(),
        CrName: $('#CrName').val(),
        CrStatus: $('#CrStatus').val(),
        CrPriority: $('#CrPriority').val(),
        CrTitle: $('#CrTitle').val(),
        CrDescription: $('#CrDescription').val()
    };
    console.log(changeRequest);

    $.ajax({
        type: "PUT",
        url: "@Url.Action("MyControllerAction", "Home")",
        content: "application/json; charset=utf-8",
        dataType: "json",
        data: updatedData,
        cache: false,
        success: function(d) {
            if (d.success == true)
                window.location = "index.html";
            else {}
        },
        error: function(xhr, textStatus, errorThrown) {
            // TODO: Show error
        }
    });

And here is my Controller

[HttpPut]
public JsonResult MyControllerAction(UpdatedDataObject updatedData)
{
    try
    {
        myModel.UpdateDataMethod(updatedData);
    }
    catch (Exception e)
    {
        var theerrror = e.ToString();
        return Json(new { result = theerrror });
    }

    return Json(new { result = "Success" });
}

When submitting the data, the controller is triggered, but it is not receiving a JSON object. What am I doing wrong here?

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
mbuchok
  • 391
  • 6
  • 18
  • 1
    Have you checked the response in the console or at least stepped through the C# code to see if any errors are thrown? – Rory McCrossan Feb 24 '16 at 16:43
  • Yes, the console is showing a json object, and I've stepped through the C# code... no errors are thrown, the controller is simply not receiving the JSON object I'm trying to pass to it. – mbuchok Feb 24 '16 at 16:45
  • 2
    The issue is a typo. The returned JSON property is called `result`. In your JS code you use `success` – Rory McCrossan Feb 24 '16 at 16:47
  • PUT would normally have this signature: `MyControllerAction(int id, UpdatedDataObject updatedData)` – Mark Schultheiss Feb 24 '16 at 17:30

3 Answers3

3

The issue is a typo. The returned JSON property is called result. In your JS code you use success. Also note that you're sending application/x-www-form-urlencoded data, not application/json. Thankfully this isn't an issue as the ModelBinder will work for both types of request. Try this:

$.ajax({
    type: "PUT",
    url: "@Url.Action("MyControllerAction", "Home")",
    dataType: "json",
    data: updatedData,
    cache: false,
    success: function(d) {
        if (d.result) {
            window.location.assign("index.html");
        } else { 
            console.log('do something constructive with the error here...');
        }
    },
    error: function(xhr, textStatus, errorThrown) {
        // TODO: Show error
    }
});

Finally, it seems a little redundant to redirect the user to another screen when the result of the AJAX request is successful. If that is the behaviour you require, then the point of AJAX is moot and you may as well use a standard form submission.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • So this works, but only when I set the type to: "POST" ... it'll work for me for now, but seems odd that it'll hit the controller action for one but not the other... and yes I changed the attributes to their respective types when testing. At any rate, thanks for your answer. This works so I'll mark it as correct. – mbuchok Feb 24 '16 at 17:11
1

I've found that including JSON.stringify() often solves these sorts of issues for me

data: JSON.stringify(updatedData),

total code would look like this:

$.ajax({
    type: "PUT",
    url: "@Url.Action("MyControllerAction", "Home")",
    content: "application/json; charset=utf-8",
    dataType: "json",
    data: JSON.stringify(updatedData),
    cache: false,
    success: function(d) {
    if (d.success == true)
    window.location = "index.html";
    else {}
         },
         error: function(xhr, textStatus, errorThrown) {
    // TODO: Show error
  }
});
Nathan Koop
  • 24,803
  • 25
  • 90
  • 125
0

In addition to what's been provided above, note that if the verb headers for PUT and DELETE don't work, see response provided here:

ASP.NET Web API - PUT & DELETE Verbs Not Allowed - IIS 8

Essentially all you need is this:

  <system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
  <remove name="WebDAVModule"/>
  <remove name="FormsAuthentication" />
</modules>
<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

Community
  • 1
  • 1
mbuchok
  • 391
  • 6
  • 18