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

29 篇文章 0 订阅

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


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

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

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

<system.webServer>      
    <handlers>
      <add name="MyHttpHandler" path="*.aspx" verb="*" type="DiyControlWeb.MyHttpHandler"/>
    </handlers>       
  </system.webServer>

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();           
        }
    }

运行时报错:


尝试解决方案:

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();
            <strong><span style="color:#FF6666;">var handler = BuildManager.CreateInstanceFromVirtualPath("/SelfTextBoxControlTest.aspx", typeof(IHttpHandler)) as IHttpHandler;</span></strong>
            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();           
        }
    }

运行后仍然报错


说明请求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类后,其实用

<span style="color:#33CC00;">context.Server.Execute("/CommonHandler2.ashx", sw, false);</span>
同样不会报错,正常执行

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();
            <span style="color:#FF0000;">Context.Server.Execute("/SelfTextBoxControlTest.aspx", sw, false);</span>
        }

        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类


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


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值