-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrading from MVC5 4.4.6 -> 4.4.8 throws KeyNotFoundException #268
Comments
I just started getting this stack-trace as well when requesting 'sitemap.xml', and |
Thanks. Actually, it is an issue with improperly guarding against optional keys in the FilteredSiteMapNodeVisibilityProvider. This issue is already fixed in my local codebase, I am just working on getting some other issues fixed before releasing it. |
In the meantime, you can work around this problem by putting the fixed FilteredSiteMapNodeVisibilityProvider into your own project and adjusting the namespace accordingly. Then all you have to do is change the namespace back when the patch is released. I could also use some feedback on the fix (and the new "named" HTML helper feature that caused it to break) if there is still something awry here. using System;
using System.Collections.Generic;
using System.Web;
namespace MvcSiteMapProvider
{
/// <summary>
/// Filtered SiteMapNode Visibility Provider.
///
/// Rules are parsed left-to-right, first match wins. Asterisk can be used to match any control. Exclamation mark can be used to negate a match.
/// </summary>
public class FilteredSiteMapNodeVisibilityProvider
: SiteMapNodeVisibilityProviderBase
{
#region ISiteMapNodeVisibilityProvider Members
/// <summary>
/// Determines whether the node is visible.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="sourceMetadata">The source metadata.</param>
/// <returns>
/// <c>true</c> if the specified node is visible; otherwise, <c>false</c>.
/// </returns>
public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
// Is a visibility attribute specified?
string visibility = string.Empty;
if (node.Attributes.ContainsKey("visibility"))
{
visibility = node.Attributes["visibility"].GetType().Equals(typeof(string)) ? node.Attributes["visibility"].ToString() : string.Empty;
}
if (string.IsNullOrEmpty(visibility))
{
return true;
}
visibility = visibility.Trim();
string name = string.Empty;
string htmlHelper = string.Empty;
if (sourceMetadata.ContainsKey("name"))
{
name = Convert.ToString(sourceMetadata["name"]);
}
if (sourceMetadata.ContainsKey("HtmlHelper"))
{
name = Convert.ToString(sourceMetadata["HtmlHelper"]);
}
// Check for the source HtmlHelper or given name. If neither are configured,
// then always visible.
if (string.IsNullOrEmpty(name) && string.IsNullOrEmpty(htmlHelper))
{
return true;
}
// Chop off the namespace
htmlHelper = htmlHelper.Substring(htmlHelper.LastIndexOf(".") + 1);
// Get the keywords
var visibilityKeywords = visibility.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
// All set. Now parse the visibility variable.
foreach (string visibilityKeyword in visibilityKeywords)
{
if (visibilityKeyword == htmlHelper || visibilityKeyword == name || visibilityKeyword == "*")
{
return true;
}
else if (visibilityKeyword == "!" + htmlHelper || visibilityKeyword == "!" + name || visibilityKeyword == "!*")
{
return false;
}
}
// Still nothing? Then it's OK!
return true;
}
#endregion
}
} |
Hey NightOwl, I did a quick pre-eliminary test on the new FilteredSiteMapNodeVisibilityProvider you posted.
|
Try this instead. The name variable was being overwritten by the HtmlHelper value. using System;
using System.Collections.Generic;
using System.Web;
namespace MvcSiteMapProvider
{
/// <summary>
/// Filtered SiteMapNode Visibility Provider.
///
/// Rules are parsed left-to-right, first match wins. Asterisk can be used to match any control. Exclamation mark can be used to negate a match.
/// </summary>
public class FilteredSiteMapNodeVisibilityProvider
: SiteMapNodeVisibilityProviderBase
{
#region ISiteMapNodeVisibilityProvider Members
/// <summary>
/// Determines whether the node is visible.
/// </summary>
/// <param name="node">The node.</param>
/// <param name="sourceMetadata">The source metadata.</param>
/// <returns>
/// <c>true</c> if the specified node is visible; otherwise, <c>false</c>.
/// </returns>
public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
{
// Is a visibility attribute specified?
string visibility = string.Empty;
if (node.Attributes.ContainsKey("visibility"))
{
visibility = node.Attributes["visibility"].GetType().Equals(typeof(string)) ? node.Attributes["visibility"].ToString() : string.Empty;
}
if (string.IsNullOrEmpty(visibility))
{
return true;
}
visibility = visibility.Trim();
string name = string.Empty;
string htmlHelper = string.Empty;
if (sourceMetadata.ContainsKey("name"))
{
name = Convert.ToString(sourceMetadata["name"]);
}
if (sourceMetadata.ContainsKey("HtmlHelper"))
{
htmlHelper = Convert.ToString(sourceMetadata["HtmlHelper"]);
}
// Check for the source HtmlHelper or given name. If neither are configured,
// then always visible.
if (string.IsNullOrEmpty(name) && string.IsNullOrEmpty(htmlHelper))
{
return true;
}
// Chop off the namespace
htmlHelper = htmlHelper.Substring(htmlHelper.LastIndexOf(".") + 1);
// Get the keywords
var visibilityKeywords = visibility.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
// All set. Now parse the visibility variable.
foreach (string visibilityKeyword in visibilityKeywords)
{
if (visibilityKeyword == htmlHelper || visibilityKeyword == name || visibilityKeyword == "*")
{
return true;
}
else if (visibilityKeyword == "!" + htmlHelper || visibilityKeyword == "!" + name || visibilityKeyword == "!*")
{
return false;
}
}
// Still nothing? Then it's OK!
return true;
}
#endregion
}
} |
ah, I see. I didn't notice that. |
I got the same problem with the version 4.6.17 with MVC 5.2.2. Could you please check it again? Thanks! |
Could you post the stack trace and your node configuration? |
a part of stack trace: Node Config: my CustomSiteMapVisibilityProvider: |
Since attributes is an // Is a visibility attribute specified?
string visibility = string.Empty;
if (node.Attributes.ContainsKey("visibility"))
{
visibility = node.Attributes["visibility"].GetType().Equals(typeof(string)) ? node.Attributes["visibility"].ToString() : string.Empty;
}
if (string.IsNullOrEmpty(visibility))
{
return true;
}
visibility = visibility.Trim(); |
thanks. it works now! |
Will try to track down more details. For now, here is the stacktrace when trying to request sitemap.xml file. Reverting back to 4.4.6 fixes the issue for now.
[KeyNotFoundException: The given key was not present in the dictionary.]
System.Collections.Generic.Dictionary
2.get_Item(TKey key) +14379623 MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider.IsVisible(ISiteMapNode node, IDictionary
2 sourceMetadata) +400MvcSiteMapProvider.RequestCacheableSiteMapNode.IsVisible(IDictionary
2 sourceMetadata) +144 MvcSiteMapProvider.Web.Mvc.XmlSiteMapResult.ShouldNodeRender(ISiteMapNode node, ControllerContext context) +66 MvcSiteMapProvider.Web.Mvc.<FlattenHierarchy>d__f.MoveNext() +152 MvcSiteMapProvider.Web.Mvc.<FlattenHierarchy>d__f.MoveNext() +568 MvcSiteMapProvider.Web.Mvc.<FlattenHierarchy>d__f.MoveNext() +568 MvcSiteMapProvider.Web.Mvc.<FlattenHierarchy>d__f.MoveNext() +568 MvcSiteMapProvider.Web.Mvc.<FlattenHierarchy>d__f.MoveNext() +568 MvcSiteMapProvider.Web.Mvc.<FlattenHierarchy>d__f.MoveNext() +568 MvcSiteMapProvider.Web.Mvc.XmlSiteMapResult.ExecuteResult(ControllerContext context) +584 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList
1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +109System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList
1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList
1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList
1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList
1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList
1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +890 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList
1 filters, ActionResult actionResult) +97System.Web.Mvc.Async.<>c__DisplayClass21.b__1e(IAsyncResult asyncResult) +241
System.Web.Mvc.Controller.b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult) +111 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53 System.Web.Mvc.Async.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult) +19System.Web.Mvc.MvcHandler.b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +51
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +111
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
The text was updated successfully, but these errors were encountered: