public IEnumerable <Endpoint> FindEndpoints(RouteValuesAddress address) { IList <OutboundMatchResult> matchResults = null; if (string.IsNullOrEmpty(address.RouteName)) { matchResults = _allMatchesLinkGenerationTree.GetMatches( address.ExplicitValues, address.AmbientValues); } else if (_namedMatchResults.TryGetValue(address.RouteName, out var namedMatchResults)) { matchResults = namedMatchResults; } if (matchResults != null) { var matchCount = matchResults.Count; if (matchCount > 0) { if (matchResults.Count == 1) { // Special case having a single result to avoid creating iterator state machine return(new[] { (RouteEndpoint)matchResults[0].Match.Entry.Data }); } else { // Use separate method since one cannot have regular returns in an iterator method return(GetEndpoints(matchResults, matchCount)); } } } return(Array.Empty <Endpoint>()); }
/// <inheritdoc /> public VirtualPathData GetVirtualPath(VirtualPathContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // If it's a named route we will try to generate a link directly and // if we can't, we will not try to generate it using an unnamed route. if (context.RouteName != null) { return(GetVirtualPathForNamedRoute(context)); } // The decision tree will give us back all entries that match the provided route data in the correct // order. We just need to iterate them and use the first one that can generate a link. var matches = _linkGenerationTree.GetMatches(context); foreach (var match in matches) { var path = GenerateVirtualPath(context, match.Entry); if (path != null) { context.IsBound = true; return(path); } } return(null); }
public void SelectMultipleEntries_BothMatch_OrderedByTemplate() { // Arrange var entries = new List <OutboundMatch>(); var entry1 = CreateMatch(new { controller = "Store", action = "Buy" }); entry1.Entry.RouteTemplate = TemplateParser.Parse("a"); entries.Add(entry1); var entry2 = CreateMatch(new { controller = "Store", action = "Buy" }); entry2.Entry.RouteTemplate = TemplateParser.Parse("b"); entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList(); // Assert Assert.Equal(entries, matches); }
public void SelectMultipleEntries_BothMatch_CriteriaSubset() { // Arrange var entries = new List <OutboundMatch>(); var entry1 = CreateMatch(new { controller = "Store", action = "Buy" }); entries.Add(entry1); var entry2 = CreateMatch(new { controller = "Store" }); entry2.Entry.Order = 1; entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { controller = "Store" }, ambientValues: new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList(); // Assert Assert.Equal(entries, matches); }
public void SelectMultipleEntries_BothMatch_OrderedByPrecedence() { // Arrange var entries = new List <TreeRouteLinkGenerationEntry>(); var entry1 = CreateEntry(new { controller = "Store", action = "Buy" }); entry1.GenerationPrecedence = 1; entries.Add(entry1); var entry2 = CreateEntry(new { controller = "Store", action = "Buy" }); entry2.GenerationPrecedence = 0; entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context).Select(m => m.Entry).ToList(); // Assert Assert.Equal(entries, matches); }
public void GetMatches_LinkToPageFromController_WithActionValueAmbiguous() { // Arrange var entries = new List <OutboundMatch>(); var entry1 = CreateMatch(new { controller = "Home", action = "Index", area = (string)null, page = (string)null, }); entry1.Entry.RouteTemplate = TemplateParser.Parse("a"); entries.Add(entry1); var entry2 = CreateMatch(new { page = "/Store/Buy", area = (string)null, controller = (string)null, action = (string)null, }); entry2.Entry.RouteTemplate = TemplateParser.Parse("b"); entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { page = "/Store/Buy", action = "Index", }, new { controller = "Home", action = "Index", page = "16", }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList(); // Assert Assert.Empty(matches); }
public void GetMatches_PagesWithArea_AllValuesAmbient() { // Arrange var entries = new List <OutboundMatch>(); var entry1 = CreateMatch(new { page = "/Store/Buy", area = (string)null, }); entry1.Entry.RouteTemplate = TemplateParser.Parse("a"); entries.Add(entry1); var entry2 = CreateMatch(new { page = "/Store/Buy", area = "Admin" }); entry2.Entry.RouteTemplate = TemplateParser.Parse("b"); entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { }, new { page = "/Store/Buy", area = "Admin", }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues).Select(m => m.Match).ToList(); // Assert Assert.Collection( matches, m => { Assert.Same(entry2, m); }, m => { Assert.Same(entry1, m); }); }
/// <inheritdoc /> public VirtualPathData GetVirtualPath(VirtualPathContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } // If it's a named route we will try to generate a link directly and // if we can't, we will not try to generate it using an unnamed route. if (context.RouteName != null) { return(GetVirtualPathForNamedRoute(context)); } // The decision tree will give us back all entries that match the provided route data in the correct // order. We just need to iterate them and use the first one that can generate a link. var matches = _linkGenerationTree.GetMatches(context.Values, context.AmbientValues); if (matches == null) { return(null); } for (var i = 0; i < matches.Count; i++) { var path = GenerateVirtualPath(context, matches[i].Match.Entry, matches[i].Match.TemplateBinder); if (path != null) { return(path); } } return(null); }
public void SelectMultipleEntries_OneDoesntMatch() { // Arrange var entries = new List <OutboundMatch>(); var entry1 = CreateMatch(new { controller = "Store", action = "Buy" }); entries.Add(entry1); var entry2 = CreateMatch(new { controller = "Store", action = "Cart" }); entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { controller = "Store" }, ambientValues: new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues); // Assert Assert.Same(entry1, Assert.Single(matches).Match); }
public void SelectSingleEntry_MultipleCriteria() { // Arrange var entries = new List<AttributeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context); // Assert Assert.Same(entry, Assert.Single(matches).Entry); }
public void SelectSingleEntry_NoCriteria() { // Arrange var entries = new List<TreeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { }); // Act var matches = tree.GetMatches(context); // Assert Assert.Same(entry, Assert.Single(matches).Entry); }
public void SelectSingleEntry_NoCriteria() { // Arrange var entries = new List <OutboundMatch>(); var entry = CreateMatch(new { }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { }); // Act var matches = tree.GetMatches(context); // Assert Assert.Same(entry, Assert.Single(matches).Match); }
public void SelectSingleEntry_MultipleCriteria() { // Arrange var entries = new List <TreeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context); // Assert Assert.Same(entry, Assert.Single(matches).Entry); }
public void GetMatches_AllowsNullAmbientValues() { // Arrange var entries = new List <OutboundMatch>(); var entry = CreateMatch(new { }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { }); // Act var matches = tree.GetMatches(context.Values, ambientValues: null); // Assert Assert.Same(entry, Assert.Single(matches).Match); }
public void SelectSingleEntry_MultipleCriteria_NoMatch() { // Arrange var entries = new List <OutboundMatch>(); var entry = CreateMatch(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "AddToCart" }); // Act var matches = tree.GetMatches(context); // Assert Assert.Empty(matches); }
public void SelectSingleEntry_MultipleCriteria() { // Arrange var entries = new List <OutboundMatch>(); var entry = CreateMatch(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues); // Assert Assert.Same(entry, Assert.Single(matches).Match); }
public void SelectSingleEntry_MultipleCriteria_AmbientValues() { // Arrange var entries = new List<AttributeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(values: null, ambientValues: new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context); // Assert var match = Assert.Single(matches); Assert.Same(entry, match.Entry); Assert.False(match.IsFallbackMatch); }
public void SelectSingleEntry_MultipleCriteria_AmbientValue_NoMatch() { // Arrange var entries = new List <TreeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { controller = "Store" }, ambientValues: new { controller = "Store", action = "Cart" }); // Act var matches = tree.GetMatches(context); // Assert Assert.Empty(matches); }
public void SelectSingleEntry_MultipleCriteria_AmbientValues() { // Arrange var entries = new List <TreeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(values: null, ambientValues: new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context); // Assert var match = Assert.Single(matches); Assert.Same(entry, match.Entry); Assert.False(match.IsFallbackMatch); }
public void SelectSingleEntry_MultipleCriteria_Replaced() { // Arrange var entries = new List <OutboundMatch>(); var entry = CreateMatch(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { action = "Buy" }, ambientValues: new { controller = "Store", action = "Cart" }); // Act var matches = tree.GetMatches(context.Values, context.AmbientValues); // Assert var match = Assert.Single(matches); Assert.Same(entry, match.Match); Assert.False(match.IsFallbackMatch); }
public void SelectMultipleEntries_BothMatch_NonOverlappingCriteria() { // Arrange var entries = new List <TreeRouteLinkGenerationEntry>(); var entry1 = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry1); var entry2 = CreateEntry(new { slug = "1234" }); entry2.Order = 1; entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy", slug = "1234" }); // Act var matches = tree.GetMatches(context).Select(m => m.Entry).ToList(); // Assert Assert.Equal(entries, matches); }
public IEnumerable <Endpoint> FindEndpoints(RouteValuesAddress address) { IEnumerable <OutboundMatchResult> matchResults = null; if (string.IsNullOrEmpty(address.RouteName)) { matchResults = _allMatchesLinkGenerationTree.GetMatches( address.ExplicitValues, address.AmbientValues); } else if (_namedMatchResults.TryGetValue(address.RouteName, out var namedMatchResults)) { matchResults = namedMatchResults; } if (matchResults == null || !matchResults.Any()) { return(Array.Empty <Endpoint>()); } return(matchResults .Select(matchResult => matchResult.Match) .Select(match => (MatcherEndpoint)match.Entry.Data)); }
public void SelectMultipleEntries_BothMatch_CriteriaSubset() { // Arrange var entries = new List<TreeRouteLinkGenerationEntry>(); var entry1 = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry1); var entry2 = CreateEntry(new { controller = "Store" }); entry2.Order = 1; entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { controller = "Store" }, ambientValues: new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context).Select(m => m.Entry).ToList(); // Assert Assert.Equal(entries, matches); }
public void SelectMultipleEntries_BothMatch_OrderedByTemplate() { // Arrange var entries = new List<AttributeRouteLinkGenerationEntry>(); var entry1 = CreateEntry(new { controller = "Store", action = "Buy" }); entry1.TemplateText = "a"; entries.Add(entry1); var entry2 = CreateEntry(new { controller = "Store", action = "Buy" }); entry2.TemplateText = "b"; entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context).Select(m => m.Entry).ToList(); // Assert Assert.Equal(entries, matches); }
public void SelectMultipleEntries_BothMatch_NonOverlappingCriteria() { // Arrange var entries = new List<AttributeRouteLinkGenerationEntry>(); var entry1 = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry1); var entry2 = CreateEntry(new { slug = "1234" }); entry2.Order = 1; entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext(new { controller = "Store", action = "Buy", slug = "1234" }); // Act var matches = tree.GetMatches(context).Select(m => m.Entry).ToList(); // Assert Assert.Equal(entries, matches); }
public void SelectMultipleEntries_OneDoesntMatch() { // Arrange var entries = new List<AttributeRouteLinkGenerationEntry>(); var entry1 = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry1); var entry2 = CreateEntry(new { controller = "Store", action = "Cart" }); entries.Add(entry2); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { controller = "Store" }, ambientValues: new { controller = "Store", action = "Buy" }); // Act var matches = tree.GetMatches(context); // Assert Assert.Same(entry1, Assert.Single(matches).Entry); }
public void SelectSingleEntry_MultipleCriteria_AmbientValue_NoMatch() { // Arrange var entries = new List<AttributeRouteLinkGenerationEntry>(); var entry = CreateEntry(new { controller = "Store", action = "Buy" }); entries.Add(entry); var tree = new LinkGenerationDecisionTree(entries); var context = CreateContext( values: new { controller = "Store" }, ambientValues: new { controller = "Store", action = "Cart" }); // Act var matches = tree.GetMatches(context); // Assert Assert.Empty(matches); }