Skip to content

Commit 2d13d54

Browse files
committed
Merge branch 'patch-336' into dev
2 parents fcedd7b + 5d44271 commit 2d13d54

File tree

3 files changed

+69
-15
lines changed

3 files changed

+69
-15
lines changed

src/MvcSiteMapProvider/MvcSiteMapProvider/SiteMap.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Linq;
45
using System.Web;
56
using System.Web.UI;
@@ -280,6 +281,13 @@ public virtual bool EnableLocalization
280281
get { return this.siteMapSettings.EnableLocalization; }
281282
}
282283

284+
/// <summary>
285+
/// Retrieves a <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> object that represents the page at the specified URL.
286+
/// </summary>
287+
/// <param name="rawUrl">A URL that identifies the page for which to retrieve a <see cref="T:MvcSiteMapProvider.ISiteMapNode"/>.</param>
288+
/// <returns>A <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> that represents the page identified by rawURL; otherwise, <b>null</b>,
289+
/// if no corresponding <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> is found or if security trimming is enabled and the
290+
/// <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> cannot be returned for the current user.</returns>
283291
public virtual ISiteMapNode FindSiteMapNode(string rawUrl)
284292
{
285293
if (rawUrl == null)
@@ -296,16 +304,35 @@ public virtual ISiteMapNode FindSiteMapNode(string rawUrl)
296304
// and the current URL will be the absolute URL that is passed.
297305
var publicFacingUrl = this.urlPath.GetPublicFacingUrl(this.HttpContext);
298306
var currentUrl = new Uri(publicFacingUrl, rawUrl);
307+
308+
// Search the internal dictionary for the URL that is registered manually.
299309
var node = this.FindSiteMapNodeFromUrl(currentUrl.PathAndQuery, currentUrl.AbsolutePath, currentUrl.Host, HttpContext.CurrentHandler);
300310

311+
// Search for the URL by creating a context based on the new URL and matching route values.
312+
if (node == null)
313+
{
314+
// Create a TextWriter with null stream as a backing stream
315+
// which doesn't consume resources
316+
using (var nullWriter = new StreamWriter(Stream.Null))
317+
{
318+
// Create a new HTTP context using the current URL.
319+
var currentUrlHttpContext = this.mvcContextFactory.CreateHttpContext(null, currentUrl, nullWriter);
320+
321+
// Find node for the passed-in URL using the new HTTP context. This will do a
322+
// match based on route values and/or query string values.
323+
node = this.FindSiteMapNodeFromMvc(currentUrlHttpContext);
324+
}
325+
}
326+
301327
return this.ReturnNodeIfAccessible(node);
302328
}
303329

304330
/// <summary>
305331
/// Retrieves a <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> object that represents the currently requested page using the current <see cref="T:System.Web.HttpContext"/> object.
306332
/// </summary>
307333
/// <returns>
308-
/// A <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> that represents the currently requested page; otherwise, null, if no corresponding <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> can be found in the <see cref="T:MvcSiteMapProvider.SiteMapNode"/> or if the page context is null.
334+
/// A <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> that represents the currently requested page; otherwise, <b>null</b>,
335+
/// if no corresponding <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> can be found in the <see cref="T:MvcSiteMapProvider.SiteMapNode"/> or if the page context is null.
309336
/// </returns>
310337
public virtual ISiteMapNode FindSiteMapNodeFromCurrentContext()
311338
{
@@ -322,6 +349,13 @@ public virtual ISiteMapNode FindSiteMapNode(ControllerContext context)
322349
return this.FindSiteMapNode(context.HttpContext);
323350
}
324351

352+
/// <summary>
353+
/// Retrieves a <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> object based on a specified key.
354+
/// </summary>
355+
/// <param name="key">A lookup key with which a <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> instance is created.</param>
356+
/// <returns>A <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> that represents the page identified by key; otherwise, <b>null</b>,
357+
/// if no corresponding <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> is found or if security trimming is enabled and the
358+
/// <see cref="T:MvcSiteMapProvider.ISiteMapNode"/> cannot be returned for the current user. The default is null.</returns>
325359
public virtual ISiteMapNode FindSiteMapNodeFromKey(string key)
326360
{
327361
ISiteMapNode node = null;

src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Html/MenuHelper.cs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, bool startFro
159159
/// <returns>Html markup</returns>
160160
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, bool startFromCurrentNode, bool startingNodeInChildLevel, bool showStartingNode, SourceMetadataDictionary sourceMetadata)
161161
{
162-
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap) : helper.SiteMap.RootNode;
162+
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap, true) : helper.SiteMap.RootNode;
163163
return Menu(helper, startingNode, startingNodeInChildLevel, showStartingNode, Int32.MaxValue, false, sourceMetadata);
164164
}
165165

@@ -204,7 +204,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, bool startFro
204204
/// <returns>Html markup</returns>
205205
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, bool startFromCurrentNode, bool startingNodeInChildLevel, bool showStartingNode, bool visibilityAffectsDescendants, SourceMetadataDictionary sourceMetadata)
206206
{
207-
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap) : helper.SiteMap.RootNode;
207+
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap, true) : helper.SiteMap.RootNode;
208208
return Menu(helper, null, startingNode, startingNodeInChildLevel, showStartingNode, Int32.MaxValue, false, visibilityAffectsDescendants, sourceMetadata);
209209
}
210210

@@ -249,7 +249,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingN
249249
/// <returns>Html markup</returns>
250250
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingNodeLevel, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, SourceMetadataDictionary sourceMetadata)
251251
{
252-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
252+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
253253
if (startingNode == null)
254254
{
255255
return MvcHtmlString.Empty;
@@ -301,7 +301,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingN
301301
/// <returns>Html markup</returns>
302302
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingNodeLevel, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, bool visibilityAffectsDescendants, SourceMetadataDictionary sourceMetadata)
303303
{
304-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
304+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
305305
if (startingNode == null)
306306
{
307307
return MvcHtmlString.Empty;
@@ -435,7 +435,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingN
435435
/// <returns>Html markup</returns>
436436
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingNodeLevel, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, SourceMetadataDictionary sourceMetadata)
437437
{
438-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
438+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
439439
if (startingNode == null)
440440
{
441441
return MvcHtmlString.Empty;
@@ -490,7 +490,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingN
490490
/// <returns>Html markup</returns>
491491
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, int startingNodeLevel, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, bool visibilityAffectsDescenants, SourceMetadataDictionary sourceMetadata)
492492
{
493-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
493+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
494494
if (startingNode == null)
495495
{
496496
return MvcHtmlString.Empty;
@@ -791,7 +791,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templa
791791
/// <returns>Html markup</returns>
792792
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, bool startFromCurrentNode, bool startingNodeInChildLevel, bool showStartingNode, SourceMetadataDictionary sourceMetadata)
793793
{
794-
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap) : helper.SiteMap.RootNode;
794+
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap, true) : helper.SiteMap.RootNode;
795795
return Menu(helper, templateName, startingNode, startingNodeInChildLevel, showStartingNode, Int32.MaxValue, false, sourceMetadata);
796796
}
797797

@@ -839,7 +839,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templa
839839
/// <returns>Html markup</returns>
840840
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, bool startFromCurrentNode, bool startingNodeInChildLevel, bool showStartingNode, bool visibilityAffectsDescendants, SourceMetadataDictionary sourceMetadata)
841841
{
842-
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap) : helper.SiteMap.RootNode;
842+
ISiteMapNode startingNode = startFromCurrentNode ? GetCurrentNode(helper.SiteMap, true) : helper.SiteMap.RootNode;
843843
return Menu(helper, templateName, startingNode, startingNodeInChildLevel, showStartingNode, Int32.MaxValue, false, visibilityAffectsDescendants, sourceMetadata);
844844
}
845845

@@ -887,7 +887,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templa
887887
/// <returns>Html markup</returns>
888888
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, int startingNodeLevel, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, SourceMetadataDictionary sourceMetadata)
889889
{
890-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
890+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
891891
if (startingNode == null)
892892
{
893893
return MvcHtmlString.Empty;
@@ -986,7 +986,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templa
986986
/// <returns>Html markup</returns>
987987
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, int startingNodeLevel, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, SourceMetadataDictionary sourceMetadata)
988988
{
989-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
989+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
990990
if (startingNode == null)
991991
{
992992
return MvcHtmlString.Empty;
@@ -1047,7 +1047,7 @@ public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templa
10471047
/// <returns>Html markup</returns>
10481048
public static MvcHtmlString Menu(this MvcSiteMapHtmlHelper helper, string templateName, int startingNodeLevel, bool startingNodeInChildLevel, bool showStartingNode, int maxDepth, bool allowForwardSearch, bool drillDownToCurrent, bool visibilityAffectsDescendants, SourceMetadataDictionary sourceMetadata)
10491049
{
1050-
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap), startingNodeLevel, allowForwardSearch);
1050+
ISiteMapNode startingNode = GetStartingNode(GetCurrentNode(helper.SiteMap, true), startingNodeLevel, allowForwardSearch);
10511051
if (startingNode == null)
10521052
{
10531053
return MvcHtmlString.Empty;
@@ -1332,6 +1332,20 @@ private static MenuHelperModel BuildModel(MvcSiteMapHtmlHelper helper, SourceMet
13321332
/// <param name="selectedSiteMapProvider">the current MVC Site Map Provider</param>
13331333
/// <returns></returns>
13341334
public static ISiteMapNode GetCurrentNode(ISiteMap selectedSiteMap)
1335+
{
1336+
return GetCurrentNode(selectedSiteMap, false);
1337+
}
1338+
1339+
/// <summary>
1340+
/// This determines the deepest node matching the current HTTP context, so if the current URL describes a location
1341+
/// deeper than the site map designates, it will determine the closest parent to the current URL and return that
1342+
/// as the current node. This allows menu relevance when navigating deeper than the sitemap structure designates, such
1343+
/// as when navigating to MVC actions, which are not shown in the menus
1344+
/// </summary>
1345+
/// <param name="selectedSiteMapProvider">the current MVC Site Map Provider</param>
1346+
/// <param name="returnRootNodeIfNotFound">whether to return the root node if the current node is null</param>
1347+
/// <returns></returns>
1348+
public static ISiteMapNode GetCurrentNode(ISiteMap selectedSiteMap, bool returnRootNodeIfNotFound)
13351349
{
13361350
// get the node matching the current URL location
13371351
var currentNode = selectedSiteMap.CurrentNode;
@@ -1341,11 +1355,12 @@ public static ISiteMapNode GetCurrentNode(ISiteMap selectedSiteMap)
13411355
if (currentNode == null)
13421356
{
13431357
var url = HttpContext.Current.Request.Url.LocalPath;
1358+
var queryString = HttpContext.Current.Request.Url.Query;
13441359

13451360
while (url.Length > 0)
13461361
{
13471362
// see if we can find a matching node
1348-
currentNode = selectedSiteMap.FindSiteMapNode(url);
1363+
currentNode = selectedSiteMap.FindSiteMapNode(url + queryString);
13491364

13501365
// if we get a hit, stop
13511366
if (currentNode != null) break;
@@ -1357,6 +1372,13 @@ public static ISiteMapNode GetCurrentNode(ISiteMap selectedSiteMap)
13571372
}
13581373
}
13591374

1375+
// If the current node is still null, return the root node.
1376+
// This is the same way the SiteMap.FindSiteMapNode(rawUrl) method worked in v3.
1377+
if (currentNode == null && returnRootNodeIfNotFound)
1378+
{
1379+
currentNode = selectedSiteMap.RootNode;
1380+
}
1381+
13601382
return currentNode;
13611383
}
13621384

src/MvcSiteMapProvider/MvcSiteMapProvider/Web/Mvc/MvcContextFactory.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ protected virtual HttpContextBase CreateHttpContext(ISiteMapNode node)
2929

3030
public virtual HttpContextBase CreateHttpContext(ISiteMapNode node, Uri uri, TextWriter writer)
3131
{
32-
if (node == null)
33-
throw new ArgumentNullException("node");
3432
if (uri == null)
3533
throw new ArgumentNullException("uri");
3634
if (writer == null)

0 commit comments

Comments
 (0)