public void VirtualPath_ReturnsEmptyStringIfNull() { // Arrange var router = new Mock<IRouter>().Object; // Act var pathData = new VirtualPathData(router, virtualPath: null); // Assert Assert.Same(router, pathData.Router); Assert.Equal(new PathString(string.Empty), pathData.VirtualPath); Assert.NotNull(pathData.DataTokens); Assert.Empty(pathData.DataTokens); }
public void VirtualPath_ReturnsEmptyStringIfNull() { // Arrange var router = Mock.Of<IRouter>(); // Act var pathData = new VirtualPathData(router, virtualPath: null); // Assert Assert.Same(router, pathData.Router); Assert.Empty(pathData.VirtualPath); Assert.NotNull(pathData.DataTokens); Assert.Empty(pathData.DataTokens); }
public void Constructor_CreatesEmptyDataTokensIfNull() { // Arrange var router = new Mock<IRouter>().Object; var path = new PathString("/virtual path"); // Act var pathData = new VirtualPathData(router, path, null); // Assert Assert.Same(router, pathData.Router); Assert.Equal(path, pathData.VirtualPath); Assert.NotNull(pathData.DataTokens); Assert.Empty(pathData.DataTokens); }
public void Constructor_CopiesDataTokens() { // Arrange var router = new Mock<IRouter>().Object; var path = new PathString("/virtual path"); var dataTokens = new RouteValueDictionary(); dataTokens["TestKey"] = "TestValue"; // Act var pathData = new VirtualPathData(router, path, dataTokens); // Assert Assert.Same(router, pathData.Router); Assert.Equal(path, pathData.VirtualPath); Assert.NotNull(pathData.DataTokens); Assert.Equal("TestValue", pathData.DataTokens["TestKey"]); Assert.Equal(1, pathData.DataTokens.Count); Assert.NotSame(dataTokens, pathData.DataTokens); }
public void Constructor_CopiesDataTokens() { // Arrange var router = new Mock <IRouter>().Object; var path = new PathString("/virtual path"); var dataTokens = new RouteValueDictionary(); dataTokens["TestKey"] = "TestValue"; // Act var pathData = new VirtualPathData(router, path, dataTokens); // Assert Assert.Same(router, pathData.Router); Assert.Equal(path, pathData.VirtualPath); Assert.NotNull(pathData.DataTokens); Assert.Equal("TestValue", pathData.DataTokens["TestKey"]); Assert.Equal(1, pathData.DataTokens.Count); Assert.NotSame(dataTokens, pathData.DataTokens); }
public virtual VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureOptions(context.Context); // If we're using Best-Effort link generation then it means that we'll first look for a route where // the route values are validated (context.IsBound == true). If we can't find a match like that, then // we'll return the path from the first route to return one. var useBestEffort = _options.UseBestEffortLinkGeneration; if (!string.IsNullOrEmpty(context.RouteName)) { var isValidated = false; VirtualPathData bestPathData = null; INamedRouter matchedNamedRoute; if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute)) { bestPathData = matchedNamedRoute.GetVirtualPath(context); isValidated = context.IsBound; } // If we get here and context.IsBound == true, then we know we have a match, we want to keep // iterating to see if we have multiple matches. foreach (var unnamedRoute in _unnamedRoutes) { // reset because we're sharing the context context.IsBound = false; var pathData = unnamedRoute.GetVirtualPath(context); if (pathData == null) { continue; } if (bestPathData != null) { // There was already a previous route which matched the name. throw new InvalidOperationException( Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName)); } else if (context.IsBound) { // This is the first 'validated' match that we've found. bestPathData = pathData; isValidated = true; } else { Debug.Assert(bestPathData == null); // This is the first 'unvalidated' match that we've found. bestPathData = pathData; isValidated = false; } } if (isValidated || useBestEffort) { context.IsBound = isValidated; if (bestPathData != null) { bestPathData = new VirtualPathData( bestPathData.Router, NormalizeVirtualPath(bestPathData.VirtualPath), bestPathData.DataTokens); } return bestPathData; } else { return null; } } else { VirtualPathData bestPathData = null; for (var i = 0; i < Count; i++) { var route = this[i]; var pathData = route.GetVirtualPath(context); if (pathData == null) { continue; } if (context.IsBound) { // This route has validated route values, short circuit. return new VirtualPathData( pathData.Router, NormalizeVirtualPath(pathData.VirtualPath), pathData.DataTokens); } else if (bestPathData == null) { // The values aren't validated, but this is the best we've seen so far bestPathData = pathData; } } if (useBestEffort) { return new VirtualPathData( bestPathData.Router, NormalizeVirtualPath(bestPathData.VirtualPath), bestPathData.DataTokens); } else { return null; } } }
public virtual VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureOptions(context.Context); // If we're using Best-Effort link generation then it means that we'll first look for a route where // the route values are validated (context.IsBound == true). If we can't find a match like that, then // we'll return the path from the first route to return one. var useBestEffort = _options.UseBestEffortLinkGeneration; if (!string.IsNullOrEmpty(context.RouteName)) { var isValidated = false; VirtualPathData bestPathData = null; INamedRouter matchedNamedRoute; if (_namedRoutes.TryGetValue(context.RouteName, out matchedNamedRoute)) { bestPathData = matchedNamedRoute.GetVirtualPath(context); isValidated = context.IsBound; } // If we get here and context.IsBound == true, then we know we have a match, we want to keep // iterating to see if we have multiple matches. foreach (var unnamedRoute in _unnamedRoutes) { // reset because we're sharing the context context.IsBound = false; var pathData = unnamedRoute.GetVirtualPath(context); if (pathData == null) { continue; } if (bestPathData != null) { // There was already a previous route which matched the name. throw new InvalidOperationException( Resources.FormatNamedRoutes_AmbiguousRoutesFound(context.RouteName)); } else if (context.IsBound) { // This is the first 'validated' match that we've found. bestPathData = pathData; isValidated = true; } else { Debug.Assert(bestPathData == null); // This is the first 'unvalidated' match that we've found. bestPathData = pathData; isValidated = false; } } if (isValidated || useBestEffort) { context.IsBound = isValidated; if (bestPathData != null) { bestPathData = new VirtualPathData( bestPathData.Router, NormalizeVirtualPath(bestPathData.VirtualPath), bestPathData.DataTokens); } return(bestPathData); } else { return(null); } } else { VirtualPathData bestPathData = null; for (var i = 0; i < Count; i++) { var route = this[i]; var pathData = route.GetVirtualPath(context); if (pathData == null) { continue; } if (context.IsBound) { // This route has validated route values, short circuit. return(new VirtualPathData( pathData.Router, NormalizeVirtualPath(pathData.VirtualPath), pathData.DataTokens)); } else if (bestPathData == null) { // The values aren't validated, but this is the best we've seen so far bestPathData = pathData; } } if (useBestEffort) { return(new VirtualPathData( bestPathData.Router, NormalizeVirtualPath(bestPathData.VirtualPath), bestPathData.DataTokens)); } else { return(null); } } }
private VirtualPathData NormalizeVirtualPath(VirtualPathData pathData) { if (pathData == null) { return pathData; } var url = pathData.VirtualPath; if (!string.IsNullOrEmpty(url) && (_options.LowercaseUrls || _options.AppendTrailingSlash)) { var indexOfSeparator = url.IndexOfAny(new char[] { '?', '#' }); var urlWithoutQueryString = url; var queryString = string.Empty; if (indexOfSeparator != -1) { urlWithoutQueryString = url.Substring(0, indexOfSeparator); queryString = url.Substring(indexOfSeparator); } if (_options.LowercaseUrls) { urlWithoutQueryString = urlWithoutQueryString.ToLowerInvariant(); } if (_options.AppendTrailingSlash && !urlWithoutQueryString.EndsWith("/")) { urlWithoutQueryString += "/"; } // queryString will contain the delimiter ? or # as the first character, so it's safe to append. url = urlWithoutQueryString + queryString; return new VirtualPathData(pathData.Router, url, pathData.DataTokens); } return pathData; }
/// <inheritdoc /> public virtual VirtualPathData GetVirtualPath(VirtualPathContext context) { EnsureBinder(context.HttpContext); EnsureLoggers(context.HttpContext); var values = _binder.GetValues(context.AmbientValues, context.Values); if (values == null) { // We're missing one of the required values for this route. return null; } if (!RouteConstraintMatcher.Match( Constraints, values.CombinedValues, context.HttpContext, this, RouteDirection.UrlGeneration, _constraintLogger)) { return null; } context.Values = values.CombinedValues; var pathData = OnVirtualPathGenerated(context); if (pathData != null) { // If the target generates a value then that can short circuit. return pathData; } // If we can produce a value go ahead and do it, the caller can check context.IsBound // to see if the values were validated. // When we still cannot produce a value, this should return null. var virtualPath = _binder.BindValues(values.AcceptedValues); if (virtualPath == null) { return null; } pathData = new VirtualPathData(this, virtualPath); if (DataTokens != null) { foreach (var dataToken in DataTokens) { pathData.DataTokens.Add(dataToken.Key, dataToken.Value); } } return pathData; }