1

I'm returning some Json via a C# MVC Controller. Other browsers work fine, but Internet Explorer (IE9) tries to Save the returned Json data as a Text file. Any ideas how to keep this from happening?

//MVC Controller Code...
return Json(new { redirectToUrl = Url.Action("Create", "Album",
                  new { url = url, isLocalFile = isLocalFile})});

//Clientside Javascript Code
$("#uploadImageForm").ajaxForm({
  beforeSubmit: function () {

  },
  success: function (data, textStatus, xhr) {
          window.location.href = data.redirectToUrl;
  },
  error: function (data, textStatus, xhr) {
  } 
});

I've tried adding "text/plain" and "text/json" to the second argument of the return Json method, it doesn't work.

Many thanks!

Hairgami_Master
  • 5,429
  • 10
  • 45
  • 66
  • This probably has more to do with the headers being returned from the server than the way you're calling it client-side. – StriplingWarrior Jun 15 '12 at 22:58
  • 2
    may be a duplicate of: http://stackoverflow.com/questions/2483771/how-can-i-convince-ie-to-simply-display-application-json-rather-than-offer-to-do – Jesse Jun 15 '12 at 23:02

2 Answers2

2

Quote from the documentation of the jquery.form plugin:

Browsers that support the XMLHttpRequest Level 2 will be able to upload files seamlessly and even get progress updates as the upload proceeds. For older browsers, a fallback technology is used which involves iframes since it is not possible to upload files using the level 1 implmenentation of the XMLHttpRequest object. This is a common fallback technique, but it has inherent limitations. The iframe element is used as the target of the form's submit operation which means that the server response is written to the iframe. This is fine if the response type is HTML or XML, but doesn't work as well if the response type is script or JSON, both of which often contain characters that need to be repesented using entity references when found in HTML markup.

To account for the challenges of script and JSON responses when using the iframe mode, the Form Plugin allows these responses to be embedded in a textarea element and it is recommended that you do so for these response types when used in conjuction with file uploads and older browsers. Please note, however, that if there is no file input in the form then the request uses normal XHR to submit the form (not an iframe). This puts the burden on your server code to know when to use a textarea and when not to.

This means that if your form contains file input fields and you are submitting this form to a controller action that returns JSON, you must wrap this JSON in a <textarea> tags.

So your response should not look like this:

{ "redirectToUrl":"some url" }

it should look like this:

<textarea>{ "redirectToUrl":"some url" }</textarea>

In order to achieve that you could use a custom action result that will wrap the response with those tags:

public class TextareaJsonResult : JsonResult
{
    public TextareaJsonResult(object data)
    {
        this.Data = data;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var response = context.HttpContext.Response;
        bool shouldWrap = !context.HttpContext.Request.IsAjaxRequest();
        if (shouldWrap)
        {
            response.Write("<textarea>");
        }

        base.ExecuteResult(context);

        if (shouldWrap)
        {
            response.ContentType = "text/html";
            response.Write("</textarea>");
        }
    }
}

and then have your controller action return this custom result:

[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
    // ... some processing

    var redirectToUrl = Url.Action(
        "Create", 
        "Album",
        new { url = url, isLocalFile = isLocalFile }
    );
    return new TextareaJsonResult(new { redirectToUrl = redirectToUrl });
}

Now obviously in your AJAX success callback you also need to account for this difference by testing the typeof result and in the case of a legacy browser (such as Internet Explorer) manually parse the response. You may take a look at the source code of the page I have linked to.

But this being said, I can see that in your success callback you are redirecting to a controller action contained in the JSON response returned by the server. Here comes my question: What's the point of using AJAX in the first place if you are going to redirect? Why don't you use a standard form post to the controller action and have the controller action directly perform the redirect? AJAX should be used when you want to stay on the same page.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

I agree with Jesse's comment, this is probably a duplicate of the link he provided.

As such I'll provide an alternative. I prefer to view json coming over the wire using a http proxy similar to fiddler http://www.fiddler2.com/fiddler2/ . I mention fiddler because it works with all browsers. The advantage is that you get a treeview of the parsed json. It's MUCH easier to read and find what you're looking for.

Also, I believe firebug for firefox, chrome dev tools, and ie dev tool all provide the same functionality. (I know chrome has the treeview, I think I remember firebug having it, and I would be surprised if modern IE doesn't have it considering the other 2 do.)

Kenneth Ito
  • 5,201
  • 2
  • 25
  • 44