Opticon Stockholm is on Tuesday September 10th, hope to see you there!
Opticon Stockholm is on Tuesday September 10th, hope to see you there!
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: