November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
Hi
When I'm looking into the code we have explicity taken care of VirtualPathArguments.RouteValues in hash code calculation, would you like to test with latest version (11.20.2) or add a test procedure that can help us more. Thanks in advanced
Hi Shahram,
Thank you for checking that issue and let me try to explain how to reproduce it.
In my application I use IUrlResolver interface which uses UrlResolverArguments as one of the parameters.
Action name is passed in RouteValues property of UrlResolverArguments .
UrlResolverArguments parameter is converted to VirtualPathArguments in EPiServer.Web.Routing.UrlResolver
string IUrlResolver.GetUrl(
ContentReference contentLink,
string language,
UrlResolverArguments urlResolverArguments)
{
return this.GetUrl(contentLink, language, new VirtualPathArguments(urlResolverArguments));
}
string IUrlResolver.GetUrl(
UrlBuilder urlBuilderWithInternalUrl,
UrlResolverArguments arguments)
{
return this.GetUrl(urlBuilderWithInternalUrl, new VirtualPathArguments(arguments));
}
And VirtualPathArguments's constructor looks like
internal VirtualPathArguments(UrlResolverArguments urlArguments)
: this()
{
if (urlArguments == null)
return;
this.ContextMode = urlArguments.ContextMode;
this.ForceCanonical = urlArguments.ForceCanonical;
this.RouteValues = urlArguments.RouteValues != null ? new RouteValueDictionary(urlArguments.RouteValues) : new RouteValueDictionary();
this.ForceAbsolute = urlArguments.ForceAbsolute;
}
Action name is still in RouteValues property and Action property is empty by default.
And hash code is calculated using the following code:
private static readonly HashSet<string> _defaultRouteValues = new HashSet<string>((IEnumerable<string>) new string[3]
{
"node",
"action",
"language"
}, (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
public override int GetHashCode()
{
HashCodeCombiner hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add<string>(this.Action, (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
hashCodeCombiner.Add((object) this.ForceAbsolute);
hashCodeCombiner.Add((object) this.ForceCanonical);
hashCodeCombiner.Add((object) this.ValidateTemplate);
hashCodeCombiner.Add<string>(this.GetRouteValue(), (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
return hashCodeCombiner.CombinedHash;
}
private string GetRouteValue()
{
StringBuilder stringBuilder = new StringBuilder();
foreach (KeyValuePair<string, object> keyValuePair in (IEnumerable<KeyValuePair<string, object>>) this.RouteValues ?? Enumerable.Empty<KeyValuePair<string, object>>())
{
if (!VirtualPathArguments._defaultRouteValues.Contains(keyValuePair.Key))
stringBuilder.Append(keyValuePair.Key).Append(keyValuePair.Value);
}
return stringBuilder.ToString();
}
You can see that action name in RouteValues property is excluded by "if (!VirtualPathArguments._defaultRouteValues.Contains(keyValuePair.Key))" condition and action in Action property is empty.
So, if I call IUrlResolver.GetUrl to generate urls to the same page with action and without action in 2nd call I receive cached value with the results of the call which was the 1st one due to action name is not taken into account as a part of cache key.
Thanks for a very comprehensive report Borys Denysenko, this was very useful for troubleshooting this issue on our site.
Hi!
We have also encountered this bug. Can't see that it has been fixed yet? Are you planning on releasing a fix soon?
It seems that together with https://world.episerver.com/documentation/Release-Notes/ReleaseNote/?releaseNoteId=CMS-15789 was introduced a bug.
In IUrlResolver there is a method
UrlResolverArguments doesn't have a dedicated field for action in the page controller. So, action could be passed as a part of RouteValues dictionary.
In the implementation for UrlResolver UrlResolverArguments are converted to VirtualPathArguments.
And this VirtualPathArguments class already has a dedicated property for Action and that property is used in GetHashCode() method which is used in cache key generation.
However action from RouteValues dictionary is not copied to Action property and during hash code calculation there is a logic which excludes node, action and language route parametwers from hash code calculation.
So, my question is if it's a kown behaviour and custom actions are no longer supported or it's a bug and I just need to wait for a fix?
Meanwhile, I created an overloaded implementation for UrlResolver
But such customizations is not something which I'd like to see and maintain during EPiServer upgrades in my project:)