Permalink
Browse files

Adding RouteDebugger to this solution.

  • Loading branch information...
1 parent c7a8a72 commit 8819e497eae48f34d97892cbb0e3d034276d5e2d haacked committed Mar 29, 2011
View
180 src/RouteDebug/DebugHttpHandler.cs
@@ -0,0 +1,180 @@
+using System.Web;
+using System.Web.Routing;
+
+namespace RouteDebug
+{
+ public class DebugHttpHandler : IHttpHandler
+ {
+ public RequestContext RequestContext { get; set; }
+
+ public bool IsReusable
+ {
+ get { return true; }
+ }
+
+ public void ProcessRequest(HttpContext context)
+ {
+ string generatedUrlInfo = string.Empty;
+ if (context.Request.QueryString.Count > 0) {
+ var rvalues = new RouteValueDictionary();
+ foreach(string key in context.Request.QueryString.Keys) {
+ rvalues.Add(key, context.Request.QueryString[key]);
+ }
+
+ var vpd = RouteTable.Routes.GetVirtualPath(RequestContext, rvalues);
+ if (vpd != null) {
+ generatedUrlInfo = "<p><label>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>";
+ }
+ }
+ }
+
+ string htmlFormat = @"<html>
+<head>
+ <title>Route Tester</title>
+ <style>
+ body, td, th {{font-family: verdana; font-size: small;}}
+ .message {{font-size: .9em;}}
+ caption {{font-weight: bold;}}
+ tr.header {{background-color: #ffc;}}
+ label {{font-weight: bold; font-size: 1.1em;}}
+ .false {{color: #c00;}}
+ .true {{color: #0c0;}}
+ </style>
+</head>
+<body>
+<h1>Route Tester</h1>
+<div id=""main"">
+ <p class=""message"">
+ 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 class=""message"">
+ To generate URLs using routing, supply route values via the query string. example: <code>http://localhost:14230/?id=123</code>
+ </p>
+ <p><label>Matched Route</label>: {1}</p>
+ {5}
+ <div style=""float: left;"">
+ <table border=""1"" cellpadding=""3"" cellspacing=""0"" width=""300"">
+ <caption>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>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>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>
+</body>
+</html>";
+ string routeDataRows = string.Empty;
+
+ RouteData routeData = this.RequestContext.RouteData;
+ RouteValueDictionary routeValues = routeData.Values;
+ RouteBase matchedRouteBase = routeData.Route;
+
+ string routes = string.Empty;
+ using (RouteTable.Routes.GetReadLock())
+ {
+ foreach (RouteBase routeBase in RouteTable.Routes)
+ {
+ bool matchesCurrentRequest = (routeBase.GetRouteData(RequestContext.HttpContext) != null);
+ string matchText = string.Format(@"<span class=""{0}"">{0}</span>", matchesCurrentRequest);
+ string url = "n/a";
+ string defaults = "n/a";
+ string constraints = "n/a";
+ string dataTokens = "n/a";
+
+ Route route = routeBase as Route;
+ if (route != null)
+ {
+ url = route.Url;
+ defaults = FormatRouteValueDictionary(route.Defaults);
+ constraints = FormatRouteValueDictionary(route.Constraints);
+ dataTokens = FormatRouteValueDictionary(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]);
+ }
+
+ Route matchedRoute = matchedRouteBase as Route;
+
+ if (matchedRoute != null)
+ matchedRouteUrl = matchedRoute.Url;
+ }
+ else
+ {
+ matchedRouteUrl = "<strong class=\"false\">NO MATCH!</strong>";
+ }
+
+ context.Response.Write(string.Format(htmlFormat
+ , routeDataRows
+ , matchedRouteUrl
+ , routes
+ , context.Request.AppRelativeCurrentExecutionFilePath
+ , dataTokensRows
+ , generatedUrlInfo));
+ }
+
+ private static string FormatRouteValueDictionary(RouteValueDictionary values)
+ {
+ if (values == null || values.Count == 0)
+ return "(null)";
+
+ string display = string.Empty;
+ foreach (string key in values.Keys)
+ display += string.Format("{0} = {1}, ", key, values[key]);
+ if (display.EndsWith(", "))
+ display = display.Substring(0, display.Length - 2);
+ return display;
+ }
+ }
+}
View
18 src/RouteDebug/DebugRoute.cs
@@ -0,0 +1,18 @@
+using System.Web.Routing;
+
+namespace RouteDebug
+{
+ public class DebugRoute : Route
+ {
+ private static DebugRoute singleton = new DebugRoute();
+
+ public static DebugRoute Singleton
+ {
+ get { return singleton; }
+ }
+
+ private DebugRoute()
+ : base("{*catchall}", new DebugRouteHandler())
+ { }
+ }
+}
View
13 src/RouteDebug/DebugRouteHandler.cs
@@ -0,0 +1,13 @@
+using System.Web;
+using System.Web.Routing;
+
+namespace RouteDebug
+{
+ public class DebugRouteHandler : IRouteHandler
+ {
+ public IHttpHandler GetHttpHandler(RequestContext requestContext)
+ {
+ return new DebugHttpHandler { RequestContext = requestContext };
+ }
+ }
+}
View
36 src/RouteDebug/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RouteDebugger")]
+[assembly: AssemblyDescription("Route Debugger is a little utility I wrote to help debug issues with route configurations. See http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RouteDebugger")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("88784f4d-3799-4a7a-8e1d-16bbfbd77416")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
View
112 src/RouteDebug/RouteDebug.csproj
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>RouteDebug</RootNamespace>
+ <AssemblyName>RouteDebug</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <TargetFrameworkProfile />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web" />
+ <Reference Include="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Dependencies\System.Web.Abstractions.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Dependencies\System.Web.Routing.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="DebugHttpHandler.cs" />
+ <Compile Include="DebugRoute.cs" />
+ <Compile Include="DebugRouteHandler.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="RouteDebugger.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
34 src/RouteDebug/RouteDebugger.cs
@@ -0,0 +1,34 @@
+using System.Web.Routing;
+
+namespace RouteDebug
+{
+ public static class RouteDebugger
+ {
+ public static void RewriteRoutesForTesting(RouteCollection routes)
+ {
+ using (routes.GetReadLock())
+ {
+ bool foundDebugRoute = false;
+ foreach (RouteBase routeBase in routes)
+ {
+ Route route = routeBase as Route;
+ if (route != null)
+ {
+ route.RouteHandler = new DebugRouteHandler();
+ }
+
+ if (route == DebugRoute.Singleton)
+ foundDebugRoute = true;
+
+ }
+ if (!foundDebugRoute)
+ {
+ routes.Add(DebugRoute.Singleton);
+ }
+ }
+
+
+ }
+
+ }
+}
View
1 src/RouteDebuggerDemoWeb/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="RouteTesterDemoWeb.GlobalApplication" Language="C#" %>
View
27 src/RouteDebuggerDemoWeb/Global.asax.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Web.Routing;
+using System.Web.Mvc;
+using System.Reflection;
+
+namespace RouteTesterDemoWeb
+{
+ public class GlobalApplication : System.Web.HttpApplication
+ {
+ public static void RegisterRoutes(RouteCollection routes)
+ {
+ routes.MapRoute("foo-route", "foo/{id}", new { controller="Away", action = "Blah", id = (string)null });
+ routes.MapRoute("bar-route", "bar/{id}", new { controller = "Home", action = "Index", id = (string)null });
+ routes.MapRoute("token-route", "tokens/{id}", new {dataToken="BlahBlahBlah"});
+ routes.MapRoute("extension", "ext/{id}.mvc", new { controller = "Home", action = "Index", id = (string)null });
+ routes.MapRoute("mvc-default", "{controller}/{action}/{id}"
+ , new { controller = "Home", action = "Index", id = (string)null });
+ }
+
+ protected void Application_Start(object sender, EventArgs e)
+ {
+ RouteTable.Routes.RouteExistingFiles = true;
+ RegisterRoutes(RouteTable.Routes);
+ RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
+ }
+ }
+}
View
35 src/RouteDebuggerDemoWeb/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RouteTester")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("RouteTester")]
+[assembly: AssemblyCopyright("Copyright © 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("65160db0-ab4a-4fd7-b39b-98d5dbd258dd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
View
114 src/RouteDebuggerDemoWeb/RouteDebuggerDemoWeb.csproj
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{40F914CD-F707-4A4D-AF7B-75E8928055BB}</ProjectGuid>
+ <ProjectTypeGuids>{F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>RouteDebug</RootNamespace>
+ <AssemblyName>RouteDebuggerDemoWeb</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UseIISExpress>false</UseIISExpress>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Dependencies\System.Web.Abstractions.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Web.ApplicationServices" />
+ <Reference Include="System.Web.DynamicData" />
+ <Reference Include="System.Web.Entity" />
+ <Reference Include="System.Web.Extensions" />
+ <Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
+ <Reference Include="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Dependencies\System.Web.Routing.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Configuration" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.EnterpriseServices" />
+ <Reference Include="System.Web.Mobile" />
+ <Reference Include="System.Xml.Linq" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Global.asax.cs">
+ <DependentUpon>Global.asax</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Global.asax" />
+ <Content Include="Web.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\RouteDebug\RouteDebug.csproj">
+ <Project>{09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}</Project>
+ <Name>RouteDebug</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ProjectExtensions>
+ <VisualStudio>
+ <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
+ <WebProjectProperties>
+ <UseIIS>False</UseIIS>
+ <AutoAssignPort>True</AutoAssignPort>
+ <DevelopmentServerPort>14230</DevelopmentServerPort>
+ <DevelopmentServerVPath>/</DevelopmentServerVPath>
+ <IISUrl>
+ </IISUrl>
+ <NTLMAuthentication>False</NTLMAuthentication>
+ <UseCustomServer>False</UseCustomServer>
+ <CustomServerUrl>
+ </CustomServerUrl>
+ <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
+ </WebProjectProperties>
+ </FlavorProperties>
+ </VisualStudio>
+ </ProjectExtensions>
+</Project>
View
53 src/RouteDebuggerDemoWeb/Web.config
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<!--
+ For more information on how to configure your ASP.NET application, please visit
+ http://go.microsoft.com/fwlink/?LinkId=152368
+ -->
+
+<configuration>
+ <appSettings>
+ <add key="ClientValidationEnabled" value="true"/>
+ <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
+ </appSettings>
+
+ <system.web>
+ <compilation debug="true" targetFramework="4.0">
+ <assemblies>
+ <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+ <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+ <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+ <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+ <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
+ </assemblies>
+ </compilation>
+
+ <authentication mode="Forms">
+ <forms loginUrl="~/Account/LogOn" timeout="2880" />
+ </authentication>
+
+ <pages>
+ <namespaces>
+ <add namespace="System.Web.Helpers" />
+ <add namespace="System.Web.Mvc" />
+ <add namespace="System.Web.Mvc.Ajax" />
+ <add namespace="System.Web.Mvc.Html" />
+ <add namespace="System.Web.Routing" />
+ <add namespace="System.Web.WebPages"/>
+ </namespaces>
+ </pages>
+ </system.web>
+
+ <system.webServer>
+ <validation validateIntegratedModeConfiguration="false"/>
+ <modules runAllManagedModulesForAllRequests="true"/>
+ </system.webServer>
+
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
+ <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration>
View
11 src/RouteMagic.Mvc/RouteMagic.Mvc.csproj
@@ -30,10 +30,18 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>RouteMagickKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Web" />
+ <Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -55,6 +63,9 @@
<Name>RouteMagic</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <None Include="RouteMagickKey.snk" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
View
BIN src/RouteMagic.Mvc/RouteMagickKey.snk
Binary file not shown.
View
12 src/RouteMagic.sln
@@ -14,6 +14,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Metadata", "Metadata", "{88
SolutionInfo.cs = SolutionInfo.cs
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteDebug", "RouteDebug\RouteDebug.csproj", "{09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteDebuggerDemoWeb", "RouteDebuggerDemoWeb\RouteDebuggerDemoWeb.csproj", "{40F914CD-F707-4A4D-AF7B-75E8928055BB}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -36,6 +40,14 @@ Global
{D9321DA3-F3AC-4567-8452-B1B5D5633045}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9321DA3-F3AC-4567-8452-B1B5D5633045}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9321DA3-F3AC-4567-8452-B1B5D5633045}.Release|Any CPU.Build.0 = Release|Any CPU
+ {09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {09548C4E-F0C1-428A-BC3A-BFBB9328D7C7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {40F914CD-F707-4A4D-AF7B-75E8928055BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {40F914CD-F707-4A4D-AF7B-75E8928055BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {40F914CD-F707-4A4D-AF7B-75E8928055BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {40F914CD-F707-4A4D-AF7B-75E8928055BB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
View
9 src/RouteMagic/RouteMagic.csproj
@@ -30,6 +30,12 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
+ <PropertyGroup>
+ <SignAssembly>true</SignAssembly>
+ </PropertyGroup>
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>RouteMagickKey.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -64,6 +70,9 @@
<Compile Include="RouteRegistrationExtensions.cs" />
<Compile Include="RouteValueDictionaryExtensions.cs" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="RouteMagickKey.snk" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
View
BIN src/RouteMagic/RouteMagickKey.snk
Binary file not shown.
View
3 src/RouteMagicDemo.Web/RouteMagicDemo.Web.csproj
@@ -14,6 +14,7 @@
<AssemblyName>RouteMagicDemo.Web</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
+ <UseIISExpress>false</UseIISExpress>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -33,6 +34,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Web.WebPages" />
<Reference Include="System.Web.Helpers" />
@@ -48,7 +50,6 @@
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Web" />
- <Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
<Reference Include="System.Xml" />
View
BIN src/RouteMagickKey.snk
Binary file not shown.
View
47 src/UnitTests/RouteEvaluator.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.Web;
+using System.Web.Routing;
+using Moq;
+
+namespace UnitTests
+{
+ public class RouteEvaluator
+ {
+ RouteCollection routes;
+
+ public RouteEvaluator(RouteCollection routes)
+ {
+ this.routes = routes;
+ }
+
+ public IList<RouteData> GetMatches(string virtualPath)
+ {
+ return GetMatches(virtualPath, "GET");
+ }
+
+ public IList<RouteData> GetMatches(string virtualPath, string httpMethod)
+ {
+ List<RouteData> matchingRouteData = new List<RouteData>();
+
+ foreach (var route in this.routes)
+ {
+ var context = new Mock<HttpContextBase>();
+ var request = new Mock<HttpRequestBase>();
+
+ context.Setup(ctx => ctx.Request).Returns(request.Object);
+ request.Setup(req => req.PathInfo).Returns(string.Empty);
+ request.Setup(req => req.AppRelativeCurrentExecutionFilePath).Returns(virtualPath);
+ if (!string.IsNullOrEmpty(httpMethod))
+ {
+ request.Setup(req => req.HttpMethod).Returns(httpMethod);
+ }
+
+ RouteData routeData = this.routes.GetRouteData(context.Object);
+ if (routeData != null)
+ matchingRouteData.Add(routeData);
+ }
+
+ return matchingRouteData;
+ }
+ }
+}
View
89 src/UnitTests/RouteMockHelpers.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Specialized;
+using System.Web;
+using Moq;
+
+namespace UnitTests
+{
+ public static class RoutingMockHelpers
+ {
+ public static HttpContextBase FakeHttpContext()
+ {
+ var context = new Mock<HttpContextBase>();
+ var request = new Mock<HttpRequestBase>();
+ var response = new Mock<HttpResponseBase>();
+ var session = new Mock<HttpSessionStateBase>();
+ var server = new Mock<HttpServerUtilityBase>();
+
+ context.Setup(ctx => ctx.Request).Returns(request.Object);
+ context.Setup(ctx => ctx.Response).Returns(response.Object);
+ context.Setup(ctx => ctx.Session).Returns(session.Object);
+ context.Setup(ctx => ctx.Server).Returns(server.Object);
+
+ return context.Object;
+ }
+
+ public static HttpContextBase FakeHttpContext(string virtualPath)
+ {
+ HttpContextBase context = FakeHttpContext();
+ context.Request.SetupRequestUrl(virtualPath);
+ return context;
+ }
+
+ static string GetUrlFileName(string url)
+ {
+ if (url.Contains("?"))
+ return url.Substring(0, url.IndexOf("?"));
+ else
+ return url;
+ }
+
+ static NameValueCollection GetQueryStringParameters(string url)
+ {
+ if (url.Contains("?"))
+ {
+ NameValueCollection parameters = new NameValueCollection();
+
+ string[] parts = url.Split("?".ToCharArray());
+ string[] keys = parts[1].Split("&".ToCharArray());
+
+ foreach (string key in keys)
+ {
+ string[] part = key.Split("=".ToCharArray());
+ parameters.Add(part[0], part[1]);
+ }
+
+ return parameters;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public static void SetHttpMethodResult(this HttpRequestBase request, string httpMethod)
+ {
+ Mock.Get(request)
+ .Setup(req => req.HttpMethod)
+ .Returns(httpMethod);
+ }
+
+ public static void SetupRequestUrl(this HttpRequestBase request, string url)
+ {
+ if (url == null)
+ throw new ArgumentNullException("url");
+
+ if (!url.StartsWith("~/"))
+ throw new ArgumentException("Sorry, we expect a virtual url starting with \"~/\".");
+
+ var mock = Mock.Get(request);
+
+ mock.Setup(req => req.QueryString)
+ .Returns(GetQueryStringParameters(url));
+ mock.Setup(req => req.AppRelativeCurrentExecutionFilePath)
+ .Returns(GetUrlFileName(url));
+ mock.Setup(req => req.PathInfo)
+ .Returns(string.Empty);
+ }
+ }
+}
View
74 src/UnitTests/RouteTests.cs
@@ -0,0 +1,74 @@
+using System.Web;
+using System.Web.Routing;
+using Moq;
+using RouteTesterDemoWeb;
+using Xunit;
+
+namespace UnitTests
+{
+ public class RouteTests
+ {
+ [Fact]
+ public void CanMatchUsingRouteEvaluator()
+ {
+ var routes = new RouteCollection();
+ GlobalApplication.RegisterRoutes(routes);
+
+ var evaluator = new RouteEvaluator(routes);
+ var matchingRouteData = evaluator.GetMatches("~/foo/bar");
+ Assert.True(matchingRouteData.Count > 0);
+ matchingRouteData = evaluator.GetMatches("~/foo/bar/baz/quux/yadda/billy");
+ Assert.Equal(0, matchingRouteData.Count);
+ }
+
+ [Fact]
+ public void CanMatchFooRouteTheShortWay()
+ {
+ var routes = new RouteCollection();
+ GlobalApplication.RegisterRoutes(routes);
+
+ var context = RoutingMockHelpers.FakeHttpContext("~/foo/bar");
+ var routeData = routes.GetRouteData(context);
+ Assert.Equal("bar", routeData.Values["id"]);
+
+ //Assert defaults.
+ Assert.Equal("Away", routeData.Values["controller"]);
+ Assert.Equal("Blah", routeData.Values["action"]);
+ }
+
+ [Fact]
+ public void CanMatchFooTheLongWay()
+ {
+ var routes = new RouteCollection();
+ GlobalApplication.RegisterRoutes(routes);
+
+ var contextMock = new Mock<HttpContextBase>();
+ var requestMock = new Mock<HttpRequestBase>();
+
+ contextMock.Setup(ctx => ctx.Request).Returns(requestMock.Object);
+ requestMock.Setup(req => req.PathInfo).Returns(string.Empty);
+ requestMock.Setup(req => req.AppRelativeCurrentExecutionFilePath).Returns("~/foo/bar");
+
+ var routeData = routes.GetRouteData(contextMock.Object);
+ Assert.Equal("bar", routeData.Values["id"]);
+
+ //Assert defaults.
+ Assert.Equal("Away", routeData.Values["controller"]);
+ Assert.Equal("Blah", routeData.Values["action"]);
+ }
+
+ [Fact]
+ public void CanMatchEmptyUrl()
+ {
+ RouteCollection routes = new RouteCollection();
+ routes.Add(new Route(string.Empty, new Mock<IRouteHandler>().Object)
+ { Defaults = new RouteValueDictionary(new { controller = "Home" }) });
+
+ var context = RoutingMockHelpers.FakeHttpContext("~/");
+ var routeData = routes.GetRouteData(context);
+ Assert.NotNull(routeData);
+ Assert.Equal("Home", routeData.Values["controller"]);
+
+ }
+ }
+}
View
9 src/UnitTests/UnitTests.csproj
@@ -38,8 +38,10 @@
<HintPath>..\packages\PowerAssert.1.0\PowerAssert.dll</HintPath>
</Reference>
<Reference Include="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Web" />
+ <Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -54,6 +56,9 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="RouteEvaluator.cs" />
+ <Compile Include="RouteMockHelpers.cs" />
+ <Compile Include="RouteTests.cs" />
<Compile Include="RouteValueDictionaryExtensionsTest.cs" />
<Compile Include="GroupRouteTest.cs" />
<Compile Include="HttpHandlers\DelegateHttpHandlerTest.cs" />
@@ -70,6 +75,10 @@
<WCFMetadata Include="Service References\" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\RouteDebuggerDemoWeb\RouteDebuggerDemoWeb.csproj">
+ <Project>{40F914CD-F707-4A4D-AF7B-75E8928055BB}</Project>
+ <Name>RouteDebuggerDemoWeb</Name>
+ </ProjectReference>
<ProjectReference Include="..\RouteMagic.Mvc\RouteMagic.Mvc.csproj">
<Project>{D9321DA3-F3AC-4567-8452-B1B5D5633045}</Project>
<Name>RouteMagic.Mvc</Name>

0 comments on commit 8819e49

Please sign in to comment.