Вопрос

Я строю довольно простую CMS. Мне нужно перехватывать запросы для большинства страниц .aspx в моем веб-приложении, чтобы получить полный контроль над выводом. В большинстве случаев выходные данные будут извлечены из кэша и будут просто в формате HTML.

Однако есть еще пара страниц, на которых мне нужно будет использовать элементы управления asp :. Я предполагаю, что лучший способ обойти несколько конкретных запросов - это унаследовать System.Web.UI.PageHandlerFactory и просто вызывать реализацию MyBase, когда мне нужно (пожалуйста, исправьте меня, если я здесь не прав). Но как мне перенести все другие запросы в мой пользовательский обработчик?

Это было полезно?

Решение

Когда я писал простую CMS, мне было трудно использовать PageHandlerFactory, чтобы заставить ее делать то, что я хотел. В конце концов я переключился на IHttpModule.

Мой модуль сначала проверит, есть ли файл .aspx в запрошенном пути. Я сделал бы это только в том случае, если на странице есть пользовательские элементы управления или она по какой-то причине не вписывается в CMS. Таким образом, если файл существует, он вернется из модуля. После этого он будет смотреть на запрошенный путь и сгущать его в «навигационный тег». Таким образом, ~ / aboutus / default.aspx станет page.aspx? Nt = aboutusdefault. page.aspx загрузит соответствующий контент из CMS. Конечно, перенаправление происходит на стороне сервера, поэтому пользователи / пауки никогда не узнают, что произошло что-то другое.

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 {
    /// <summary>
    /// 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
    /// </summary>
    public class VirtualPageModule : IHttpModule {
        /// <summary>
        /// Init is required from the IHttpModule interface
        /// </summary>
        /// <param name="Appl"></param>
        public void Init(System.Web.HttpApplication Appl) {
            // make sure to wire up to BeginRequest
            Appl.BeginRequest += new System.EventHandler(Rewrite_BeginRequest);
        }

        /// <summary>
        /// Dispose is required from the IHttpModule interface
        /// </summary>
        public void Dispose() {
            // make sure you clean up after yourself
        }

        /// <summary>
        /// To handle the starting of the incoming request
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        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.
            );
        }

        /// <summary>
        /// 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
        /// </summary>
        /// <param name="httpApp">The HttpApplication.</param>
        /// <remarks>
        /// Execute this function before calling RewritePath.
        /// </remarks>
        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 });
            }
        }
    }
}

Другие советы

Вы имеете в виду, что собираетесь ввести контроль? Если это так, вы можете рассмотреть обязательный базовый класс вместо класса Page. Страница реализует IHttpHandler, поэтому вы можете создать производный класс, а затем изменить свои страницы, чтобы они были производными от вашего производного класса. Вы будете иметь намного больший контроль над своей страницей и сможете подключиться к ней и к ее отображению.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top