【问题标题】:Can I use HttpHandler to fake the existence of aspx pages?我可以使用 HttpHandler 来伪造 aspx 页面的存在吗?
【发布时间】:2009-03-23 15:04:14
【问题描述】:

我正在使用 ASP.NET 3.5 构建一个网站,并且大多数网站结构都是静态的,足以创建文件夹结构和 aspx 页面。但是,站点管理员希望能够通过 Web 界面和使用 WYSIWYG 编辑器将新页面添加到站点的不同部分。我正在使用嵌套母版页为站点的不同部分提供自己的菜单。我想做的是在网站的每个部分下都有一个通用页面,该页面使用适当的母版页,并有一个可以从数据库加载的内容的占位符。我还希望这些“假”页面具有与任何其他 aspx 页面一样的 url,就好像它们在服务器上有相应的文件一样。所以不要让我的网址是:

http://mysite.com/subsection/gerenicconent.aspx?contentid=1234

应该是这样的:

http://mysite.com/subsection/somethingmeaningful.aspx

问题是somethingmeaningful.aspx 不存在,因为管理员是通过web UI 创建的,内容存储在数据库中。我在想的是,我将实现一个 HTTP 处理程序来处理对 aspx 文件的请求。在该处理程序中,我将检查所请求的 URL 是实际文件还是我的“假页面”之一。如果它是对虚假页面的请求,我会将请求重新路由到相应部分的通用内容页面,更改查询字符串以从数据库中请求适当的数据,并重写 URL 使其看起来用户就好像假页面真的存在一样。我现在遇到的问题是我无法弄清楚如何将请求路由到 aspx 页面的默认处理程序。我试图实例化一个 PageHandlerFactory,但构造函数是受内部保护的。有什么方法可以告诉我的 HttpHandler 调用通常用于处理请求的 HttpHandler 吗?我的处理程序代码目前如下所示:

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

namespace HandlerTest
{
    public class FakePageHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        public void ProcessRequest(HttpContext context)
        {
            if(RequestIsForFakedPage(context))
            {
                // reroute the request to the generic page and rewrite the URL
                PageHandlerFactory factory = new PageHandlerFactory(); // this won't compile because the constructor is protected internal
                factory.GetHandler(context, context.Request.RequestType, GetGenericContentPath(context), GetPhysicalApplicationPath(context)).ProcessRequest(context);
            }
            else
            {
                // route the request to the default handler for aspx pages
                PageHandlerFactory factory = new PageHandlerFactory();
                factory.GetHandler(context, context.Request.RequestType, context.Request.Path, context.Request.PhysicalPath).ProcessRequest(context);
            }
        }

        public string RequestForPageIsFaked(HttpContext context)
        {
            // TODO
        }

        public string GetGenericContentPath(HttpContext context)
        {
            // TODO
        }

        public string GetPhysicalApplicationPath(HttpContext context)
        {
            // TODO
        }
    }
}

我还有一些工作要做,以确定请求是否针对真实页面,并且我还没有重写任何 URL,但是这样的事情可能吗?除了调用其构造函数之外,还有其他方法可以创建 PageHandlerFactory 吗?有什么方法可以将请求路由到 aspx 页面的“正常”HttpHandler 吗?我基本上是在说“像往常一样处理这个 ASPX 请求。”

【问题讨论】:

    标签: asp.net


    【解决方案1】:

    如果您使用的是 3.5,请考虑使用 asp.net 路由。

    http://msdn.microsoft.com/en-us/library/cc668201.aspx

    【讨论】:

      【解决方案2】:

      您最好为此使用 http 模块,因为在这种情况下,您可以使用 RewritePath 方法来路由虚假页面的请求,而对实际页面不做任何事情,这将使它们能够正常处理。

      here 有一个很好的解释,如果您愿意,它还涵盖了使用 IIS 7.0 的好处。

      【讨论】:

        【解决方案3】:

        我刚刚从我们刚刚编写的类似系统中提取了这个。

        此方法处理物理页面和“假”页面。我敢肯定,您将能够确定这与您的虚假页面架构的匹配度。

        public class AspxHttpHandler : IHttpHandlerFactory
        {
                #region ~ from IHttpHandlerFactory ~
        
                public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
                {
                            string url=context.Request.Url.AbsolutePath;
                    string[] portions = url.Split(new char[] { '/', '\\' });
                            // gives you the path, i presume this will help you identify the section and page
                            string serverSidePage=Path.Combine(context.Server.MapPath("~"),url);
                            if (File.Exists(serverSidePage))
                            {
                                     // page is real
                                    string virtualPath = context.Request.Url.AbsolutePath;
                        string inputFile = context.Server.MapPath(virtualPath);
        
                        try
                        {
                                            // if it's real, send in the details to the ASPX compiler
                            return PageParser.GetCompiledPageInstance(virtualPath, inputFile, context);
                        }
                        catch (Exception ex)
                        {
                                throw new ApplicationException("Failed to render physical page", ex);
                        }
                              }
                              else
                              {
                                    // page is fake
                                    // need to identify a page that exists which you can use to compile against
                                    // here, it is CMSTaregtPage - it can use a Master
                                    string inputFile = context.Server.MapPath("~/CMSTargetPage.aspx");
                        string virtualPath = "~/CMSTargetPage.aspx";
                                    // you can also add things that the page can access vai the Context.Items collection
                                    context.Items.Add("DataItem","123");
                                    return PageParser.GetCompiledPageInstance(virtualPath, inputFile, context);
        }
        
        public void ReleaseHandler(IHttpHandler handler)
        {
        
        }
        

        【讨论】:

          最近更新 更多