zoukankan      html  css  js  c++  java
  • RouteDebugger分析

    RouteDebugger的介绍  http://www.cnblogs.com/suizhikuo/archive/2012/07/25/2608889.html

    2.RouteDebugger结构,一共有5个文件,将逐一解释每个文件的作用

    RouteDebug.cs

    using System.Web.Routing;
    
    namespace RouteDebug
    {
        public class DebugRoute : Route
        {
            static readonly DebugRoute singleton = new DebugRoute();
    
            public static DebugRoute Singleton
            {
                get { return singleton; }
            }
    
            private DebugRoute()
                : base("{*catchall}", new DebugRouteHandler()) { }
        }
    }

    全局单例的DebugRoute,构造函数传入了DebugRouteHandler。

    DebugRouteHandler.cs

    using System.Web;
    using System.Web.Routing;
    
    namespace RouteDebug
    {
        public class DebugRouteHandler : IRouteHandler
        {
            public IHttpHandler GetHttpHandler(RequestContext requestContext)
            {
                return new DebugHttpHandler();
            }
        }
    }

    核心都在DebugHttpHandler最后再解释。

    PreApplicationStart.cs

    using System;
    using System.Configuration;
    using System.Web;
    using RouteDebug;
    
    [assembly: PreApplicationStartMethod(typeof(PreApplicationStart), "Start")]
    
    namespace RouteDebug
    {
        public class PreApplicationStart
        {
            public static void Start()
            {
                bool enabled = Convert.ToBoolean(ConfigurationManager.AppSettings["RouteDebugger:Enabled"]);
                if (enabled)
                {
                    Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(RouteDebuggerHttpModule));
                }
            }
        }
    }

    项目启动时利用DynamicModuleUtility根据Webconfig配置动态的注册RouteDebuggerHttpModule.

    RouteDebuggerHttpModule.cs

    namespace RouteDebug
    {
        public class RouteDebuggerHttpModule : IHttpModule
        {
            public void Init(HttpApplication context)
            {
                context.EndRequest += OnEndRequest;
                context.BeginRequest += OnBeginRequest;
            }
    
            static void OnBeginRequest(object sender, System.EventArgs e)
            {
                if (RouteTable.Routes.Last() != DebugRoute.Singleton)
                {
                    RouteTable.Routes.Add(DebugRoute.Singleton);
                }
            }
    
            static void OnEndRequest(object sender, System.EventArgs e)
            {
                var handler = new DebugHttpHandler();
    
                handler.ProcessRequest(HttpContext.Current);
            }
    
            public void Dispose()
            {
            }
        }
    }

    OnBeginRequest向路由表添加DebugRoute.

    OnEndRequest输出RouteDebugger信息.

    DebugHttpHandler.cs

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Web;
    using System.Web.Hosting;
    using System.Web.Routing;
    
    namespace RouteDebug
    {
        public class DebugHttpHandler : IHttpHandler
        {
            readonly VirtualPathProvider _virtualPathProvider;
    
            public DebugHttpHandler() : this(null) { }
    
            public DebugHttpHandler(VirtualPathProvider virtualPathProvider)
            {
                _virtualPathProvider = virtualPathProvider ?? HostingEnvironment.VirtualPathProvider;
            }
    
            public void ProcessRequest(HttpContext context)
            {
                var request = context.Request;
    
                if (!IsRoutedRequest(request) || context.Response.ContentType == null || !context.Response.ContentType.Equals("text/html", StringComparison.OrdinalIgnoreCase))
                {
                    return;
                }
    
                string generatedUrlInfo = string.Empty;
                var requestContext = request.RequestContext;
    
                if (request.QueryString.Count > 0)
                {
                    var rvalues = new RouteValueDictionary();
                    foreach (string key in request.QueryString.Keys)
                    {
                        if (key != null)
                        {
                            rvalues.Add(key, request.QueryString[key]);
                        }
                    }
    
                    var vpd = RouteTable.Routes.GetVirtualPath(requestContext, rvalues);
                    if (vpd != null)
                    {
                        generatedUrlInfo = "<p><label style=\"font-weight: bold; font-size: 1.1em;\">Generated URL</label>: ";
                        generatedUrlInfo += "<strong style=\"color: #00a;\">" + vpd.VirtualPath + "</strong>";
                        var vpdRoute = vpd.Route as Route;
                        if (vpdRoute != null)
                        {
                            generatedUrlInfo += " using the route \"" + vpdRoute.Url + "\"</p>";
                        }
                    }
                }
    
                const string htmlFormat = @"<html>
    <div id=""haackroutedebugger"" style=""background-color: #fff; padding-bottom: 10px;"">
        <style>
            #haackroutedebugger, #haackroutedebugger td, #haackroutedebugger th {{background-color: #fff; font-family: verdana, helvetica, san-serif; font-size: small;}}
            #haackroutedebugger tr.header td, #haackroutedebugger tr.header th {{background-color: #ffc;}}
        </style>
        <hr style="" 100%; border: solid 1px #000; margin:0; padding:0;"" />
        <h1 style=""margin: 0; padding: 4px; border-bottom: solid 1px #bbb; padding-left: 10px; font-size: 1.2em; background-color: #ffc;"">Route Debugger</h1>
        <div id=""main"" style=""margin-top:0; padding: 0 10px;"">
            <p style=""font-size: .9em; padding-top:0"">
                Type in a url in the address bar to see which defined routes match it. 
                A {{*catchall}} route is added to the list of routes automatically in 
                case none of your routes match.
            </p>
            <p style=""font-size: .9em;"">
                To generate URLs using routing, supply route values via the query string. example: <code>http://localhost:14230/?id=123</code>
            </p>
            <p><label style=""font-weight: bold; font-size: 1.1em;"">Matched Route</label>: {1}</p>
            {5}
            <div style=""float: left;"">
                <table border=""1"" cellpadding=""3"" cellspacing=""0"" width=""300"">
                    <caption style=""font-weight: bold;"">Route Data</caption>
                    <tr class=""header""><th>Key</th><th>Value</th></tr>
                    {0}
                </table>
            </div>
            <div style=""float: left; margin-left: 10px;"">
                <table border=""1"" cellpadding=""3"" cellspacing=""0"" width=""300"">
                    <caption style=""font-weight: bold;"">Data Tokens</caption>
                    <tr class=""header""><th>Key</th><th>Value</th></tr>
                    {4}
                </table>
            </div>
            <hr style=""clear: both;"" />
            <table border=""1"" cellpadding=""3"" cellspacing=""0"">
                <caption style=""font-weight: bold;"">All Routes</caption>
                <tr class=""header"">
                    <th>Matches Current Request</th>
                    <th>Url</th>
                    <th>Defaults</th>
                    <th>Constraints</th>
                    <th>DataTokens</th>
                </tr>
                {2}
            </table>
            <hr />
            <h3>Current Request Info</h3>
            <p>
                AppRelativeCurrentExecutionFilePath is the portion of the request that Routing acts on.
            </p>
            <p><strong>AppRelativeCurrentExecutionFilePath</strong>: {3}</p>
        </div>
    </div>";
                string routeDataRows = string.Empty;
    
                var routeData = requestContext.RouteData;
                var routeValues = routeData.Values;
                var matchedRouteBase = routeData.Route;
    
                string routes = string.Empty;
                using (RouteTable.Routes.GetReadLock())
                {
                    foreach (var routeBase in RouteTable.Routes)
                    {
                        bool matchesCurrentRequest = (routeBase.GetRouteData(requestContext.HttpContext) != null);
                        string matchText = string.Format(@"<span{0}>{1}</span>", BoolStyle(matchesCurrentRequest), matchesCurrentRequest);
                        string url = "n/a";
                        string defaults = "n/a";
                        string constraints = "n/a";
                        string dataTokens = "n/a";
    
                        Route route = CastRoute(routeBase);
    
                        if (route != null)
                        {
                            url = route.Url;
                            defaults = FormatDictionary(route.Defaults);
                            constraints = FormatDictionary(route.Constraints);
                            dataTokens = FormatDictionary(route.DataTokens);
                        }
    
                        routes += string.Format(@"<tr><td>{0}</td><td>{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>"
                                , matchText
                                , url
                                , defaults
                                , constraints
                                , dataTokens);
                    }
                }
    
                string matchedRouteUrl = "n/a";
    
                string dataTokensRows = "";
    
                if (!(matchedRouteBase is DebugRoute))
                {
                    foreach (string key in routeValues.Keys)
                    {
                        routeDataRows += string.Format("\t<tr><td>{0}</td><td>{1}&nbsp;</td></tr>", key, routeValues[key]);
                    }
    
                    foreach (string key in routeData.DataTokens.Keys)
                    {
                        dataTokensRows += string.Format("\t<tr><td>{0}</td><td>{1}&nbsp;</td></tr>", key, routeData.DataTokens[key]);
                    }
    
                    var matchedRoute = matchedRouteBase as Route;
    
                    if (matchedRoute != null)
                        matchedRouteUrl = matchedRoute.Url;
                }
                else
                {
                    matchedRouteUrl = string.Format("<strong{0}>NO MATCH!</strong>", BoolStyle(false));
                }
    
                context.Response.Write(string.Format(htmlFormat
                    , routeDataRows
                    , matchedRouteUrl
                    , routes
                    , request.AppRelativeCurrentExecutionFilePath
                    , dataTokensRows
                    , generatedUrlInfo));
            }
    
            private Route CastRoute(RouteBase routeBase)
            {
                var route = routeBase as Route;
                if (route == null)
                {
                    // cheat!
                    // TODO: Create an interface for self reporting routes.
                    var type = routeBase.GetType();
                    var property = type.GetProperty("__DebugRoute", BindingFlags.NonPublic | BindingFlags.Instance);
                    if (property != null)
                    {
                        route = property.GetValue(routeBase, null) as Route;
                    }
                }
                return route;
            }
    
            private static string FormatDictionary(IDictionary<string, object> values)
            {
                if (values == null)
                    return "(null)";
    
                if (values.Count == 0)
                {
                    return "(empty)";
                }
    
                string display = string.Empty;
                foreach (string key in values.Keys)
                {
                    display += string.Format("{0} = {1}, ", key, FormatObject(values[key]));
                }
                if (display.EndsWith(", "))
                    display = display.Substring(0, display.Length - 2);
                return display;
            }
    
            private static string FormatObject(object value)
            {
                if (value == null)
                {
                    return "(null)";
                }
    
                var values = value as object[];
                if (values != null)
                {
                    return string.Join(", ", values);
                }
    
                var dictionaryValues = value as IDictionary<string, object>;
                if (dictionaryValues != null)
                {
                    return FormatDictionary(dictionaryValues);
                }
    
                if (value.GetType().Name == "UrlParameter")
                {
                    return "UrlParameter.Optional";
                }
    
                return value.ToString();
            }
    
            private static string BoolStyle(bool boolean)
            {
                if (boolean) return " style=\"color: #0c0\"";
                return " style=\"color: #c00\"";
            }
    
            private bool IsRoutedRequest(HttpRequest request)
            {
                string path = request.AppRelativeCurrentExecutionFilePath;
                if (path != "~/" && (_virtualPathProvider.FileExists(path) || _virtualPathProvider.DirectoryExists(path)))
                {
                    return false;
                }
                return true;
            }
    
            public bool IsReusable
            {
                get { return true; }
            }
        }
    }

    IHttpHandler接口肯定都不陌生,有两个地方会调用到ProcessRequest方法。一是RouteDebuggerHttpModule的EndRequest方法。二是匹配到DebugRoute,DebugRoute加在了路由表的最后,没有匹配到任何的Route的时候就会返回DebugRoute。 所以这个时候就会输出两次ProcessRequest. 这是RouteDebugger的核心,循环RouteTable.Routes判断是否匹并且输出。

  • 相关阅读:
    [C#] 逆袭——自制日刷千题的AC自动机攻克HDU OJ
    [安卓] 13、安卓蓝牙定位(一)——如何周期性获得蓝牙节点信号强度?
    [stm32] NRF24L01+USART搞定有线和无线通信
    [安卓] 12、开源一个基于SurfaceView的飞行射击类小游戏
    [安卓] 11、串口蓝牙·将软硬结合进行到底
    [安卓] 10、悬浮窗与获取其他任务信息
    [安卓] 9、线程、VIEW、消息实现从TCP服务器获取数据动态加载显示
    [安卓] 8、VIEW和SURFACEVIEW游戏框架
    [安卓] 7、页面跳转和Intent简单用法
    Git常用命令记录
  • 原文地址:https://www.cnblogs.com/miku/p/2875264.html
Copyright © 2011-2022 走看看