Asp.Net Server.Execute、Server.Transfer报“执行子请求时出错”解决方案

我们一般会自定义自己的HttpHandler来处理一些特殊的业务,往往需要在方法ProcessRequest中调用其他的实现IHttpHandler的Page页或ashx一般处理文件或自定义的HttpHandler类,那么我们会用Server.Execute("path")或Server.Transfer()来实现,但有时运行时会报“为 ...执行子请求时出错。”,那么如何解决呢?


这里分几种情况来讨论。(这里测试环境为.net 4.0 IIS7 Win7)

一、自定义HttpHandler类中请求aspx、ashx、自定义HttpHandler类

首先Web.congfig中配置自定义处理程序

      
    
      
           
  

1、自定义HttpHandler类使用Server.Execute跳转到Page页

public class MyHttpHandler:IHttpHandler
    {
        public   void ProcessRequest(HttpContext context)
        {
            StringWriter sw = new StringWriter();
            context.Server.Execute("/SelfTextBoxControlTest.aspx",sw,false);
            string dealResult = sw.ToString();
            context.Response.Write(dealResult);
            context.Response.End();           
        }
    }

运行时报错:

Asp.Net Server.Execute、Server.Transfer报“执行子请求时出错”解决方案_第1张图片


尝试解决方案:

HttpHandler类继承Page类

代码:

 public class MyHttpHandler:Page
    {
        public override  void ProcessRequest(HttpContext context)
        {
            StringWriter sw = new StringWriter();
            context.Server.Execute("/SelfTextBoxControlTest.aspx",false);
            string dealResult = sw.ToString();
            context.Response.Write(dealResult);
            context.Response.End();           
        }
    }
运行时虽然不报“执行子请求出错”,但一直循环调用ProcessRequest方法,形成死循环

解决方案:

MyHttpHandler继承IHttpHandler(继承Page也可以),通过BuildManager.CreateInstanceFromVirtualPath方法获取页面的IHttpHandler实例,再将该实例传入Execute重载方法(public void Execute(IHttpHandler handler, TextWriter writer, bool preserveForm))中

代码:

public class MyHttpHandler:IHttpHandler
    {       
        public  void ProcessRequest(HttpContext context)
        {
            StringWriter sw = new StringWriter();
            var handler = BuildManager.CreateInstanceFromVirtualPath("/SelfTextBoxControlTest.aspx", typeof(IHttpHandler)) as IHttpHandler;
            context.Server.Execute(handler,sw,false);
            string dealResult = sw.ToString();
            context.Response.Write(dealResult);
            context.Response.End();           
        }
    }

运行通过,返回请求页面响应结果,输出到当前页面


2、自定义HttpHandler类使用Server.Execute跳转到ashx一般处理程序中


代码:

 public class MyHttpHandler:IHttpHandler
    {
        public  void ProcessRequest(HttpContext context)
        {
            StringWriter sw = new StringWriter();
            context.Server.Execute("/CommonHandler2.ashx", sw, false);
            string dealResult = sw.ToString();
            context.Response.Write(dealResult);
            context.Response.End();           
        }
    }

运行时报和aspx页面相同的错


那是不是和请求page页面一样,用BuildManager.CreateInstanceFromVirtualPath()就能解决呢?我们来试一下

代码:

public class MyHttpHandler:IHttpHandler
    {
        public  void ProcessRequest(HttpContext context)
        {
            StringWriter sw = new StringWriter();
            var handler = BuildManager.CreateInstanceFromVirtualPath("/CommonHandler2.ashx", typeof(IHttpHandler)) as IHttpHandler;
            context.Server.Execute(handler, sw, false);
            string dealResult = sw.ToString();
            context.Response.Write(dealResult);
            context.Response.End();           
        }
    }

运行后仍然报错

Asp.Net Server.Execute、Server.Transfer报“执行子请求时出错”解决方案_第2张图片

说明请求ashx和aspx页面不同,我们来试试将ashx文件类继承Page

代码:

<%@ WebHandler Language="C#" Class="CommonHandler2" %>

using System;
using System.Web;
using System.Web.UI;

public class CommonHandler2 :Page{
    
    public override void ProcessRequest (HttpContext context) 
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World");
    }
}

运行代码,正常执行!

在将ashx文件类继承Page类后,其实用

context.Server.Execute("/CommonHandler2.ashx", sw, false);
同样不会报错,正常执行

3、自定义HttpHandler类使用Server.Execute跳转到其他自定义的HttpHandler类

代码:

MyHttpHandler

public class MyHttpHandler:IHttpHandler
    {
        public  void ProcessRequest(HttpContext context)
        {
            StringWriter sw = new StringWriter();
            TestHandler handler = new TestHandler();
            context.Server.Execute(handler, sw, false);
            string dealResult = sw.ToString();
            context.Response.Write(dealResult);
            context.Response.End();           
        }
    }

TestHandler

public class TestHandler:IHttpHandler
    {

        public  void ProcessRequest(HttpContext context)
        {
            context.Response.Write("TestHandler");
        }
    }

运行代码,报“执行子请求错误”。


解决方案:

在目标请求类TestHandler继承改为Page类,即:

TestHandler

public class TestHandler:Page
    {
        public override  void ProcessRequest(HttpContext context)
        {
            context.Response.Write("TestHandler");
        }
    }
运行代码,正常执行!


二、Asp.Net Page页中请求其他Page页、ashx文件、自定HttpHandler类

1、Asp.Net Page页中请求其他Page页

代码:

public partial class _Default : Page
    {
      
        protected void btnTestHandler_Click(object sender, EventArgs e)
        {
            StringWriter sw = new StringWriter();
            Context.Server.Execute("/SelfTextBoxControlTest.aspx", sw, false);
        }

        protected void Page_Load(object sender, EventArgs e)
        {

        }
        
    }
运行代码,一切正常!说明Page页调用其他Page页,只需将目标文件路径传入Server.Execute中即可,当然,通过CreateInstanceFromVirtualPath获取文件实例再传入也行。

2、Asp.Net Page页中请求ashx文件

这种情况和上面自定义HttpHandler类请求ashx文件一样,ashx文件类也必须继承Page类才能正常被请求,否则报“执行子请求出错”


3、Asp.Net Page页中请求自定义HttpHandler类

这种情况和上面自定义HttpHandler类请求其他自定义HttpHandler类一样,被请求的自定义HttpHandler类也必须继承Page类才能正常被请求,否则报“执行子请求出错”


总结:

通常当Asp.Net运行Server.Transfer或Server.Execute程序出现“执行子请求出错”时,排除目标对象代码异常外,可得出以下结论

1、当目标对象为Page页时,用BuildManager.CreateInstanceFromVirtualPath方法获取page页的实例,再传入Server.Transfer或Server.Execute中

2、当目标对象为ashx文件或自定义HttpHandler类时,将目标对象继承的父类改为Page类


至于内部原理,暂时还没搞清楚,等以后弄明白后后续再更新博文。有知道的朋友可以给我留言,万分感谢!


你可能感兴趣的:(Asp.Net,C#)