3

I'm having some problems with getting a JSON response from an ASP MVC controller method to be processed within jQuery - something that I've tried before without a problem - however I've obviously done something wrong this time and I can't figure out what...

I have a spark view being rendered from ASP MVC 3, calling a controller method which is returning a JsonResult. I've stripped it down to just a success or failure message at the moment until it will actually work. I can follow the method through both paths in debug and the JSON object created looks correct.

[HttpPost]
public JsonResult AdjustmentDetail(AdjustmentPaymentModel adjustment)
{
    try
    {
        //do some other processing
        return Json(new {success = true}, "application/json");
    }
    catch(Exception e)
    {
        return Json(new { success = false, message = e.Message });
    }
}

The controller method is being called from a Spark view, using jQuery to submit the form and capture the result to return some feedback to the user and then provide them some choices from that point on. At the moment, it's just set to pop up an alert so that I can see it receive the JSON and execute the callback function. Again, some inputs on the form have been removed for readability (one plain text box and two text boxes with jQuery datepickers on that appear to be functioning correctly - hence the datepicker functions in the javascript, which I've left in case they might be interfering).

<script>
  $(document).ready(function () {
    $(".datepicker").attr('readOnly', 'true');
  });

  $(function () {
    $('.datepicker').datepicker({
      maxDate: 0,
      dateFormat: 'dd/mm/yy'
    });
  });

  $('document').ready(function () {
    $('#submit-adjustment').submit(function () {
      $('#mini-loader').show();

      $.post('${Url.Action("AdjustmentDetail", "payments")}', { adjustment: Model }, function (d) {
        alert(d);
        $('#mini-loader').hide();
      }, 'json');

      return false;
    });
  });
</script>

<form action='' id='submit-adjustment' method='post'>
  <label for="Notes">
    Notes
    <small>
      <span class="error">${Html.ValidationMessageFor(m => m.Notes)}</span>
    </small>
  </label>

  ${Html.EditorFor(m => m.Notes)}

  ${Html.HiddenFor(m => m.BankAccount)}
  ${Html.HiddenFor(m => m.IsCreditAdjustment)}

  <div style="padding-top:10px;">
    <input class="button big" name="submit-adjustment" type="submit" value="Submit Adjustment" />
    <img src="/Content/Images/mini-loader.gif" id="mini-loader" style="display: none;"/>
  </div>
</form>

In the past, the above has worked - the form posts and then the resulting JSON is processed by the jQuery callback function. In this case however (whether the controller method completes successfully or throws an exception), the JSON is rendered in the browser:

{"success":true}

And when following the Javascript execution in Chrome, the function is either not being called or the JSON render is changing the page before it gets the chance to do so. I've checked the call using Fiddler and the post is responding with a 200, and with a content type of: application/x-www-form-urlencoded

I've been googling this for a while and I'm either unable to express the problem in a google query, or I'm just missing something very simple here! Any help is much appreciated - please let me know if I need to provide any more detail.

Ian Cotterill
  • 1,667
  • 4
  • 18
  • 28
  • It looks like your jQuery is posting to the action `ProcessAdjustment`, but your controller action is `AdjustmentDetail` - do you have a route pointing to that action or a separate action elsewhere? – Ian Routledge Jan 03 '12 at 11:14
  • Ah yes, I changed the controller method name while I was debugging. I've altered it and re-tested, the behaviour is the same and it was routing correctly anyway (which is a little strange...). I'll edit the post above. – Ian Cotterill Jan 03 '12 at 11:17
  • A *response* Content-Type of `application/x-www-form-urlencoded` doesn't make any sense - and you'd want it to be a json content type anyway. A *request* content type sure, but not response. – Duncan Smart Jan 03 '12 at 12:52
  • My mistake, I was taking that from Fiddler - assumed because it was showing along with the 200, it was the response - so it's likely to be the request type. I'm setting the response type in the controller specifically as I've seen various suggestions that the response type is to blame here, but as far as I can tell it is application/json much of my googling seemed to suggest. – Ian Cotterill Jan 03 '12 at 12:58

2 Answers2

1

Change the submit button for a regular button

<input id="Button1" type="button" value="Test" class="btn btn-primary">

and add the jquery to submit.

<script language="javascript" type="text/javascript">
$(document).ready(function () {


    $('#Button1').click(function () {
        alert('here');
        $('#addCustomerForm').submit();
        return false;
    });

});

dfortun
  • 704
  • 6
  • 7
0

It looks like the default event for the form submit is not being prevented by the return false for some reason. Instead of this, add an event argument to the submit handler and a call to event.preventDefault():

$('#submit-adjustment').submit(function (event) {
   event.preventDefault();
   ...
Duncan Smart
  • 31,172
  • 10
  • 68
  • 70
  • Had to change the parameter in the post to this.Model or it thought the model was undefined, but that seems to have fixed it. Thanks very much! – Ian Cotterill Jan 03 '12 at 13:42
  • After a little more playing around, the this.Model part hasn't fixed it (this.Model was always returning a new model, not one from the form) - if I use the preventDefault then I can't access the model, and if I try to do anything before the preventDefault then it will submit the form and ignore the jQuery - the routing was working earlier as the view was named the same as the controller method, so it was submitting and never using the jQuery. Trying to find how I can extract the model, will update if I have any luck. Leaving this as an answer as it actually fixed the original problem. – Ian Cotterill Jan 03 '12 at 16:37
  • Fixed the null model issue by Html.BeginForm and then using var model = $('#submit-adjustment').serialize(); $.post('${Url.Action("AdjustmentDetail", "payments")}', model, function (d, s, x) {... To serialise the model and submit the form. – Ian Cotterill Jan 04 '12 at 12:25