jQuery ajaxForm returning .json file
Asked Answered
P

8

11

I've got a model creation form in rails which I also have returning JSON through ajax. My code so far look like:

$('#new_stem').ajaxForm({ //#new_stem is my form
  dataType: 'json',
  success: formSuccess
});

function formSuccess(stemObj) {
  //does stuff with stemObj
}

And I have a multipart form with a file uploader (but I'm not sure if that is relevant).

When I submit the form it works fine (my models are properly being created and renders as json), but instead of the json getting handled by the formSuccess function, it prompts a download for "stems.json" (the path to my stem creation action) in Firefox.

What would cause this to happen, and what could solve it? Not sure if this is part of the problem, but I don't have a submit button in my form, I have a link with a click handler that calls $('#new_stem).submit()

Thanks guys!

EDIT: Firebug tells me the header contains the following:

Etag        "b53e5247e7719cf6b1840e2c6e68781c"
Connection      Keep-Alive
Content-Type    application/json; charset=utf-8
Date        Mon, 03 May 2010 02:19:31 GMT
Server      WEBrick/1.3.1 (Ruby/1.8.7/2010-01-10)
X-Runtime       241570
Content-Length  265
Cache-Control   private, max-age=0, must-revalidate

plus a cookie header

Perfume answered 3/5, 2010 at 2:8 Comment(1)
I am thinking that this has to do with the file upload aspect. If I navigate directly to a json file with Firefox the same prompt opens, and I know that in order to upload a file through ajax a seperate iframe has to be created which submits a form. I think the iframe is just navigating to that json file afterwards and firefox tries to handle it as a download. Are there any server-side options I can alter to make it think it is not a download?Perfume
P
2

Though not exactly what I was aiming to solve, I was able to come to a slightly different solution that suited my needs!

As ajax file uploads are done through iframes, the issue was that after the iframe loaded the .json file, it was interpreted by Firefox as a download and a download prompt was opened. I am pretty sure I could have played with some server settings to prevent this, but I've already sunk enough time into this.

So what I did was rendered the output as text instead of json because I was only really fishing for one id number anyway. My code now looks like:

$(document).ready(function() {
  $('#continue-upload').click(function() {
    $('#new_stem').ajaxSubmit({
      dataType: 'text', //'json',
      success: formSuccess
    });
  });
});

The id number I needed also came wrapped in pre tags, so I needed to strip those off in my results function as well.

This does what I want it to now, woo!

Perfume answered 3/5, 2010 at 5:44 Comment(0)
M
8

To prevent browser to trigger download of .json file set Content-type header to "text/html".

PHP:

header("Content-type: text/html");

ASP.NET MVC:

return Json(obj, "text/html");

In javascript you need to parse text result, like this:

$(".addform").ajaxSubmit({
            url: "file.php",
            type: "POST",
            dataType: "text",
            iframe: true,
            success: function (text) {
                var data = $.parseJSON(text);
            },
            error: function (xmlRequest, textStatus, errorThrown) {
                alert(errorThrown);
            }
        });

Works perfectly.

Muscat answered 9/8, 2010 at 13:19 Comment(1)
This will cause problems when your response contains the character < (or & in certain cases), since the HTML parser will rightly do some error correction.Tobietobin
C
2

This plugin will allow you to submit MultiPart Forms using ajax.

If you want to use the Ajax 'success:' option you have to submit the form using ajax. Currently you are using the submit() function which basically just submits the form in the traditional way. The fact that you are able to see the json data as a downloaded file or in your browsers means that this is happening.

You need to use that plugin(if you need the multipart function - otherwise just use the regular Ajax function)

With the plugin, you would use it like this :

$("#SubmitButton").click(function() {

  $.ajaxFileUpload({
    url: serverurl,
    secureuri: false,
    fileElementId: elementId,
    dataType: 'json',
    success: function(data, status) {
      /* show success message */
    },
    error: function(data, status, e) {
      /* handle error */
    }
  });
});

If you want to do it without the file upload, there is an easier way to do it.

$("#SubmitButton").click(function() {
  $.post('YOUR_URL', $("#FormName").serialize(), function(data) {
    alert(data.name); // John
  }, "json"); //specify return data is going to be json
});
Cristiano answered 3/5, 2010 at 3:37 Comment(6)
the ajaxForm plugin does allow for file uploads, and those run successfully. I believe it also hooks into the .submit() event, but I altered my click handler to call .ajaxSubmit() instead. Same results unfortunately!Perfume
going to give this plugin a try as well!Perfume
It doesn't look like this plugin gives me any control over the structure of my post data. As this is rails, it needs to be send over in a specific wayPerfume
check : #670820 -- Using the $('#frmSearch').bind -- this person was able to get the same thing to work. Read the correct answer on the page. if you're using ajaxSubmit I hope you're also using the - jQuery Form Plugin(jquery.malsup.com/form) with it.Cristiano
It seems to me now that the submission isn't the problem, but Firefox handles the returning .json file as if it was a download (as ajax uploads are done through iframes). I need to come up with a way to make firefox open it in the browser instead of as a downloadPerfume
file-extensions.org/… File extension JSON description: "File extension .json is used by Mozilla Firefox web browser. Used by Mozilla Firefox from version 3.0 for bookmark backup in JSON format. " using php I would generally just output a proper json formatted string from a regular php page with a .php extension and jquery takes it without any issues and processes it as json.Cristiano
P
2

Though not exactly what I was aiming to solve, I was able to come to a slightly different solution that suited my needs!

As ajax file uploads are done through iframes, the issue was that after the iframe loaded the .json file, it was interpreted by Firefox as a download and a download prompt was opened. I am pretty sure I could have played with some server settings to prevent this, but I've already sunk enough time into this.

So what I did was rendered the output as text instead of json because I was only really fishing for one id number anyway. My code now looks like:

$(document).ready(function() {
  $('#continue-upload').click(function() {
    $('#new_stem').ajaxSubmit({
      dataType: 'text', //'json',
      success: formSuccess
    });
  });
});

The id number I needed also came wrapped in pre tags, so I needed to strip those off in my results function as well.

This does what I want it to now, woo!

Perfume answered 3/5, 2010 at 5:44 Comment(0)
M
2

Actually the ajaxSubmit code for that plugin is slightly hacky. To make ajaxSubmit work (at time of writing) your server must return JSON data as content-type=text/html. The plugin will automatically pull off the <\pre> tags etc (see source). I guess when they were trying to get the hidden iframe to pull json back they decided to treat json a text and parse it off the iframe.

Milkman answered 6/1, 2011 at 6:3 Comment(0)
A
1

Sounds like as if its Content-Type response header is incorrect and thus the browser doesn't know what to do with it. It should be application/json. You can use the Firebug's Net panel to detemine the actual response headers.

Accentor answered 3/5, 2010 at 2:12 Comment(5)
I took a look at the incoming headers with firebug, which contains Content-Type application/json; charset=utf-8Perfume
OK, I'd update the question to include that.. It's one of the first what one would think about when a download prompt unexpectedly pops. How about Content-Disposition? No attachment?Accentor
Headers looks fine. I'll do a shoot in the dark: what if you change dataType to jsonp? This is however normally only used for crossdomain JSON requests, but this changes the way how JSON is processed.Accentor
it doesn't look like ajaxForm supports jsonpPerfume
You finally fixed it by changing to dataType to text. I find this pretty strange. How about the other browsers? Isn't this some Firefox configuration issue?Accentor
F
0

Are you cancelling the default action of the submit event? It sounds like the form is actually being submitted (in the classical sense – in other words, Firefox is actually navigating to the page specified in the form's action).

Friedrick answered 3/5, 2010 at 2:38 Comment(2)
As far as I know, ajaxForm already takes care about that.Accentor
Ah -- I've never used ajaxForm. Perhaps fire up Fiddler to see if multiple requests are getting generated?Friedrick
A
0

Maybe it helps

$('#cpFileUpload').ajaxForm({
        dataType: 'html',           
        success: function(data) {           
            eval(data);                 
            if (data.result == false) {
                alert('error on server side');
            } else {                
                // do what you want
            }
        }       
    }); 

And on server side the output must be like this (only this output or without any other text inside body tag)

var data = {result: true, html: 'ok'}

Not so nice, but working

Amazon answered 20/6, 2010 at 22:13 Comment(0)
A
0

Easy way:

$('#new_stem').ajaxForm({
dataType: 'text',
complete: function(xhr) {
    data = JSON.parse(xhr.responseText);
}});
Armrest answered 9/10, 2018 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.