// ILM Professional Services, Inc. licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // // Copyright 2008 ILM Professional Services, Inc. using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Routing; using Castle.MonoRail.Framework; using Castle.MonoRail.Framework.Routing; namespace ILM.Routing { public class MonoRailRouteHandler : MonoRailHttpHandlerFactory, IRouteHandler { private static MonoRailRouteHandler _instance = new MonoRailRouteHandler(); public static MonoRailRouteHandler Instance { get { return _instance; } } private class MockUrlTokenizer : IUrlTokenizer { [ThreadStatic] private static UrlInfo _currentUrlInfo; public static UrlInfo CurrentUrlInfo { get { return _currentUrlInfo; } set { _currentUrlInfo = value; } } public void AddDefaultRule(string url, string area, string controller, string action) { throw new NotImplementedException(); } public UrlInfo TokenizeUrl(string filePath, string pathInfo, Uri uri, bool isLocal, string appVirtualDir) { return CurrentUrlInfo; } } public MonoRailRouteHandler() { UrlTokenizer = new MockUrlTokenizer(); } #region IRouteHandler Members public IHttpHandler GetHttpHandler(RequestContext requestContext) { // until monorail uses s.w.abstractions, cheat a bit var context = HttpContext.Current; // parse urlinfo from the s.w.routing data var values = requestContext.RouteData.Values; var info = new UrlInfo( context.Request.Url.Host, context.Request.Url.Host, context.Request.ApplicationPath, context.Request.Url.Scheme, context.Request.Url.Port, context.Request.RawUrl, values.ContainsKey("area") ? (string)values["area"] : String.Empty, values.ContainsKey("controller") ? (string)values["controller"] : String.Empty, values.ContainsKey("action") ? (string)values["action"] : String.Empty, String.Empty, context.Request.Url.Query ); MockUrlTokenizer.CurrentUrlInfo = info; // create a monorail routematch var match = new RouteMatch(); foreach (var pair in values) { match.Parameters.Add(pair.Key, pair.Value as string); } context.Items[RouteMatch.RouteMatchKey] = match; // allow standard monorail handler to proceed var handler = GetHandler( context, context.Request.RequestType, context.Request.RawUrl, context.Request.PhysicalApplicationPath); return handler; } #endregion } public static class RouteCollectionExtensions { public static void Map( this RouteCollection routes, string routeName, string routeUrl) { Map(routes, routeName, routeUrl, null, null); } public static void Map( this RouteCollection routes, string routeName, string routeUrl, object routeDefaults) { Map(routes, routeName, routeUrl, routeDefaults, null); } public static void Map( this RouteCollection routes, string routeName, string routeUrl, object routeDefaults, object routeConstraints) { routes.Add( routeName, new Route( routeUrl, new RouteValueDictionary(routeDefaults), new RouteValueDictionary(routeConstraints), MonoRailRouteHandler.Instance) ); } } /// /// Use with IIS7 as a wildcard handler: /// ]]> /// Otherwise if no handler is associated with "*", IIS7 will give 404s, even when routes are matched. /// public class MockHandlerFactory : IHttpHandlerFactory { #region IHttpHandlerFactory Members public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { return null; } public void ReleaseHandler(IHttpHandler handler) { } #endregion } }