public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
     VirtualPathData result = null;
     if (values.ContainsKey("legacyURL") && urls.Contains((string)values["legacyURL"], StringComparer.OrdinalIgnoreCase)) {
         result = new VirtualPathData(this, new UrlHelper(requestContext).Content((string)values["legacyURL"]).Substring(1));
     }
     return result;            
 }
        public ChildActionExtensionsTest()
        {
            route = new Mock<RouteBase>();
            route.Setup(r => r.GetVirtualPath(It.IsAny<RequestContext>(), It.IsAny<RouteValueDictionary>()))
                .Returns(() => virtualPathData);

            virtualPathData = new VirtualPathData(route.Object, "~/VirtualPath");

            routes = new RouteCollection();
            routes.Add(route.Object);

            originalRouteData = new RouteData();

            string returnValue = "";
            httpContext = new Mock<HttpContextBase>();
            httpContext.Setup(hc => hc.Request.ApplicationPath).Returns("~");
            httpContext.Setup(hc => hc.Response.ApplyAppPathModifier(It.IsAny<string>()))
                .Callback<string>(s => returnValue = s)
                .Returns(() => returnValue);
            httpContext.Setup(hc => hc.Server.Execute(It.IsAny<IHttpHandler>(), It.IsAny<TextWriter>(), It.IsAny<bool>()));

            viewContext = new ViewContext
            {
                RequestContext = new RequestContext(httpContext.Object, originalRouteData)
            };

            viewDataContainer = new Mock<IViewDataContainer>();

            htmlHelper = new Mock<HtmlHelper>(viewContext, viewDataContainer.Object, routes);
        }
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary routeValues) {
            // Lookup best match for route values in the expanded tree
            var match = _aliasMap.Locate(routeValues);
            if (match != null) {
                // Build any "spare" route values onto the Alias (so we correctly support any additional query parameters)
                var sb = new StringBuilder(match.Item2);
                var extra = 0;
                foreach (var routeValue in routeValues) {
                    // Ignore any we already have
                    if (match.Item1.ContainsKey(routeValue.Key)) {
                        continue;
                    }

                    // Add a query string fragment
                    sb.Append((extra++ == 0) ? '?' : '&');
                    sb.Append(Uri.EscapeDataString(routeValue.Key));
                    sb.Append('=');
                    sb.Append(Uri.EscapeDataString(Convert.ToString(routeValue.Value, CultureInfo.InvariantCulture)));
                }
                // Construct data
                var data = new VirtualPathData(this, sb.ToString());
                // Set the Area for this route
                data.DataTokens["area"] = Area;
                return data;
            }

            return null;
        }
        public HostedHttpVirtualPathData(VirtualPathData virtualPath)
        {
            if (virtualPath == null)
            {
                throw Error.ArgumentNull("route");
            }

            _virtualPath = virtualPath;
            _hostedHttpRoute = new HostedHttpRoute(_virtualPath.Route as Route);
        }
        public HostedHttpVirtualPathData(VirtualPathData virtualPath, IHttpRoute httpRoute)
        {
            if (virtualPath == null)
            {
                throw Error.ArgumentNull("route");
            }

            _virtualPath = virtualPath;
            Route = httpRoute;
        }
        void LowercaseUrlPath(VirtualPathData pathData)
        {
            var url = pathData.VirtualPath;
            var queryIndex = url.IndexOf('?');
            if (queryIndex < 0) queryIndex = url.Length;

            pathData.VirtualPath =
                url.Substring(0, queryIndex).ToLowerInvariant() +
                url.Substring(queryIndex);
        }
        public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("httpContext");
            }
            VirtualPathData vp = null;

            if (!String.IsNullOrEmpty(name))
            {
                RouteBase rb = this [name];
                if (rb != null)
                {
                    vp = rb.GetVirtualPath(requestContext, values);
                }
                else
                {
                    throw new ArgumentException("A route named '" + name + "' could not be found in the route collection.", "name");
                }
            }
            else
            {
                foreach (RouteBase rb in this)
                {
                    vp = rb.GetVirtualPath(requestContext, values);
                    if (vp != null)
                    {
                        break;
                    }
                }
            }

            if (vp != null)
            {
                string appPath = requestContext.HttpContext.Request.ApplicationPath;
                if (appPath != null && (appPath.Length == 0 || !appPath.EndsWith("/", StringComparison.Ordinal)))
                {
                    appPath += "/";
                }

                string pathWithApp = String.Concat(appPath, vp.VirtualPath);
                vp.VirtualPath = requestContext.HttpContext.Response.ApplyAppPathModifier(pathWithApp);
                return(vp);
            }

            return(null);
        }
Exemple #8
0
 public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
 {
     requestContext = this.GetRequestContext(requestContext);
     using (this.GetReadLock())
     {
         foreach (RouteBase base2 in this)
         {
             VirtualPathData virtualPath = base2.GetVirtualPath(requestContext, values);
             if (virtualPath != null)
             {
                 virtualPath.VirtualPath = GetUrlWithApplicationPath(requestContext, virtualPath.VirtualPath);
                 return(virtualPath);
             }
         }
     }
     return(null);
 }
Exemple #9
0
        public string GetSubstitutedVirtualPath(RequestContext requestContext)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }
            if (!this._useRouteVirtualPath)
            {
                return(this.VirtualPath);
            }
            VirtualPathData virtualPath = this.RouteVirtualPath.GetVirtualPath(requestContext, requestContext.RouteData.Values);

            if (virtualPath == null)
            {
                return(this.VirtualPath);
            }
            return("~/" + virtualPath.VirtualPath);
        }
        public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            requestContext = GetRequestContext(requestContext);

            // Go through all the configured routes and find the first one that returns a match
            using (GetReadLock()) {
                foreach (RouteBase route in this)
                {
                    VirtualPathData vpd = route.GetVirtualPath(requestContext, values);
                    if (vpd != null)
                    {
                        vpd.VirtualPath = NormalizeVirtualPath(requestContext, vpd.VirtualPath);
                        return(vpd);
                    }
                }
            }

            return(null);
        }
Exemple #11
0
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            if (requestContext == null)
            {
                throw new ArgumentNullException("requestContext");
            }
            if (url == null)
            {
                return(new VirtualPathData(this, String.Empty));
            }

            // null values is allowed.
            // if (values == null)
            //  values = requestContext.RouteData.Values;

            RouteValueDictionary usedValues;
            string resultUrl = url.BuildUrl(this, requestContext, values, Constraints, out usedValues);

            if (resultUrl == null)
            {
                return(null);
            }

            if (!ProcessConstraints(requestContext.HttpContext, usedValues, RouteDirection.UrlGeneration))
            {
                return(null);
            }

            var result = new VirtualPathData(this, resultUrl);

            RouteValueDictionary dataTokens = DataTokens;

            if (dataTokens != null)
            {
                foreach (var item in dataTokens)
                {
                    result.DataTokens[item.Key] = item.Value;
                }
            }

            return(result);
        }
Exemple #12
0
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            Uri uri = requestContext.HttpContext.Request.Url;
            Uri baseAddress = new Uri(string.Format("{0}://{1}",uri.Scheme, uri.Authority));
            Dictionary<string, string> variables = new Dictionary<string, string>();
            foreach (var item in values)
            {
                variables.Add(item.Key, item.Value.ToString());
            }

            //确定段变量是否被提供
            foreach (var name in this.UriTemplate.PathSegmentVariableNames)
            {
                if (!this.UriTemplate.Defaults.Keys.Any(
                    key => string.Compare(name, key, true) == 0) &&
                    !values.Keys.Any(key => string.Compare(name, key, true) == 0))
                {
                    return null;
                }
            }
            //确定查询变量是否被提供
            foreach (var name in this.UriTemplate.QueryValueVariableNames)
            {
                if (!this.UriTemplate.Defaults.Keys.Any(
                    key => string.Compare(name, key, true) == 0) &&
                    !values.Keys.Any(key => string.Compare(name, key, true) == 0))
                {
                    return null;
                }
            }

            Uri virtualPath = this.UriTemplate.BindByName(baseAddress, variables);
            string strVirtualPath = virtualPath.ToString().ToLower().Replace(baseAddress.ToString().ToLower(), "");
            VirtualPathData virtualPathData = new VirtualPathData(this,strVirtualPath);
            foreach (var token in this.DataTokens)
            {
                virtualPathData.DataTokens.Add(token.Key, token.Value);
            }
            return virtualPathData;
        }
Exemple #13
0
        public static void FillVirtualPath(VirtualPathData virtualPathData)
        {
            HttpContext context = HttpContext.Current;
            if (context == null)
                throw new ArgumentNullException("HttpContext");
            HttpRequest request = context.Request;
            if (request == null)
                throw new ArgumentNullException("Request");

            string virtualPath = virtualPathData.VirtualPath;

            if (virtualPath == null)
                throw new ArgumentNullException("virtualPath");

            if (virtualPath == string.Empty)
                return;
            if (VirtualPathUtility.IsAppRelative(virtualPath))
                virtualPath = VirtualPathUtility.ToAbsolute(virtualPath);

            PortalAlias alias = PortalManager.GetPortalAlias(request.Url.Host, request.Url.Port, request.IsSecureConnection);
            virtualPath = alias.ToString() + virtualPath;
            virtualPathData.VirtualPath = virtualPath;
        }
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            BoundUrl url = this._parsedRoute.Bind(requestContext.RouteData.Values, values, this.Defaults, this.Constraints);

            if (url == null)
            {
                return(null);
            }
            if (!this.ProcessConstraints(requestContext.HttpContext, url.Values, RouteDirection.UrlGeneration))
            {
                return(null);
            }
            VirtualPathData data = new VirtualPathData(this, url.Url);

            if (this.DataTokens != null)
            {
                foreach (KeyValuePair <string, object> pair in this.DataTokens)
                {
                    data.DataTokens[pair.Key] = pair.Value;
                }
            }
            return(data);
        }
        public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values)
        {
            requestContext = GetRequestContext(requestContext);

            if (!String.IsNullOrEmpty(name))
            {
                RouteBase namedRoute;
                bool      routeFound;
                using (GetReadLock()) {
                    routeFound = _namedMap.TryGetValue(name, out namedRoute);
                }
                if (routeFound)
                {
                    VirtualPathData vpd = namedRoute.GetVirtualPath(requestContext, values);
                    if (vpd != null)
                    {
                        vpd.VirtualPath = NormalizeVirtualPath(requestContext, vpd.VirtualPath);
                        return(vpd);
                    }
                    return(null);
                }
                else
                {
                    throw new ArgumentException(
                              String.Format(
                                  CultureInfo.CurrentUICulture,
                                  SR.GetString(SR.RouteCollection_NameNotFound),
                                  name),
                              "name");
                }
            }
            else
            {
                return(GetVirtualPath(requestContext, values));
            }
        }
Exemple #16
0
        /// <summary>
        ///     When overridden in a derived class, checks whether the route matches the specified values, and if so, generates a
        ///     URL and retrieves information about the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        ///     An object that contains the generated URL and information about the route, or null if the route does not match
        ///     <paramref name="values" />.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var model = values[CurrentPageKey] as IPage;

            if (model == null)
            {
                return null;
            }

            var vpd = new VirtualPathData(this, VirtualPathResolver.Resolve(model, values));

            vpd.VirtualPath = string.Format("/ui/pages".TrimStart(new[] {'/'}) + "/{0}", vpd.VirtualPath);

            string queryParams = String.Empty;
            // add query string parameters
            foreach (var kvp in values)
            {
                if (kvp.Key.Equals(CurrentPageKey) || kvp.Key.Equals(ControllerKey) || kvp.Key.Equals(ActionKey))
                {
                    continue;
                }
                queryParams = queryParams.AddQueryParam(kvp.Key, kvp.Value.ToString());
            }
            vpd.VirtualPath += queryParams;
            return vpd;
        }
Exemple #17
0
        /// <summary>
        /// Returns information about the URL that is associated with the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains information about the URL that is associated with the route.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var model = values[ModelKey] as IPageModel;

            if (model == null) {
                VirtualPathData path = base.GetVirtualPath(requestContext, values);

                if (path != null && path.VirtualPath != "")
                    path.VirtualPath = path.VirtualPath + "/";
                return path;
            }

            var vpd = new VirtualPathData(this, this.VirtualPathResolver.ResolveVirtualPath(model, values));

            vpd.Route = this;

            vpd.VirtualPath = string.Format("/ui/pages".TrimStart(new[] { '/' }) + "/{0}", VirtualPathResolver.ResolveVirtualPath(model, values));

            var queryParams = String.Empty;
            // add query string parameters
            foreach (var kvp in values) {
                if (kvp.Key.Equals(ModelKey) || kvp.Key.Equals(ControllerKey) || kvp.Key.Equals(ActionKey)) {
                    continue;
                }
                queryParams = queryParams.AddQueryParam(kvp.Key, kvp.Value.ToString());
            }
            vpd.VirtualPath += queryParams;

            return vpd;
        }
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            string url;
            if (GenerateUrls != null)
            {
                url = GenerateUrls(this, requestContext, values);
                if (url.StartsWith("/"))
                    url = url.Substring(1);
            }
            else
                return base.GetVirtualPath(requestContext, values);

            //was this url valid?
            if (!UrlRegex.IsMatch(url))
                return null;

            var data = new VirtualPathData(this, url);
            if (DataTokens != null)
            {
                foreach (KeyValuePair<string, object> pair in DataTokens)
                {
                    data.DataTokens[pair.Key] = pair.Value;
                }
            }

            Url = url;

            return data;
        }
Exemple #19
0
    /// <summary>
    /// 创建 VirtualPathData 对象
    /// </summary>
    /// <param name="virtualPath">虚拟路径</param>
    /// <param name="rule">产生该虚拟路径的路由规则</param>
    /// <returns>VirtualPathData 对象</returns>
    protected VirtualPathData CreateVirtualPathData( string virtualPath, SimpleRouteRule rule )
    {
      var data = new VirtualPathData( this, virtualPath );


      foreach ( var pair in rule.DataTokens )
        data.DataTokens.Add( pair.Key, pair.Value );

      data.DataTokens["RoutingRuleName"] = rule.Name;

      return data;
    }
Exemple #20
0
        /// <summary>
        /// Returns information about the URL that is associated with the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains information about the URL that is associated with the route.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            RouteUrl url = this.Bind(requestContext.RouteData.Values, values);

            if (url == null)
            {
                return null;
            }

            if (!this.ProcessConstraints(requestContext.HttpContext, url.Values, RouteDirection.UrlGeneration))
            {
                return null;
            }

            VirtualPathData data = new VirtualPathData(this, url.Url);

            if (this.DataTokens != null)
            {
                foreach (KeyValuePair<string, object> pair in this.DataTokens)
                {
                    data.DataTokens[pair.Key] = pair.Value;
                }
            }

            return data;
        }
Exemple #21
0
        /// <summary>
        /// Returns information about the URL that is associated with the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains information about the URL that is associated with the route.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var model = values[ModelKey] as IPageModel;

            if (model == null) {
                return null;
            }

            var vpd = new VirtualPathData(this, this.VirtualPathResolver.ResolveVirtualPath(model, values));

            var queryParams = String.Empty;
            // add query string parameters
            foreach (var kvp in values) {
                if (kvp.Key.Equals(ModelKey) || kvp.Key.Equals(ControllerKey) || kvp.Key.Equals(ActionKey)) {
                    continue;
                }
                queryParams = queryParams.AddQueryParam(kvp.Key, kvp.Value.ToString());
            }
            vpd.VirtualPath += queryParams;
            return vpd;
        }
Exemple #22
0
		public override VirtualPathData GetVirtualPath (RequestContext requestContext, RouteValueDictionary values)
		{
			if (requestContext == null)
				throw new ArgumentNullException ("requestContext");
			if (url == null)
				return new VirtualPathData (this, String.Empty);

			// null values is allowed.
			// if (values == null)
			// 	values = requestContext.RouteData.Values;

			RouteValueDictionary usedValues;
			string resultUrl = url.BuildUrl (this, requestContext, values, Constraints, out usedValues);

			if (resultUrl == null)
				return null;

			if (!ProcessConstraints (requestContext.HttpContext, usedValues, RouteDirection.UrlGeneration))
				return null;

			var result = new VirtualPathData (this, resultUrl);

			RouteValueDictionary dataTokens = DataTokens;
			if (dataTokens != null) {
				foreach (var item in dataTokens)
					result.DataTokens[item.Key] = item.Value;
			}

			return result;
		}
Exemple #23
0
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
            // Try to generate a URL that represents the values passed in based on current
            // values from the RouteData and new values using the specified Route.

            BoundUrl result = _parsedRoute.Bind(requestContext.RouteData.Values, values, Defaults, Constraints);

            if (result == null) {
                return null;
            }

            // Verify that the route matches the validation rules
            if (!ProcessConstraints(requestContext.HttpContext, result.Values, RouteDirection.UrlGeneration)) {
                return null;
            }

            VirtualPathData vpd = new VirtualPathData(this, result.Url);

            // Add the DataTokens from the Route to the VirtualPathData
            if (DataTokens != null) {
                foreach (var prop in DataTokens) {
                    vpd.DataTokens[prop.Key] = prop.Value;
                }
            }
            return vpd;
        }
Exemple #24
0
        /// <summary>
        /// 尝试从路由值创建虚拟路径
        /// </summary>
        /// <param name="requestContext">当前请求上下文</param>
        /// <param name="values">路由值</param>
        /// <returns>虚拟路径信息</returns>
        public override VirtualPathData GetVirtualPath( RequestContext requestContext, RouteValueDictionary values )
        {
            var cache = requestContext.HttpContext.Cache;

              var _values = values.ToDictionary( pair => pair.Key, pair => pair.Value == null ? null : pair.Value.ToString(), StringComparer.OrdinalIgnoreCase );

              var cacheKey = CreateCacheKey( _values );

              var virtualPath = cache.Get( cacheKey ) as string;

              if ( virtualPath != null )
            return new VirtualPathData( this, virtualPath );

              var keySet = new HashSet<string>( _values.Keys, StringComparer.OrdinalIgnoreCase );

              var candidateRules = _rules
            .Where( r => !r.Oneway )                                               //不是单向路由规则
            .Where( r => keySet.IsSupersetOf( r.RouteKeys ) )                      //所有路由键都必须匹配
            .Where( r => keySet.IsSubsetOf( r.AllKeys ) || !r.LimitedQueries )     //所有路由键和查询字符串键必须能涵盖要设置的键。
            .Where( r => r.IsMatch( _values ) )                                    //必须满足路由规则所定义的路由数据。
            .ToArray();

              if ( !candidateRules.Any() )
            return null;

              var bestRule = BestRule( candidateRules );

              virtualPath = bestRule.CreateVirtualPath( _values );

              if ( MvcCompatible )
            virtualPath = virtualPath.Substring( 2 );

              cache.Insert( cacheKey, virtualPath, CacheItemPriority.AboveNormal );

              var data = new VirtualPathData( this, virtualPath );

              foreach ( var pair in bestRule.DataTokens )
            data.DataTokens.Add( pair.Key, pair.Value );

              data.DataTokens["RoutingRuleName"] = bestRule.Name;

              return data;
        }
Exemple #25
0
        /// <summary>
        /// Returns information about the URL that is associated with the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains information about the URL that is associated with the route.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            if (KarbonWebContext.Current == null)
                return null;

            // Grab the model from the route data collection
            var model = KarbonWebContext.Current.CurrentPage;
            if (model == null)
                return null;

            // Create virtual path from model url
            var vpd = new VirtualPathData(this, model.RelativeUrl.TrimStart("~/"));

            // Append any other route data values as querystring params
            var queryParams = values.Where(kvp => !kvp.Key.Equals(ControllerKey)
                && !kvp.Key.Equals(ActionKey))
                .ToQueryString();

            vpd.VirtualPath += queryParams;

            // Return the virtual path
            return vpd;
        }
        private VirtualPathData GetTranslatedVirtualPath(VirtualPathData virtualPathData, RequestContext requestContext, RouteValueDictionary values)
        {
            if (Translations == null || !Translations.Any())
                return virtualPathData;

            var currentCultureName = Thread.CurrentThread.CurrentUICulture.Name;

            // Try and get the language-culture translation, then fall back to language translation
            var translation = Translations.FirstOrDefault(t => t.CultureName == currentCultureName)
                              ?? Translations.FirstOrDefault(t => currentCultureName.StartsWith(t.CultureName));

            if (translation == null)
                return virtualPathData;

            return translation.GetVirtualPath(requestContext, values);
        }
 public void RouteGeneratorCallsCustomFunctionIfProvided()
 {
     bool called = false;
     RequestContext innerContext = null;
     RouteValueDictionary innerRouteValues = null;
     RegexRoute innerRoute = null;
     VirtualPathData innerPathData = null;
     var route = new RegexRoute(
         @"(?<Controller>[a-zA-Z]+)(_(?<Action>[a-zA-Z]+))?(_?<Id>\d+)?",
         delegate(RequestContext context, RouteValueDictionary routeValues, RegexRoute thisRoute)
             {
                 called = true;
                 innerContext = context;
                 innerRouteValues = routeValues;
                 innerRoute = thisRoute;
                 innerPathData = new VirtualPathData(thisRoute, "");
                 return innerPathData;
             },
         handler);
     RouteData routeData = route.GetRouteData("Products_View_0");
     var values = new RouteValueDictionary(new {Controller = "Accounts", Action = "Delete", Id = 0});
     var requestContext = new RequestContext(mr.PartialMock<HttpContextBase>(), routeData);
     VirtualPathData pathData = route.GetVirtualPath(
         requestContext,
         values);
     Assert.IsTrue(called);
     Assert.IsNotNull(innerContext);
     Assert.AreSame(requestContext, innerContext);
     Assert.IsNotNull(innerRouteValues);
     Assert.AreSame(values, innerRouteValues);
     Assert.IsNotNull(innerRoute);
     Assert.AreSame(route, innerRoute);
     Assert.IsNotNull(pathData);
     Assert.AreSame(pathData, innerPathData);
 }
Exemple #28
0
        /// <summary>
        /// Returns information about the URL that is associated with the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains information about the URL that is associated with the route.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            var model = values[ModelKey] as IPageModel;

            if (model == null) {
                //return base.GetVirtualPath(requestContext, values);
                return null;
            }

            var vpd = new VirtualPathData(this, this.VirtualPathResolver.ResolveVirtualPath(model, values));

            //var vpd = base.GetVirtualPath(requestContext, values);

            //if (vpd == null)
            //    return null;

            vpd.Route = this;

            vpd.VirtualPath = string.Format("pages/{0}", VirtualPathResolver.ResolveVirtualPath(model, values));

            return vpd;
        }