Custom PageHandlerFactory for .aspx

后端 未结 2 717
执笔经年
执笔经年 2021-02-10 11:35

I am building a fairly simple CMS. I need to intercept requests for the majority of .aspx pages in my web application, in order to gain complete control over the output. In mo

2条回答
  •  野性不改
    2021-02-10 12:04

    When I wrote a simple CMS, I had a difficult time using the PageHandlerFactory to get it to do what I wanted. In the end I switched to a IHttpModule.

    My module would first check to see if there was an .aspx file in the requested path. I'd only do that if the page has user controls on it or didn't fit into the CMS for some reason. So if the file existed, it would return out of the module. After that it would look at the requested path and condense it into a "navigation tag." Thus ~/aboutus/default.aspx would become page.aspx?nt=aboutusdefault. page.aspx would load the proper content form the CMS. Of course, the redirect occurs server-side so the users/spiders never know anything different happened.

    using System;
    using System.Data;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Reflection;
    using System.Text.RegularExpressions;
    using System.Web;
    
    namespace MyCMS.Handlers {
        /// 
        /// Checks to see if we should display a virutal page to replace the current request.
        /// Code adapted from:
        /// Rewrite.NET -- A URL Rewriting Engine for .NET
        /// By Robert Chartier
        /// http://www.15seconds.com/issue/030522.htm
        /// 
        public class VirtualPageModule : IHttpModule {
            /// 
            /// Init is required from the IHttpModule interface
            /// 
            /// 
            public void Init(System.Web.HttpApplication Appl) {
                // make sure to wire up to BeginRequest
                Appl.BeginRequest += new System.EventHandler(Rewrite_BeginRequest);
            }
    
            /// 
            /// Dispose is required from the IHttpModule interface
            /// 
            public void Dispose() {
                // make sure you clean up after yourself
            }
    
            /// 
            /// To handle the starting of the incoming request
            /// 
            /// 
            /// 
            public void Rewrite_BeginRequest(object sender, System.EventArgs args) {
                // Cast the sender to an HttpApplication object
                HttpApplication httpApp = (HttpApplication)sender;
    
                // See if the requested file already exists
                if (System.IO.File.Exists(httpApp.Request.PhysicalPath)) {
                    // Do nothing, process the request as usual
                    return;
                }
    
                string requestPath = VirtualPathUtility.ToAppRelative(httpApp.Request.Path);
    
                // Organic navigation tag (~/aboutus/default.aspx = nt "aboutusdefault")
                Regex regex = new Regex("[~/\\!@#$%^&*()+=-]");
                requestPath = regex.Replace(requestPath, string.Empty).Replace(".aspx", string.Empty);
                string pageName = "~/page.aspx";
                string destinationUrl = VirtualPathUtility.ToAbsolute(pageName) + "?nt=" + requestPath;
                SendToNewUrl(destinationUrl, httpApp);
            }
    
            public void SendToNewUrl(string url, HttpApplication httpApp) {
                applyTrailingSlashHack(httpApp);
                httpApp.Context.RewritePath(
                    url,
                    false // RebaseClientPath must be false for ~/ to continue working in subdirectories.
                );
            }
    
            /// 
            /// Applies the trailing slash hack. To circumvent an ASP.NET bug related to dynamically
            /// generated virtual directories ending in a trailing slash (/).
            /// As described by BuddyDvd:
            /// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=105061
            /// 
            /// The HttpApplication.
            /// 
            /// Execute this function before calling RewritePath.
            /// 
            private void applyTrailingSlashHack(HttpApplication httpApp) {
                if (httpApp.Request.Url.AbsoluteUri.EndsWith("/") && !httpApp.Request.Url.AbsolutePath.Equals("/")) {
                    Type requestType = httpApp.Context.Request.GetType();
                    object clientFilePath = requestType.InvokeMember("ClientFilePath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty, null, httpApp.Context.Request, null);
                    string virtualPathString = (string)clientFilePath.GetType().InvokeMember("_virtualPath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, clientFilePath, null);
                    clientFilePath.GetType().InvokeMember("_virtualPath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, clientFilePath, new object[] { virtualPathString });
                    requestType.InvokeMember("_clientFilePath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, HttpContext.Current.Request, new object[] { clientFilePath });
                    object clientBaseDir = requestType.InvokeMember("ClientBaseDir", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty, null, httpApp.Context.Request, null);
                    clientBaseDir.GetType().InvokeMember("_virtualPath", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, clientBaseDir, new object[] { virtualPathString });
                    requestType.InvokeMember("_clientBaseDir", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField, null, HttpContext.Current.Request, new object[] { clientBaseDir });
                }
            }
        }
    }
    

提交回复
热议问题