zoukankan      html  css  js  c++  java
  • 让UpdatePanel支持上传文件:解决当页面显式设置document.domain时提示的500错误

        最近在做一个项目,需要在UpdatePanel中上载文件,在网络上找了一下,发现有老赵写的AjaxUploadHelper,一开始工作的很好;开发时使用localhost来进行测试的,一切正常;但部署到正式环境后,噩梦开始了,所有在UpdatePanel内的异步操作都不正常,都提示如下信息:

    Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred while processing the request on the server. The status code returned from the server was: 500

    一开始以为是开发环境与正式环境不同导致服务器端输出HTTP 500的错误呢,但怎么也找不到服务器上有关异常的日志信息,后来偶然把上载文件的控件设置为Visible = false,竟然不报这个错了,一切正常;研究了一下AjaxUploadHelper这个控件,是使用iframe来提交的,而不幸的是我们的系统需要跟别的老系统进行页面上的交互,所以系统的BasePage统一输出了一段脚本来设置document.domain,以让2个子域的系统进行交互:

    1try {
    2  document.domain = 'devfx.net';
    3}
     catch(e) {;}

     但是,AJAX异步通过iframe提交,输出的结果是不会有这段脚本的,这导致主页面的document.domain = 'devfx.net',而iframe却是真正域local.devfx.net,所以AjaxUploadHelper内的脚本获取不了iframe的内容,浏览器报Access Denied,AjaxUploadHelper的脚本把这个错误统一封装成500的错误了,可以看一下AjaxFileUploadHelper.js的代码:

            try
            
    {    
                
    var f = iframe.contentWindow.__f__;
                
    var responseData = f ? this._parseScriptText(f.toString()) : 
                    
    this._parsePreNode(iframe.contentWindow.document.body.firstChild);
                    
                
    if (responseData.indexOf("\r\n"< 0 && responseData.indexOf("\n"> 0)
                
    {
                    responseData 
    = responseData.replace(/\n/g, "\r\n");
                }

                    
                
    this._responseData = responseData;
                
    this._statusCode = 200;
                
    this._responseAvailable = true;
            }

            
    catch (e)
            
    {
                
    this._statusCode = 500;
                
    this._responseAvailable = false;
            }


    i,害人哪。。。。
    既然知道了是由于跨域产生的,解决起来就比较容易了。
    修改AjaxUploadHelper,增加属性ClientDocumentDomain,用以设置iframe的document.domain:
            private void RenderPageCallback(HtmlTextWriter writer, Control pageControl)
            
    {
                AjaxFileUploadUtility.WriteScriptBlock(
    this.Page.Response, true);

                StringBuilder sb 
    = new StringBuilder();
                HtmlTextWriter innerWriter 
    = new HtmlTextWriter(new StringWriter(sb));
                renderPageCallbackMethodInfo.Invoke(
    this.PageRequestManager, new object[] { innerWriter, pageControl });

                writer.Write(sb.Replace(
    "*/""*//*").ToString());

                AjaxFileUploadUtility.WriteScriptBlock(
    this.Page.Response, false);

                
    if(!string.IsNullOrEmpty(this.ClientDocumentDomain)) {
                    
    string domainScript = string.Format("<script type='text/javascript' language='javascript'>try {{ document.domain = '{0}'; }} catch(e) {{;}}</script>"this.ClientDocumentDomain);
                    writer.Write(domainScript);
                }

            }

    这下似乎一切正常了。

    上面的修改只是针对AjaxUploadHelper而改的。修改后的代码包:New AjaxFileUploadHelper

    到目前为止,老赵又发了更新:让UpdatePanel支持上传文件,这次使用了jquery以及插件jquery.form.js,把原来自己创建iframe的工作交由给jquery.form来处理,而且针对的framework是3.5的,(老赵发的代码包缺了好多脚本,害我好找!!);我以为新版本能把这个问题解决,可惜还是没有;我以为按修改AjaxUploadHelper方法就可以了,尝试了3天到目前为止还没有很完美的解决方案。主要的障碍在AJAX异步回调后,输出的是Content-Type是text/plain,如果这个时候输出脚本来设置domain,似乎任何脚本都不会被执行(好像浏览器把输出仅当成文本了),自然iframe的document.domain还是不对的,所以还是会报500的假错误(貌似AjaxUploadHelper控件却是可以的,不解了);如果完全改成AjaxUploadHelper的操作方式,不知道会不会解决;等有空的时候在深入研究研究。
  • 相关阅读:
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    72. Edit Distance
    583. Delete Operation for Two Strings
    582. Kill Process
    indexDB基本用法
    浏览器的渲染原理
    js实现txt/excel文件下载
    git 常用命令
    nginx进入 配置目录时
  • 原文地址:https://www.cnblogs.com/R2/p/1202047.html
Copyright © 2011-2022 走看看