• 让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的操作方式,不知道会不会解决;等有空的时候在深入研究研究。
  • 相关阅读:
    (OK) Android graphic (12)—display上层相关概念、关系
    (OK) Android系统启动-SystemServer下篇
    (OK) Android系统启动-SystemServer上篇
    (OK) Android 5 SystemServer 各个系统Manager-startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY)
    Android 6.0 源码分析
    (OK) android6.0源码分析之Runtime的初始化
    (OK) Android的JNI_OnLoad简介与应用
    (OK) Android架构实例分析之注册hello HAL的JNI方法表
    (OK) Android的NDK开发(1)————Android JNI简介与调用流程
    (OK) android-5.0 sensor工作原理—sensorservice的启动(二)
  • 原文地址:https://www.cnblogs.com/R2/p/1202047.html
Copyright © 2020-2023  润新知