November Happy Hour will be moved to Thursday December 5th.
November Happy Hour will be moved to Thursday December 5th.
Looks like problem is inside ExistingActionRouteConstraint constraint.
Reflected code:
public virtual bool Match(Route route, SegmentContext routingContext, string parameterName)
{
IContent content;
string str = routingContext.RouteData.Values["action"] as string;
if (string.IsNullOrEmpty(str))
{
return true;
}
if (!this._mapContentRouteParameters.ContentLoader.TryGet<IContent>(routingContext.RoutedContentLink, LanguageSelector.MasterLanguage(), out content))
{
return false;
}
TemplateModel model = this._mapContentRouteParameters.TemplateResolver.Resolve(HttpContext.Current.ContextBaseOrNull(), content, TemplateTypeCategories.MvcController, routingContext.ContextMode);
if ((model != null) && (model.TemplateType != null))
{
return this._actions.GetControllerActions(model.TemplateType).Contains(str);
}
string a = (route.Defaults[RoutingConstants.ActionKey] as string) ?? "index";
return string.Equals(a, str, StringComparison.OrdinalIgnoreCase);
}
It does action lookup not on actual routed data, but on "parent" content.
routingContext.RoutedContentLink
Is it a valid behaviour?
If I add "second" (with same name) STUB action on "parent" cms-content controller, it starts working:)
Looks like a bug.
Here is workaroung I've found:
public class Global : EPiServer.Global
{
protected override void RegisterRoutes(RouteCollection routes)
{
base.RegisterRoutes(routes);
//go through content routes and apply constraint fix
FixExistingActionConstraint(routes);
}
private static void FixExistingActionConstraint(RouteCollection routes)
{
foreach (var route in routes)
{
var contentRoute = route as ContentRoute;
if (contentRoute != null && contentRoute.Constraints.ContainsKey(RoutingConstants.ActionKey))
{
var original = contentRoute.Constraints[RoutingConstants.ActionKey] as ExistingActionRouteConstraint;
if (original != null)
{
//replace constraint with custom wrapper
contentRoute.Constraints[RoutingConstants.ActionKey] = new ExistingActionRouteConstraintWrapper(original);
}
}
}
}
}
public class ExistingActionRouteConstraintWrapper : IContentRouteConstraint
{
private readonly ExistingActionRouteConstraint original;
public ExistingActionRouteConstraintWrapper(ExistingActionRouteConstraint original)
{
this.original = original;
}
public bool Match(Route route, SegmentContext segmentContext, string parameterName)
{
//try to minify "fix" influence and process only "my" partials routes (objects are marked with IVirtualPage interface)
if (segmentContext.RoutedObject is IVirtualPage)
{
return true;
}
return original.Match(route, segmentContext, parameterName);
}
}
Does it make sense? Any pitfalls?
Hi and thanks for the detailed explanation!
I agree that this should be considered a bug. That is if a partial router has routed to something the validation should be against that controller (if any) and not the "original" cms content.
I have reported a bug for this.
Fixed in 7.6.5, release note: http://world.episerver.com/Documentation/Release-Notes/ReleaseNote/?releaseNoteId=112923
Does partial routing supports {action} segment?
I did following: