之前開發時遇到的一個問題,使用easyui的form提交表單,在Chrome下時沒問題的,但是在IE下出現類似附件下載時提示是否保存的現象。
這里記錄一下如何解決的。其實這個現象不光是easyui的form,還有其他一些form插件也是一樣的,使用不當就會遇到這個問題。
前台:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="keywords" content=""> <meta name="description" content=""> <title></title> <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/default/easyui.css"> <link rel="stylesheet" type="text/css" href="http://www.jeasyui.com/easyui/themes/icon.css"> <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> <script type="text/javascript" src="http://www.jeasyui.com/easyui/jquery.easyui.min.js"></script> </head> <body> <div> <form id="formTest" method="post" action="~/Test/Save"> name: <input type="text" /><br /> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()">submit</a> </form> </div> <script type="text/javascript"> function submitForm() { $('#formTest').form('submit', { success: function(data){ var data = $.parseJSON(data); if (data.result){ alert(data.msg) } } }); } </script> </body> </html>
后台:
public ActionResult Save() { return Json(new { result = true, msg = "Save successful." }); }
結果:
Chrome是這樣↓
IE是這樣↓,不科學啊?
怎么解決?改后台的Action的返回的content-type改為text/html:
public ActionResult Save() { return Json(new { result = true, msg = "Save successful." }, "text/html"); }
為什么?因為JsonReslut默認返回給瀏覽器的content-type類型是:application/json,(←等於沒說)。
奇怪了,我們平時通過jQuery的ajax方法來提交數據、請求數據不都挺正常的嗎,沒出現過這個情況啊,瀏覽器兼容性jQuery已經幫我們處理好了啊,這個easyui的form方法也是無刷新提交表單啊,應該也是ajax吧。問題就在這里,這個easyui的form提交表單並不是真的ajax。我們來看看easyui-form的源碼(正好1.4.2版本的jquery.form.js有源碼):
...省略... function ajaxSubmit(target, options){ var opts = $.data(target, 'form').options; $.extend(opts, options||{}); var param = $.extend({}, opts.queryParams); if (opts.onSubmit.call(target, param) == false){return;} $(target).find('.textbox-text:focus').blur(); //構造了一個iframe var frameId = 'easyui_frame_' + (new Date().getTime()); var frame = $('<iframe id='+frameId+' name='+frameId+'></iframe>').appendTo('body') frame.attr('src', window.ActiveXObject ? 'javascript:false' : 'about:blank'); frame.css({ position:'absolute', top:-1000,//讓我們看不到它 left:-1000 }); frame.bind('load', cb); submit(param); function submit(param){ var form = $(target); if (opts.url){ form.attr('action', opts.url); } var t = form.attr('target'), a = form.attr('action'); form.attr('target', frameId);//把我們要提交的form的target指向構造出來的那個iframe var paramFields = $(); try { for(var n in param){ var field = $('<input type="hidden" name="' + n + '">').val(param[n]).appendTo(form); paramFields = paramFields.add(field); } checkState(); form[0].submit(); } finally { form.attr('action', a); t ? form.attr('target', t) : form.removeAttr('target'); paramFields.remove(); } ...省略...
看我標為紅色的,其他的我現在不關心,就先省略了。
我們看到easyui的作者寫了一個ajaxSubmit方法(不仔細看內容還真以為是一個ajax方法呢)。方法里面動態構造了一個隱藏的iframe,然后把我們要提交的form的target指向了構造出來的這個隱藏的iframe,給這個iframe設置了load事件回調方法用來處理響應。重要的是那句“form[0].submit()”,這是什么,這就是直接在提交表單啊,哪兒有什么ajax,只是保證了頁面無刷新。(好吧,我承認我理解的ajax概念比較狹隘)
IE瀏覽器對於application/json的非ajax的響應的處理比較特殊,我這里指的是相當於你在IE的地址欄上輸入了一個url,而服務器返回的content-type是application/json,我猜是IE默認是不能直接處理application/json的響應,所以就提示下載了。
而Chrome則默認對application/json是當做文本來處理的,所以可以正常顯示。
還有一點需要弄清楚的是ajax,我們看看這個(來自w3school):
我們看出ajax的響應實際上就兩種,一種當做純文本處理,另一種當做xml處理。所以jQuery的ajax默認對於application/json或者text/html都會當做文本處理的,ajax是沒有一種處理方式是“下載保存”的方式的。
這樣應該比較好理解這個問題了。
可以比較一下用真的ajax來提交表單,不管后台返回的是application/json或者text/html處理都是一致的:
function submitForm() { $.post($("#formTest").attr("action"), { name: $("#formTest input[type=text]").val() }, function (response) { alert(response.msg); }); }